I have encrypted a string with RSA public key using the Windows Crypto API, but I'm not able to decrypt it using the RSA private key with Go. The following code is the encryption using C++
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;
DWORD dwPublicKeyLen = 0;
DWORD dwDataLen = 0;
DWORD dwEncryptedLen = 0;
BYTE* pbPublicKey = NULL;
BYTE* pbData = NULL;
HANDLE hPublicKeyFile = NULL;
HANDLE hEncryptedFile = NULL;
HANDLE hPlainFile = NULL;
DWORD lpNumberOfBytesWritten = 0;
BYTE derPubKey[2048];
DWORD derPubKeyLen = 2048;
CERT_PUBLIC_KEY_INFO* publicKeyInfo = NULL;
DWORD publicKeyInfoLen = 0;
HANDLE hFile = NULL;
if (!CryptAcquireContextW(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
printf("CryptAcquireContext error 0x%x\n", GetLastError());
return 1;
}
std::string pempubkeyS = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNoGP0DHZA9RyZlQETr3NGr6hoxn9oHFiFeJwCUooz+qP38vQ53Cs7VtisfEl/FmkwRCz9l0bKU9MZ00Z1/WLTa+48dqGMNL2+um1za0Z0fyxXmYEwy3zvFaswtgzHfXlN+pcay6DsaBXXSvQpC6sz50DvcIw4YsMPqSSBk++LSQIDAQAB";
std::wstring pempubkey = std::wstring(pempubkeyS.begin(), pempubkeyS.end());
if (!CryptStringToBinaryW(pempubkey.c_str(), 0, CRYPT_STRING_BASE64, derPubKey, &derPubKeyLen, NULL, NULL))
{
printf("CryptStringToBinary failed. Err: %d\n", GetLastError());
return -1;
}
/*
* Decode from DER format to CERT_PUBLIC_KEY_INFO
*/
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPubKey, derPubKeyLen, CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen))
{
printf("CryptDecodeObjectEx 1 failed. Err: %x\n", GetLastError());
return -1;
}
/*
* Import the public key using the context
*/
if (!CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING, publicKeyInfo, &hKey))
{
printf("CryptImportPublicKeyInfo failed. error: %d\n", GetLastError());
return -1;
}
LocalFree(publicKeyInfo);
std::string cleartext = "This is a test!";
int len = cleartext.length();
// Get lenght for encrypted data
if (!CryptEncrypt(hKey, NULL, TRUE, CRYPT_OAEP, NULL, &dwEncryptedLen, 0))
{
// Error
printf("CryptEncrypt error 0x%x\n", GetLastError());
return 1;
}
cleartext.resize(len + dwEncryptedLen);
// Encrypt data
if (!CryptEncrypt(hKey, NULL, TRUE, 0, (BYTE*)&cleartext[0], &dwDataLen, dwEncryptedLen))
{
// Error
printf("CryptEncrypt error 0x%x\n", GetLastError());
return 1;
}
std::string cleartextbase64 = "";
cleartext.resize(dwDataLen);
Base64Encode(cleartext, &cleartextbase64);
std::cout << cleartextbase64 << std::endl;
// HkCebflDgmxJ33hmLTrqGsPyyyPKP74MePHedzrB8jiI6AOJhIw06WD93HggIRCgm/A6CqRYYgHe749Z6uTAqsh2dY9bvGMfNGLAQ7g5YFYlK+MWUEyFB1yRH6cDJKloP+J1UhIibGa3R+cwY9EHfDNCZfeTL0zYPHFKun9OBZ0=
The following code is the decryption using Go
keyRaw, err := base64.StdEncoding.DecodeString("LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWHdJQkFBS0JnUUROb0dQMERIWkE5UnlabFFFVHIzTkdyNmhveG45b0hGaUZlSndDVW9veitxUDM4dlE1CjNDczdWdGlzZkVsL0Zta3dSQ3o5bDBiS1U5TVowMFoxL1dMVGErNDhkcUdNTkwyK3VtMXphMFowZnl4WG1ZRXcKeTN6dkZhc3d0Z3pIZlhsTitwY2F5NkRzYUJYWFN2UXBDNnN6NTBEdmNJdzRZc01QcVNTQmsrK0xTUUlEQVFBQgpBb0dCQUtia3J6dTlnWjFuVkRjelFSU0JLc2NNZTF2UEFFbTMrQUVjeTBMM1MwUzFBYkNWZUxRZGh0azZ1OUlECmJvTy81TkJRQlZRdUhEN0xtbU16bjlUVVBBaDRRWUxSUGxVQWFRVTM5eThxTDdIbWdoR0lRN0JrZWxPS3hYQjkKNEtBUTFiRksxZ2hwZEFEeDhtTVh5SWZjTG5JSnRJT1ZibWloRjNxdUt4UzBuRlNCQWtFQTE2TlRPeWpKWW9aUQpoaG9XSFJHcXlDU1ZKbGRwaUxSaENxNFAwRVNER2NaTFRlMVVSVXRhRWlZeHk4cGdoQmkxVHpkU1ZVM3h2bk10ClZOeEtoc0tHblFKQkFQUWRXUzdXYUFvWHJYODZ1alJNd1VxcW4zcVJwMWVGM29hdzZ0TWtWZHpDcTZoRzlyRjUKU2pzekhjUkJ4WlNyeklWeXN1T2pBYS9ta0JtbmZtV3Y0WjBDUVFDMy9DMXVvMzA0S0J1YVg3V1FkZHQrU3VCTApSM2ZPNFFDUGFUWXEzOW52NnVXamhxUkpQMktKYTdjL0J0eFV1UFF4czZUM0RicitZUzFEWTNYZkJ5aHRBa0VBCjZwZ05yYkpFZDNaN3VDb3k2YkhkaTZqZTdBWnZuKys1Z3cwZ0RscjczTlNEN0lxTjVzNGQ1VGhoWWNxbld4R2kKMFpnQmpEdUprb1pyY3d3QXJ5NVFEUUpCQUt0Uk1LbmJnZFR3TWRQbTMwQWErQk50UGNwckN4VXFFWHpCT2lZSQpXVVBZOTBCdmxGSzkvK3VVWktOQzhoK1Ntc2F3ekFaKzZUVzlEWUFuSWZ1UkExZz0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K")
if err != nil {
panic(err)
}
block, _ := pem.Decode(keyRaw)
configPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
panic(err)
}
encodedEncrypted := `HkCebflDgmxJ33hmLTrqGsPyyyPKP74MePHedzrB8jiI6AOJhIw06WD93HggIRCgm/A6CqRYYgHe749Z6uTAqsh2dY9bvGMfNGLAQ7g5YFYlK+MWUEyFB1yRH6cDJKloP+J1UhIibGa3R+cwY9EHfDNCZfeTL0zYPHFKun9OBZ0=`
cipherText, err := base64.StdEncoding.DecodeString(encodedEncrypted)
if err != nil {
panic(err)
}
cleartextMessage, err := rsa.DecryptPKCS1v15(rand.Reader, configPrivateKey, cipherText)
//cleartextMessage, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, configPrivateKey, cipherText, nil)
if err != nil {
panic(err) // panic: crypto/rsa: decryption error
}
fmt.Println(string(cleartextMessage))
As you can see I've got a panic: crypto/rsa: decryption error . Any ideas? Thanks in advance!
There are the following issues:
The 6th parameter contains on entry the plaintext length (and on exit the ciphertext length). Because the 6th parameter on entry<\/em> is
0<\/code> , an empty<\/em> string is encrypted.
This is probably not intended and must be fixed accordingly!
<\/li>
Therefore, in the Go code,
rsa.DecryptPKCS1v15()<\/code> must be used, which is currently the case (
rsa.DecryptOAEP()<\/code> is commented out).
Note that when determining the length of the encrypted data (1st
CryptEncrypt()<\/code> call), the
CRYPT_OAEP<\/code> flag is set, which is inconsistent, but probably has no effect.
This point has already been addressed in the comments.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.