I want to rewrite old C code from 1990 to Go. But the pain point here is migration of cryptographic algorithms. I have the following Cpp code that successfully decrypts the cipher into plain text.
#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]);
}
}
and I have the following Go code:
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)
}
run online: https://go.dev/play/p/veRMRShmtnw
The output of them are different. While the CPP version able to decrypt correctly.
My assumption is, that `CryptDeriveKey` harden the initial hash password with additional values and as a result encryption key gets altered.