2017-06-18 7 views
0

J'ai un problème lors de l'échange de clé publique entre "OpenSSL" et "Windows CryptoAPI". La clé publique est exportée depuis OpenSSL au format pem. Mon programme est écrit en C++. Je reçois la clé publique et la charge par "CryptoAPI". Après avoir chargé la clé publique, je crypte certaines données et les envoie à l'autre application. L'autre application ne peut pas déchiffrer les données reçues par sa propre clé privée. aidez-moi s'il vous plaît à trouver la solution.Cryptage Rsa dans Windows crypto et décryptage dans openssl

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

code source:

_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

Sans les informations nécessaires, nous ne pouvons pas déboguer, même si nous voulons déboguer votre code (veuillez déboguer ce n'est pas une question, c'est une demande d'aide). –

+0

Dans votre deuxième fonction à l'intérieur de sa première instruction if, vous supprimez la valeur du résultat mais vous ne l'avez pas orthographié correctement. –

+0

Vous devez indiquer où se situe l'erreur dans le code ci-dessus. Est-ce 'CryptDecodeObjectEx' ou' CryptImportPublicKeyInfo' ou quelque chose d'autre? Vous devez valider la clé publique après l'avoir chargée. Cela peut signifier que vous devez charger une paire de clés de test pour garantir l'exactitude. OpenSSL est grand endian, et CAPI est petit boutiste. Vous devriez probablement commencer par [openssl capi rsa site endian: stackoverflow.com] (https://www.google.com/search?q=openssl+capi+rsa+endian+site%3Astackoverflow.com). Et voir [Charger un fichier PEM X509 dans Windows CryptoApi] (https://stackoverflow.com/q/1231178/608639) en particulier. – jww

Répondre

0

CryptEncrypt, pour des raisons qui ont probablement fait sens à l'auteur à l'époque, écrit les octets vers le bas en arrière. Ou, plutôt, il les écrit dans l'ordre byte minor/little-endian alors que presque toutes les autres bibliothèques de cryptographie (y compris les routines Windows CNG BCryptEncrypt et NCryptEncrypt) les écrit dans l'ordre byte major/big-endian.

Vous devez donc inverser les données provenant de CryptEncrypt, et l'inverser en CryptDecrypt.

Par exemple, dans. RSACryptoServiceProvider.Encrypt .NET Core appelle CapiHelper.EncryptKey qui appelle CryptEncrypt puis Array.Reverse avant de retourner.

Le CryptEncrypt documentation a comme la dernière phrase de la section Remarques

Le cryptogramme est retourné au format petit-boutiste.

+0

Merci pour la réponse –