C++用BCrypt.lib加密,C#用RSACryptoServiceProvider解密报参数错误
问题:.NET RSA解密BCrypt加密数据时抛出“参数不正确”异常
我有一个基于.NET(C#)编写的Windows服务,以及一个C编写的库。.NET端通过RSACryptoServiceProvider生成RSA公钥/私钥对,将公钥信息传递给C端;C++端导入该公钥后,使用BCrypt.lib库对数据加密,将结果编码为Base64格式返回给.NET服务。目前.NET端调用Decrypt()方法解密时,抛出异常:CryptographicException: '参数不正确'。推测可能是编码或字节序问题,已尝试将Base64转为字节数组、反转数组,但均无效。
.NET端代码
var rsa = RSACryptoServiceProvider.Create(1024); var publicKey = rsa.ToXmlString(false); var encryptedData = Convert.FromBase64String(GetEncryptedDataFromCPP(publicKey)); //Array.Reverse(encryptedData); byte[] decryptedData = rsa.Decrypt(encryptedData, RSAEncryptionPadding.Pkcs1); // 抛出CryptographyException: 参数不正确 var decryptedDataValue = Encoding.UTF8.GetString(decryptedData);
C++端代码
VOID GetEncryptedDataFromCPP(publicKey) { BYTE* pbPublicKey = NULL; DWORD cbExp = 3; DWORD cbModulus = 128; DWORD cbKey = cbExp + sizeof(BCRYPT_RSAKEY_BLOB) + cbModulus; BCRYPT_RSAKEY_BLOB* pRsaBlob; PBYTE pbCurrent; //**假设已从XML字符串中提取模数和指数并赋值如下** std::string modulus = "3XCSEveWJ3Mp41g5VxcmmlCYDL5X+VUX1ULOIl8TdsEu6bbS/Ho0ofBgAwglCrbRgAjm7ZW+EivEVLZRx5FVsEYqGX12fFZSn84Ye6D2rUYqvwR0kBE8MBCdirqg3gXAlmuIgxucWcxiT9NDTaC67Awe9yyQv3fJ2uPeOEXw0LU="; std::string exponent = "AQAB"; std::vector<BYTE> PubKeyModulus_bin = base64_decode(modulus); std::vector<BYTE> PubKeyExp_bin = base64_decode(exponent); pbPublicKey = (BYTE*)CoTaskMemAlloc(cbKey); ZeroMemory(pbPublicKey, cbKey); pRsaBlob = (BCRYPT_RSAKEY_BLOB*)(pbPublicKey); // 构造公钥Blob头部 pRsaBlob->Magic = BCRYPT_RSAPUBLIC_MAGIC; pRsaBlob->BitLength = 128*8; pRsaBlob->cbPublicExp = 3; pRsaBlob->cbModulus = 128; pRsaBlob->cbPrime1 = 0; pRsaBlob->cbPrime2 = 0; BCRYPT_ALG_HANDLE hAlgorithm = NULL; BCRYPT_KEY_HANDLE hKey = NULL; NTSTATUS status; BYTE textData[] = "test"; DWORD textDataSize = sizeof(textData); status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_RSA_ALGORITHM, NULL, 0); if (!NT_SUCCESS(status)) { printf("Failed to get algorithm provider..status : %08x\n", status); } status = BCryptImportKeyPair(hAlgorithm, NULL, BCRYPT_RSAPUBLIC_BLOB, &hKey, (PUCHAR)pbPublicKey, cbKey,//155, BCRYPT_NO_KEY_VALIDATION); if (!NT_SUCCESS(status)) { printf("Failed to import Private key..status : %08x\n", status); } status = BCryptEncrypt(hKey, textData, textDataSize, NULL, NULL, 0, NULL, 0, &encryptedBufferSize, BCRYPT_PAD_PKCS1 ); if (!NT_SUCCESS(status)) { printf("Failed to get required size of buffer..status : %08x\n", status); } encryptedBuffer = (PUCHAR)HeapAlloc(GetProcessHeap(), 0, encryptedBufferSize); if (encryptedBuffer == NULL) { printf("failed to allocate memory for blindedFEKBuffer\n"); } status = BCryptEncrypt(hKey, textData, textDataSize, NULL, NULL, 0, encryptedBuffer, encryptedBufferSize, &encryptedBufferSize, BCRYPT_PAD_PKCS1 ); if (!NT_SUCCESS(status)) { printf("Failed encrypt data..status : %08x\n", status); } printf("Encrypted Data\n"); printMem(encryptedBuffer, encryptedBufferSize); printf("\n\n"); std::string encryptedDataReturn = base64_encode(&encryptedBuffer[0], encryptedBufferSize); } }
ReverseMemCpy函数(用于字节序处理)
void ReverseMemCopy(BYTE* pbDest, BYTE const* pbSource, DWORD cb) { for (DWORD i = 0; i < cb; i++) { //pbDest[cb - 1 - i] = pbSource[i]; // 大端转小端时启用 pbDest[i] = pbSource[i]; } }
输入输出数据
- 输入数据:
test - .NET端生成的RSA密钥对:
<RSAKeyValue><Modulus>3XCSEveWJ3Mp41g5VxcmmlCYDL5X+VUX1ULOIl8TdsEu6bbS/Ho0ofBgAwglCrbRgAjm7ZW+EivEVLZRx5FVsEYqGX12fFZSn84Ye6D2rUYqvwR0kBE8MBCdirqg3gXAlmuIgxucWcxiT9NDTaC67Awe9yyQv3fJ2uPeOEXw0LU=</Modulus><Exponent>AQAB</Exponent><P>8uB+2rMMnduKEZ/j9pIkNuHPjqOaeBi0DMkfVTHlrknVdDwCreKVHEx9XIEyYQeYdpCwmj8hwHMEVmHJhVUcjw==</P><Q>6WeNjG2cOZ6y6e+A0k12Bn5UX/HNgeBjdfyy67PG9FMioJ9znAZsJmM5dWaQD9Px3OaHEp5tJhlqrUc6U25oew==</Q><DP>FMpW0Y3GJLUoSn3vW6oC45fM1p72mBU1RGrq/bX5vUOgvARvDkd5ECUUDhkZIOkviea0119UGk8+Lc7NG1a/zQ==</DP><DQ>Sda9vAhNHRlspn9jdKSWyxUaIkQ/7G+NZ50rCVAVh+PpF4F6NIj/m+FWIyLwPmGhqW2wm55ND3mI+wqGlDBgkw==</DQ><InverseQ>Pz8NIq8+1o6PXWdWJUJPyV1Wli9NdK5RlH8yc44QJYzAxcEFnI8CPHkQu0BHrN+mfOX9UN7LfHjI9wmOVStksw==</InverseQ><D>NjayPJyLEXt7fOKDn1PWqp8iqrQLO8ree+LQLtASJtfjEWsmOpP8wMzl5LggwX/CyNLlHrOzhiVa+tZsLSziykG4CzY1qwL6HS+oSoR7GbjkSZXQPbN8RM2tS8fZ0ZyRAtn7ohDRFNMZe6Y+cFQ3H2ijARpVl4VngTqyK/Syyz0=</D></RSAKeyValue>
- 加密后的Base64数据:
kycXjy03kP+VjWP4uYFMl4/avSOhJ269BZM/AeEj0RQmSgkfA+m9woENkDVqQuxOuw8/DqpeNreA7p11QOu3i5WNJ2wC2zhCVgXi0z+tjylQidAKiwNFNlvEfAQN3h18F/gLKkuCH7W3a7tqigxZc2jCOflA4ZeGx54ZL+gVDAw= - 加密后的十六进制数据:
93 27 17 8f 2d 37 90 ff 95 8d 63 f8 b9 81 4c 97 8f da bd 23 a1 27 6e bd 05 93 3f 01 e1 23 d1 14 26 4a 09 1f 03 e9 bd c2 81 0d 90 35 6a 42 ec 4e bb 0f 3f 0e aa 5e 36 b7 80 ee 9d 75 40 eb b7 8b 95 8d 27 6c 02 db 38 42 56 05 e2 d3 3f ad 8f 29 50 89 d0 0a 8b 03 45 36 5b c4 7c 04 0d de 1d 7c 17 f8 0b 2a 4b 82 1f b5 b7 6b bb 6a 8a 0c 59 73 68 c2 39 f9 40 e1 97 86 c7 9e 19 2f e8 15 0c 0c - .NET端解密异常:
System.Security.Cryptography.CryptographicException: '参数不正确'
解决方案
问题核心是字节序不匹配和公钥Blob数据未正确写入:
- 字节序差异:BCrypt的
BCRYPT_RSAPUBLIC_BLOB要求模数、指数以小端字节序存储,而.NET XML公钥中的模数、指数是大端(网络字节序),需反转字节数组。 - 公钥Blob数据缺失:原C++代码仅初始化了Blob头部,未将实际的模数、指数数据写入Blob,导致导入的公钥无效。
修正后的C++关键代码片段
// 反转模数和指数的字节序(大端转小端) std::vector<BYTE> reversedModulus(PubKeyModulus_bin.rbegin(), PubKeyModulus_bin.rend()); std::vector<BYTE> reversedExponent(PubKeyExp_bin.rbegin(), PubKeyExp_bin.rend()); // 将反转后的数据写入公钥Blob pbCurrent = pbPublicKey + sizeof(BCRYPT_RSAKEY_BLOB); memcpy(pbCurrent, reversedExponent.data(), reversedExponent.size()); pbCurrent += reversedExponent.size(); memcpy(pbCurrent, reversedModulus.data(), reversedModulus.size());
同时修正Base64编码部分的变量错误:
std::string encryptedDataReturn = base64_encode(&encryptedBuffer[0], encryptedBufferSize);
完成以上修正后,C++端生成的加密数据即可被.NET端正常解密。
内容的提问来源于stack exchange,提问作者kaushik
相关产品推荐
相关产品推荐

