You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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数据未正确写入:

  1. 字节序差异:BCrypt的BCRYPT_RSAPUBLIC_BLOB要求模数、指数以小端字节序存储,而.NET XML公钥中的模数、指数是大端(网络字节序),需反转字节数组。
  2. 公钥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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 00:02:31