Windows中的rsa加密在openssl

时间:2017-06-18 18:07:22

标签: c++ openssl cryptography rsa cryptoapi

我在“OpenSSL”和“Windows CryptoAPI”之间交换公钥时遇到问题。公钥以pem格式从OpenSSL导出。我的程序是用c ++编写的。我获取公钥并通过“CryptoAPI”加载它。加载公钥后,我加密了一些数据并将它们发送到另一个应用程序。另一个应用程序无法通过自己的私钥解密接收的数据。请帮我找到解决方案。

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcJXxao6OzesjaM5VnsYTnHWUN
z8dosWEETARH6NOqq+hAoMscsv+2MgT0oOYKLf/c8i37YFXnswEan78QnWYO3jtX
UHfJgXcLcMz7o3lX3OwNqRXgXW6Db95EjPEnLuPCJ2Pafu9E75ZMglkgw9MrIAik
XKL9u2dc9fkbc7FptQIDAQAB
-----END PUBLIC KEY-----

源代码:

_ServerContextHandle = NULL;
_EncryptionKeyHandle = NULL;

void Initialize(char* inPublicKeyByPemFormat)
{
    HCRYPTPROV serverContextHandle;

    bool result = CryptAcquireContextW(&serverContextHandle, nullptr, nullptr, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == TRUE;

    if (result)
    {
        _ServerContextHandle = serverContextHandle;

        byte derPublicKey[2048];
        DWORD derPublicKeyLength = 2048;

        result = CryptStringToBinaryA(inPublicKeyByPemFormat, 0, CRYPT_STRING_BASE64HEADER, derPublicKey, &derPublicKeyLength, nullptr, nullptr) == TRUE;

        CERT_PUBLIC_KEY_INFO* publicKeyInfo = nullptr;
        DWORD publicKeyInfoLength;

        if(result)
        {
            result = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO, derPublicKey, derPublicKeyLength, CRYPT_ENCODE_ALLOC_FLAG, nullptr, &publicKeyInfo, &publicKeyInfoLength) == TRUE;
        }

        HCRYPTKEY encryptionKeyHandle;

        if(result)
        {
            result = CryptImportPublicKeyInfo(_ServerContextHandle, X509_ASN_ENCODING, publicKeyInfo, &encryptionKeyHandle) == TRUE;
        }

        LocalFree(publicKeyInfo);

        if (result)
        {
            _EncryptionKeyHandle = encryptionKeyHandle;
        }
    }
}


byte* EncryptData(byte* inData, DWORD inDataLength, DWORD* outLength) const
{
    byte* result = nullptr;

    *outLength = 0;

    DWORD length = inDataLength;

    result = CloneByteArray(inData, inDataLength);

    if (!CryptEncrypt(_EncryptionKeyHandle, NULL, TRUE, 0, result, &length, length))
    {
        delet result;

        result = new byte[length];

        CopyByteArray(inData, result, inDataLength);

        *outLength = inDataLength;

        if (!CryptEncrypt(_EncryptionKeyHandle, NULL, TRUE, 0, result, outLength, length))
        {
            delete result;

            result = nullptr;

            *outLength = 0;
        }
    }
    else
    {
        *outLength = length;
    }

    return result;
}

1 个答案:

答案 0 :(得分:0)

if ($("#assignment_name").val() == "") { $(".to_description").addClass("disabled"); $("#assignment_name").on("change", function() { if($(this).val() == "") { $(".to_description").addClass("disabled"); } else { $(".to_description").removeClass("disabled"); } }); }; ,由于当时可能对作者有意义的原因,将字节向下写入。或者,它以字节小/小端顺序写入它们,而几乎所有其他加密库(包括Windows CNG CryptEncryptBCryptEncrypt例程)以字节主/大端顺序写入它们。

因此,您需要撤消来自NCryptEncrypt的数据,并将其反转到CryptEncrypt

例如,在.NET Core的RSACryptoServiceProvider.Encrypt中,它调用CapiHelper.EncryptKey,然后在返回之前调用CryptDecrypt然后调用CryptEncrypt

CryptEncrypt documentation作为备注部分的最后一句

  

密文以little-endian格式返回。