我想将 1990 年的旧 C 代码重写为 Go。但这里的痛点是密码算法的迁移。我有以下 Cpp 代码,可以成功地将密码解密为纯文本。
#include <windows.h>
#include <wincrypt.h>
#include <string>
#include <iostream>
using namespace std;
int main() {
auto name = L"aaaa";
HCRYPTPROV hProv;
if (!CryptAcquireContext(&hProv, name, MS_DEF_PROV, PROV_RSA_FULL, 0) &&
!CryptAcquireContextW(&hProv, name, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET) &&
!CryptAcquireContextW(&hProv, name, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET) &&
!CryptAcquireContextW(&hProv, name, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) {
cout << "fail" << endl;
exit(1);
}
HCRYPTHASH hHash;
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
cout << "fail" << endl;
exit(1);
}
const BYTE* pwd = reinterpret_cast<const BYTE*>("-+ REDACTED +-");
if (!CryptHashData(hHash, pwd, 14, 0)) {
cout << "md5 failure" << endl;
exit(1);
}
HCRYPTKEY hKey;
if (!CryptDeriveKey(hProv, CALG_RC2, hHash, 0, &hKey)) {
cout << "failure" << endl;
exit(1);
}
unsigned char cipher[] = {52, 54, 253, 199, 131, 110, 202, 15, 185, 107, 71, 244, 150, 171, 220, 6, 183, 86, 234, 252, 242, 84, 156, 200};
DWORD len = 24;
if (!CryptDecrypt(hKey, 0, TRUE, 0, cipher, &len)) {
printf("%x\n", GetLastError());
exit(1);
}
for (int i = 0; i < len; i++) {
printf("%d, ", cipher[i]);
}
}
我有以下 Go 代码:
package main
import (
"crypto/md5"
"fmt"
"github.com/dgryski/go-rc2"
)
func main() {
pwd := "-+ REDACTED +-"
hash := md5.Sum([]byte(pwd))
alg, err := rc2.New(hash[:], 128)
if err != nil {
panic(err)
}
cipher := []byte{52, 54, 253, 199, 131, 110, 202, 15, 185, 107, 71, 244, 150, 171, 220, 6, 183, 86, 234, 252, 242, 84, 156, 200}
result := []byte{}
dst := make([]byte, 8)
for i := 8; i <= len(cipher); i += 8 {
alg.Decrypt(dst, cipher[i-8:i])
result = append(result, dst...)
}
fmt.Println(result)
}
在线运行:https://go.dev/play/p/veRMRShmtnw
它们的输出是不同的。而CPP版本可以正确解密。
我的假设是,“CryptDeriveKey”使用附加值强化初始哈希密码,结果加密密钥被更改。
以下代码不正确,因为最后一个块未解密,并且
result
的长度为16
字节。
for i := 8; i < len(cipher); i += 8 {
alg.Decrypt(dst, cipher[i-8:i])
result = append(result, dst...)
}
将其替换为以下代码并重试:
for i := 0; i < len(cipher); i += 8 {
alg.Decrypt(dst, cipher[i:i+8])
result = append(result, dst...)
}