2017-06-18 56 views
0

「OpenSSL」と「Windows CryptoAPI」の間で公開鍵を交換する際に問題があります。公開鍵はOpenSSLからpem形式でエクスポートされます。私のプログラムはC++で書かれています。公開鍵を取得し、「CryptoAPI」でロードします。公開鍵をロードした後、私はいくつかのデータを暗号化し、それらを他のアプリケーションに送ります。他のアプリケーションは、受信したデータを自分の秘密鍵で解読することはできません。解決策を見つけるのを手伝ってください。Windowsでのrsa暗号化opensslでの暗号化と復号化

-----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; 
} 
+0

コードをデバッグしたい場合でも、必要な情報がないとデバッグできません(デバッグしてください。これは問題ではありません。ヘルプのリクエストです)。 –

+0

最初のifステートメント内の2番目の関数では、結果の値を削除していますが、正しく綴りませんでした。 –

+0

上記のコードにどこに障害があるのか​​を明記する必要があります。それは 'CryptDecodeObjectEx'か' CryptImportPublicKeyInfo'なのでしょうか?公開鍵を読み込んだ後、公開鍵を検証する必要があります。正確性を保証するためにテストキーのペアをロードする必要があるかもしれません。 OpenSSLはビッグエンディアンで、CAPIはリトルエンディアンです。おそらく[openssl capi rsa endian site:stackoverflow.com](https://www.google.com/search?q=openssl+capi+rsa+endian+site%3Astackoverflow.com)から始めるべきです。特に、[Windows CryptoApiにX509 PEMファイルを読み込む](https://stackoverflow.com/q/1231178/608639)を参照してください。 – jww

答えて

0

CryptEncryptは、おそらく一度作者に意味を成していた理由のために、ダウン後方バイトを書き込みます。あるいは、それはバイトマイナー/リトルエンディアンの順序で書き込みますが、他のほとんどすべての暗号化ライブラリ(Windows CNG BCryptEncryptおよびNCryptEncryptルーチンを含む)はバイトメジャー/ビッグエンディアンの順序で書き込みます。

CryptEncryptのデータを逆にして、逆のデータをCryptDecryptに戻す必要があります。

たとえば、.NETコアのRSACryptoServiceProvider.Encryptでは、CryptEncryptを呼び出し、返す前にArray.Reverseを呼び出すCapiHelper.EncryptKeyを呼び出します。

CryptEncrypt documentation

暗号文は、リトルエンディアン形式で返されます備考セクションの最後の文として持っています。

+0

お返事ありがとう –