2015-12-17 2 views
2

Le problème que je rencontre est que je suis capable de déchiffrer des données en utilisant la même clé publique RSA 2048 bits qui a été utilisée pour crypter les données. Il me semble que cela va à l'encontre de l'objectif de chiffrer les données en premier lieu, si une clé publique peut le déchiffrer. La seule chose que je peux considérer en ce moment est que je génère des paires d'échange de clés symétriques quand je pense que je génère des paires asymétriques. Le but de l'utilisateur final est de l'utiliser plus tard pour transmettre des informations d'identification d'utilisateur à authentifier en utilisant une application loin du bureau, lorsque je ne peux pas utiliser leurs informations d'identification mises en cache depuis leurs postes de travail sur le domaine. Je serais théoriquement capable de décrypter ces informations d'identification en utilisant seulement la clé privée.Crypto API La clé publique RSA peut déchiffrer des données, n'est pas asymétrique comme prévu

J'ai produit une classe de test simple et un code pour reproduire mon problème. Les étapes que je prends sont les suivantes:

  1. Acquire un contexte de Microsoft Enhanced Cryptographic Provider v1.0
  2. Générer une paire de clés publique/privée.
  3. Exportez les BLOB de clé privée et publique vers des fichiers distincts.
  4. Chargez la clé publique et cryptez un texte simple.
  5. Tenter de déchiffrer le même texte chiffré à l'aide de la clé publique (je m'attendais à ce qu'il échoue ici sauf lorsque j'utilise la clé privée - mais les deux fonctionnent).

TestEncryptDecrypt classe d'aide: TestEncryptDecrypt.h

#pragma once 
#include <Windows.h> 
#include <wincrypt.h> 

class TestEncryptDecrypt 
{ 
public: 
    TestEncryptDecrypt() 
    { 
    } 
    ~TestEncryptDecrypt() 
    { 
     if (hKey != NULL) 
      CryptDestroyKey(hKey); 

     if (hProvider != NULL) 
      CryptReleaseContext(hProvider, 0); 
    } 

    BOOL InitializeProvider(LPCTSTR pszProvider, DWORD dwProvType) 
    { 
     if (hProvider != NULL) 
     { 
      if (!CryptReleaseContext(hProvider, 0)) 
       return 0; 
     } 

     return CryptAcquireContext(&hProvider, NULL, pszProvider, dwProvType, 0); 
    } 

    BOOL Generate2048BitKeys(ALG_ID Algid) 
    { 
     DWORD dwFlags = (0x800 << 16) | CRYPT_EXPORTABLE; 
     return CryptGenKey(hProvider, Algid, dwFlags, &hKey); 
    } 

    VOID ExportPrivatePublicKey(LPTSTR lpFileName) 
    { 
     if (hKey == NULL) 
      return; 

     DWORD dwDataLen = 0; 
     BOOL exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwDataLen); 
     LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen); 
     exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, lpKeyBlob, &dwDataLen); 
     WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen); 
     free(lpKeyBlob); 
    } 

    VOID ExportPublicKey(LPTSTR lpFileName) 
    { 
     if (hKey == NULL) 
      return; 

     DWORD dwDataLen = 0; 
     BOOL exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwDataLen); 
     LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen); 
     exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, lpKeyBlob, &dwDataLen); 
     WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen); 
     free(lpKeyBlob); 
    } 

    BOOL ImportKey(LPTSTR lpFileName) 
    { 
     if (hProvider == NULL) 
      return 0; 

     if (hKey != NULL) 
      CryptDestroyKey(hKey); 

     LPBYTE lpKeyContent = NULL; 
     DWORD dwDataLen = 0; 
     ReadBytesFile(lpFileName, &lpKeyContent, &dwDataLen); 
     BOOL importResult = CryptImportKey(hProvider, lpKeyContent, dwDataLen, 0, 0, &hKey); 

     delete[] lpKeyContent; 

     return importResult; 
    } 

    BOOL EncryptDataWriteToFile(LPTSTR lpSimpleDataToEncrypt, LPTSTR lpFileName) 
    { 
     DWORD SimpleDataToEncryptLength = _tcslen(lpSimpleDataToEncrypt)*sizeof(TCHAR); 
     DWORD BufferLength = SimpleDataToEncryptLength * 10; 
     BYTE *EncryptedBuffer = new BYTE[BufferLength]; 
     SecureZeroMemory(EncryptedBuffer, BufferLength); 
     CopyMemory(EncryptedBuffer, lpSimpleDataToEncrypt, SimpleDataToEncryptLength); 

     BOOL cryptResult = CryptEncrypt(hKey, NULL, TRUE, 0, EncryptedBuffer, &SimpleDataToEncryptLength, BufferLength); 
     DWORD dwGetLastError = GetLastError(); 

     WriteBytesFile(lpFileName, EncryptedBuffer, SimpleDataToEncryptLength); 

     delete[] EncryptedBuffer; 

     return cryptResult; 
    } 

    BOOL DecryptDataFromFile(LPBYTE *lpDecryptedData, LPTSTR lpFileName, DWORD *dwDecryptedLen) 
    { 
     if (hKey == NULL) 
      return 0; 

     LPBYTE lpEncryptedData = NULL; 
     DWORD dwDataLen = 0; 
     ReadBytesFile(lpFileName, &lpEncryptedData, &dwDataLen); 
     BOOL decryptResult = CryptDecrypt(hKey, NULL, TRUE, 0, lpEncryptedData, &dwDataLen); 
     *dwDecryptedLen = dwDataLen; 
     //WriteBytesFile(L"decryptedtest.txt", lpEncryptedData, dwDataLen); 
     *lpDecryptedData = new BYTE[dwDataLen + 1]; 
     SecureZeroMemory(*lpDecryptedData, dwDataLen + 1); 
     CopyMemory(*lpDecryptedData, lpEncryptedData, dwDataLen); 

     delete[]lpEncryptedData; 

     return decryptResult; 
    } 

    VOID WriteBytesFile(LPTSTR lpFileName, BYTE *content, DWORD dwDataLen) 
    { 
     HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0x7, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
     DWORD dwBytesWritten = 0; 
     WriteFile(hFile, content, dwDataLen, &dwBytesWritten, NULL); 
     CloseHandle(hFile); 
    } 

private: 
    HCRYPTPROV hProvider = NULL; 
    HCRYPTKEY hKey = NULL; 

    VOID ReadBytesFile(LPTSTR lpFileName, BYTE **content, DWORD *dwDataLen) 
    { 
     HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0x7, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
     DWORD dwFileLength = 0; 
     DWORD dwBytesToRead = GetFileSize(hFile, NULL); 
     DWORD dwBytesRead = 0; 

     *content = new BYTE[dwBytesToRead + 1]; 
     SecureZeroMemory(*content, dwBytesToRead + 1); 

     ReadFile(hFile, *content, dwBytesToRead, &dwBytesRead, NULL); 

     *dwDataLen = dwBytesRead; 

     CloseHandle(hFile); 
    } 
}; 

Code d'essai: fichier .cpp principal

#include "stdafx.h" 
#include "TestEncryptDecrypt.h" 
#include <Windows.h> 
#include <wincrypt.h> 

int main() 
{ 
    TestEncryptDecrypt *edc = new TestEncryptDecrypt(); 
    //Initialize the provider 
    edc->InitializeProvider(MS_ENHANCED_PROV, PROV_RSA_FULL); 

    //Generate a 2048-bit asymmetric key pair 
    edc->Generate2048BitKeys(CALG_RSA_KEYX); 

    //Export the private/public key pair 
    edc->ExportPrivatePublicKey(L"privpubkey.txt"); 

    //Export only the public key 
    edc->ExportPublicKey(L"pubkey.txt"); 

    //Import the public key (destroys the private/public key pair already set) 
    edc->ImportKey(L"pubkey.txt"); 

    //Encrypt and write some test data to file 
    edc->EncryptDataWriteToFile(TEXT("Hello World!ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), L"encrypteddata.txt"); 

    //Decrypt the data from file using the same public key (this should fail but it doesn't) 
    DWORD dwDataLen = 0; 
    LPBYTE lpDecryptedData = NULL; 
    edc->DecryptDataFromFile(&lpDecryptedData, L"encrypteddata.txt", &dwDataLen); 

    //Write the supposedly decrypted data to another file 
    edc->WriteBytesFile(L"decrypteddata.txt", lpDecryptedData, dwDataLen); 

    //Clear data 
    delete[] lpDecryptedData; 
    delete edc; 

    return 0; 
} 

Malheureusement je ne suis pas l'occasion de travailler avec C++ très souvent si vous peut remarquer quelques problèmes. N'hésitez pas à critiquer de manière constructive.

Est-ce que quelqu'un sait pourquoi je suis capable de déchiffrer des données en utilisant la même clé publique? Mon but est de pouvoir crypter de façon irréversible quelque chose du côté client où il ne peut être décrypté que sur le serveur, où la clé privée se cache.

Edit: Je considérais que la hKey n'a pas été détruite correctement par la méthode importkey, j'ai donc écrit ce cas de test à la place (même résultat - clé publique peut chiffrer et déchiffrer les données):

// CPPTests.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include "TestEncryptDecrypt.h" 
#include <Windows.h> 
#include <wincrypt.h> 

int main() 
{ 
    TestEncryptDecrypt *edc = new TestEncryptDecrypt(); 
    //Initialize the provider 
    edc->InitializeProvider(MS_ENHANCED_PROV, PROV_RSA_FULL); 

    //Generate a 2048-bit asymmetric key pair 
    edc->Generate2048BitKeys(CALG_RSA_KEYX); 

    //Export the private/public key pair 
    edc->ExportPrivatePublicKey(L"privpubkey.txt"); 

    //Export only the public key 
    edc->ExportPublicKey(L"pubkey.txt"); 

    //Destroy everything and load up only the public key to write some encrypted data 
    delete edc; 
    edc = new TestEncryptDecrypt(); 
    edc->InitializeProvider(MS_ENHANCED_PROV, PROV_RSA_FULL); 
    edc->ImportKey(L"pubkey.txt"); 

    //Encrypt and write some test data to file 
    edc->EncryptDataWriteToFile(TEXT("Hello World!ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), L"encrypteddata.txt"); 

    //Destroy everything and load up only the public key to read some encrypted data 
    delete edc; 
    edc = new TestEncryptDecrypt(); 
    edc->InitializeProvider(MS_ENHANCED_PROV, PROV_RSA_FULL); 
    edc->ImportKey(L"pubkey.txt"); 

    //Decrypt the data from file using the same public key (this should fail but it doesn't) 
    DWORD dwDataLen = 0; 
    LPBYTE lpDecryptedData = NULL; 
    edc->DecryptDataFromFile(&lpDecryptedData, L"encrypteddata.txt", &dwDataLen); 

    //Write the supposedly decrypted data to another file 
    edc->WriteBytesFile(L"decrypteddata.txt", lpDecryptedData, dwDataLen); 

    //Clear data 
    delete[] lpDecryptedData; 
    delete edc; 

    return 0; 
} 
+1

Peut-être l'hypothèse ici '// Importer la clé publique (détruit la paire de clés privée/publique déjà définie)' n'est pas correct? Et si vous réinstanciez 'edc' juste avant cela? – Kenney

+0

@Kenney Je pensais que d'abord, aussi. J'ai pensé que peut-être le CryptDestroyKey dans la fonction d'importation ne faisait pas son travail. La destruction puis la ré-instanciation de l'instance d'edc permettent toujours le décryptage du contenu chiffré tant que I Initialise le même fournisseur et charge avec le blob de clé publique ou privée. – RyanH

+0

@zaph Je veux dire que la fonction CryptDecrypt sous-jacente devrait renvoyer un 0 indiquant l'échec de décryptage et, par conséquent, lpDecryptedData devrait rester NULL et produire un fichier decrypteddata.txt vierge. Au lieu de cela, le fichier decrypteddata.txt est produit avec les résultats parfaitement décryptés. – RyanH

Répondre

0

Le problème est que, pour une raison quelconque, l'API Crypto, utilisant Microsoft Enhanced Provider avec RSA, produit des clés symétriques. Je suis incapable de l'obtenir pour produire des clés asymétriques. L'algorithme fonctionnera cependant avec des clés asymétriques. C'est donc une bonne nouvelle pour nous. Cela signifie que pour que cela fonctionne, il suffit de générer des clés. Vous pouvez également les exporter à partir de certificats auto-signés, utiliser votre entreprise CA, etc.

Pour résoudre ce problème, j'ai produit une paire de clés publique/privée en utilisant OpenSSL. Je OpenSSL compilé pour Windows juste pour le plaisir a couru les instructions suivantes pour me procurer une paire de fichiers clés public/privé non cryptés:

  1. OpenSSL genpkey private2 -out.PEM PEM -outform -des3 -algorithm RSA -pkeyopt rsa_keygen_bits: 2048

    ou

    openssl genrsa -des3 -out private.pem 2048

  2. openssl rsa -in private.pem -outform PEM -pubout public.pem -out

  3. openssl rsa -in private.pem -outform PEM private_unencrypted.pem -out

Une fois que j'avais ceux que j'ajouté 2 nouvelles fonctions à mon test classe d'aide, ImportPu blicKey et ImportPrivateKey. Cela importera uniquement les fichiers PEM sans phrase secrète. Je ne considère pas cela comme une menace à la sécurité, étant donné que le public est public et que le privé devrait se cacher sur un serveur sécurisé quelque part, peut-être codé avec un hachage.

TestEncryptDecrypt.h

#pragma once 
#include <Windows.h> 
#include <wincrypt.h> 

class TestEncryptDecrypt 
{ 
public: 
    TestEncryptDecrypt() 
    { 
    } 
    ~TestEncryptDecrypt() 
    { 
     if (hKey != NULL) 
      CryptDestroyKey(hKey); 

     if (hProvider != NULL) 
      CryptReleaseContext(hProvider, 0); 
    } 

    BOOL InitializeProvider(LPCTSTR pszProvider, DWORD dwProvType) 
    { 
     if (hProvider != NULL) 
     { 
      if (!CryptReleaseContext(hProvider, 0)) 
       return 0; 
     } 

     return CryptAcquireContext(&hProvider, NULL, pszProvider, dwProvType, CRYPT_VERIFYCONTEXT); 
    } 

    BOOL Generate2048BitKeys(ALG_ID Algid) 
    { 
     DWORD dwFlags = (0x800 << 16) | CRYPT_EXPORTABLE; 
     return CryptGenKey(hProvider, Algid, dwFlags, &hKey); 
    } 

    VOID ExportPrivatePublicKey(LPTSTR lpFileName) 
    { 
     if (hKey == NULL) 
      return; 

     DWORD dwDataLen = 0; 
     BOOL exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwDataLen); 
     LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen); 
     exportResult = CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, lpKeyBlob, &dwDataLen); 
     WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen); 
     free(lpKeyBlob); 
    } 

    VOID ExportPublicKey(LPTSTR lpFileName) 
    { 
     if (hKey == NULL) 
      return; 

     DWORD dwDataLen = 0; 
     BOOL exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, &dwDataLen); 
     LPBYTE lpKeyBlob = (LPBYTE)malloc(dwDataLen); 
     exportResult = CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, lpKeyBlob, &dwDataLen); 
     WriteBytesFile(lpFileName, lpKeyBlob, dwDataLen); 
     free(lpKeyBlob); 
    } 

    BOOL ImportKey(LPTSTR lpFileName) 
    { 
     if (hProvider == NULL) 
      return 0; 

     if (hKey != NULL) 
      CryptDestroyKey(hKey); 

     LPBYTE lpKeyContent = NULL; 
     DWORD dwDataLen = 0; 
     ReadBytesFile(lpFileName, &lpKeyContent, &dwDataLen); 
     BOOL importResult = CryptImportKey(hProvider, lpKeyContent, dwDataLen, 0, 0, &hKey); 

     delete[] lpKeyContent; 

     return importResult; 
    } 

    BOOL ImportPublicKey(LPTSTR lpFileName) 
    { 
     //If a context doesn't exist acquire one 
     if (hProvider == NULL) 
     { 
      BOOL result = CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 
      if (!result) 
       return result; 
     } 

     if (hKey != NULL) 
      CryptDestroyKey(hKey); 

     //Load the PEM 
     LPBYTE PublicBytes = NULL; 
     DWORD dwDataLen = 0; 
     ReadBytesFile(lpFileName, &PublicBytes, &dwDataLen); 

     //Convert to Unicode 
     int PublicPEMSize = MultiByteToWideChar(CP_ACP, 0, (LPCCH)PublicBytes, -1, NULL, 0); 
     TCHAR *PublicPEM = new TCHAR[PublicPEMSize]; 
     MultiByteToWideChar(CP_ACP, 0, (LPCCH)PublicBytes, -1, PublicPEM, PublicPEMSize); 
     delete[]PublicBytes; 

     //Convert PEM to DER 
     LPBYTE PublicDER = NULL; 
     DWORD dwPublicDERLen = 0; 

     BOOL result = CryptStringToBinary(PublicPEM, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwPublicDERLen, NULL, NULL); 
     if (!result) 
      return result; 

     PublicDER = new BYTE[dwPublicDERLen]; 
     result = CryptStringToBinary(PublicPEM, 0, CRYPT_STRING_BASE64HEADER, PublicDER, &dwPublicDERLen, NULL, NULL); 
     if (!result) 
      return result; 

     delete[] PublicPEM; 

     //Decode the object into a public key info struct 
     CERT_PUBLIC_KEY_INFO *PublicKeyInfo = NULL; 
     DWORD dwPublicKeyInfoLen = 0; 

     result = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, PublicDER, dwPublicDERLen, CRYPT_ENCODE_ALLOC_FLAG, NULL, &PublicKeyInfo, &dwPublicKeyInfoLen); 
     if (!result) 
      return result; 

     //Import the public key 
     result = CryptImportPublicKeyInfo(hProvider, X509_ASN_ENCODING, PublicKeyInfo, &hKey); 
     if (!result) 
      return result; 


     //cleanup 
     delete[] PublicDER; 
     LocalFree(PublicKeyInfo); 

     return result; 
    } 

    BOOL ImportPrivateKey(LPTSTR lpFileName) 
    { 
     //If a context doesn't exist acquire one 
     if (hProvider == NULL) 
     { 
      BOOL result = CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 
      if (!result) 
       return result; 
     } 

     if (hKey != NULL) 
      CryptDestroyKey(hKey); 

     //Load the PEM 
     LPBYTE PrivateBytes = NULL; 
     DWORD dwDataLen = 0; 
     ReadBytesFile(lpFileName, &PrivateBytes, &dwDataLen); 

     //Convert to Unicode 
     int PrivatePEMSize = MultiByteToWideChar(CP_ACP, 0, (LPCCH)PrivateBytes, -1, NULL, 0); 
     TCHAR *PrivatePEM = new TCHAR[PrivatePEMSize]; 
     MultiByteToWideChar(CP_ACP, 0, (LPCCH)PrivateBytes, -1, PrivatePEM, PrivatePEMSize); 
     delete[]PrivateBytes; 

     //Convert PEM to DER 
     LPBYTE PrivateDER = NULL; 
     DWORD dwPrivateDERLen = 0; 

     BOOL result = CryptStringToBinary(PrivatePEM, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwPrivateDERLen, NULL, NULL); 
     if (!result) 
      return result; 

     PrivateDER = new BYTE[dwPrivateDERLen]; 
     result = CryptStringToBinary(PrivatePEM, 0, CRYPT_STRING_BASE64HEADER, PrivateDER, &dwPrivateDERLen, NULL, NULL); 
     if (!result) 
      return result; 

     delete[] PrivatePEM; 

     //Decode the object into a private key info struct 
     BYTE *PrivateKeyInfo = NULL; 
     DWORD dwPrivateKeyInfoLen = 0; 

     result = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, PrivateDER, dwPrivateDERLen, 0, NULL, NULL, &dwPrivateKeyInfoLen); 
     if (!result) 
      return result; 

     PrivateKeyInfo = new BYTE[dwPrivateKeyInfoLen]; 

     result = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, PrivateDER, dwPrivateDERLen, 0, NULL, PrivateKeyInfo, &dwPrivateKeyInfoLen); 
     if (!result) 
      return result; 



     //Import the private key 
     result = CryptImportKey(hProvider, PrivateKeyInfo, dwPrivateKeyInfoLen, NULL, 0, &hKey); 
     if (!result) 
      return result; 


     //cleanup 
     delete[] PrivateDER; 
     delete[] PrivateKeyInfo; 

     return result; 
    } 

    BOOL EncryptDataWriteToFile(LPTSTR lpSimpleDataToEncrypt, LPTSTR lpFileName) 
    { 
     DWORD SimpleDataToEncryptLength = _tcslen(lpSimpleDataToEncrypt)*sizeof(TCHAR); 
     DWORD BufferLength = SimpleDataToEncryptLength * 10; 
     BYTE *EncryptedBuffer = new BYTE[BufferLength]; 
     SecureZeroMemory(EncryptedBuffer, BufferLength); 
     CopyMemory(EncryptedBuffer, lpSimpleDataToEncrypt, SimpleDataToEncryptLength); 

     BOOL cryptResult = CryptEncrypt(hKey, NULL, TRUE, 0, EncryptedBuffer, &SimpleDataToEncryptLength, BufferLength); 
     DWORD dwGetLastError = GetLastError(); 

     WriteBytesFile(lpFileName, EncryptedBuffer, SimpleDataToEncryptLength); 

     delete[] EncryptedBuffer; 

     return cryptResult; 
    } 

    BOOL DecryptDataFromFile(LPBYTE *lpDecryptedData, LPTSTR lpFileName, DWORD *dwDecryptedLen) 
    { 
     if (hKey == NULL) 
      return 0; 

     LPBYTE lpEncryptedData = NULL; 
     DWORD dwDataLen = 0; 
     ReadBytesFile(lpFileName, &lpEncryptedData, &dwDataLen); 
     BOOL decryptResult = CryptDecrypt(hKey, NULL, TRUE, 0, lpEncryptedData, &dwDataLen); 
     *dwDecryptedLen = dwDataLen; 
     //WriteBytesFile(L"decryptedtest.txt", lpEncryptedData, dwDataLen); 
     *lpDecryptedData = new BYTE[dwDataLen + 1]; 
     SecureZeroMemory(*lpDecryptedData, dwDataLen + 1); 
     CopyMemory(*lpDecryptedData, lpEncryptedData, dwDataLen); 

     delete[]lpEncryptedData; 

     return decryptResult; 
    } 

    VOID WriteBytesFile(LPTSTR lpFileName, BYTE *content, DWORD dwDataLen) 
    { 
     HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0x7, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
     DWORD dwBytesWritten = 0; 
     WriteFile(hFile, content, dwDataLen, &dwBytesWritten, NULL); 
     CloseHandle(hFile); 
    } 

private: 
    HCRYPTPROV hProvider = NULL; 
    HCRYPTKEY hKey = NULL; 

    VOID ReadBytesFile(LPTSTR lpFileName, BYTE **content, DWORD *dwDataLen) 
    { 
     HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0x7, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 
     DWORD dwFileLength = 0; 
     DWORD dwBytesToRead = GetFileSize(hFile, NULL); 
     DWORD dwBytesRead = 0; 

     *content = new BYTE[dwBytesToRead + 1]; 
     SecureZeroMemory(*content, dwBytesToRead + 1); 

     ReadFile(hFile, *content, dwBytesToRead, &dwBytesRead, NULL); 

     *dwDataLen = dwBytesRead; 

     CloseHandle(hFile); 
    } 
}; 

Et voici le test, fournissant la preuve qu'il ne peut pas déchiffrer à l'aide de la clé publique, mais plutôt la .pem clé privée:

int main() 
{ 
    TestEncryptDecrypt *edc = new TestEncryptDecrypt(); 
    edc->ImportPublicKey(L"public.pem"); 
    edc->EncryptDataWriteToFile(L"Hello world! hahahahah", L"encrypted.txt"); 

    LPBYTE decodedData = NULL; DWORD decodedLen = 0; 
    BOOL result = edc->DecryptDataFromFile(&decodedData, L"encrypted.txt", &decodedLen); 
    if (result == 1) 
     OutputDebugString(L"We were able to decrypt from a public key! That's not good."); 

    result = edc->ImportPrivateKey(L"private_unencrypted.pem"); 
    result = edc->DecryptDataFromFile(&decodedData, L"encrypted.txt", &decodedLen); 
    edc->WriteBytesFile(L"decrypted.txt", decodedData, decodedLen); 
    return 0; 
} 
+0

Salut @RyanH Je suis arrivé au même problème que vous ici, avec la génération Crypto API RSA, le public était capable de crypter et décrypter.Puis j'ai généré les clés avec OpenSSL (et les ai importées) comme vous l'avez expliqué et j'ai développé un code similaire au vôtre mais ... le public est toujours capable de crypter et décrypter. Je ne peux pas comprendre ce qui se passe ici. Avez-vous appris quelque chose de nouveau à ce sujet au fil des ans? Merci d'avance! –

+0

@CaptainNemo C'est intéressant. Je ne peux penser qu'à trois possibilités pour votre cas: a) vous ne pouvez pas générer une paire de clés asymétrique; b) la clé privée est mise en cache et utilisée d'une manière ou d'une autre; c) vous pouvez importer la clé privée par erreur. Je viens de tester mon exemple de code ci-dessus à nouveau contre une nouvelle paire de clés asymétriques et le public était capable de crypter mais incapable de décrypter, comme prévu. La clé publique de 2048 bits était de 451 octets et la clé privée non chiffrée de 1675 octets. Je verrai si je peux vous PM les clés que j'ai testées. – RyanH

+0

Veuillez consulter [ce lien] (https://enterpriseevolution-my.sharepoint.com/personal/ryan_eesupport_ca/_layouts/15/guestaccess.aspx?docid=037cdb60b79024a43b1ba9f6f7432f20e&authkey=AYC9qllwYYGXGjxbXdzpmUg) pour mes exemples de fichiers PEM privés/publics qui fonctionnent avec succès pour moi. Le public peut seulement crypter et le privé peut crypter ou déchiffrer. – RyanH

0

Après quelques combats avec le même problème que j'ai réalisé où l'erreur était.

Dans votre premier code acquéraient votre contexte avec le dernier drapeau à zéro:

CryptAcquireContext(&hProvider, NULL, pszProvider, dwProvType, 0); 

Mais dans votre solution vous changé dans CRYPT_VERIFYCONTEXT.

CryptAcquireContext(&hProvider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 

Vous avez résolu votre problème en modifiant ce drapeau, et non en important les clés d'OpenSSL. Je suis assez sûr que si vous le tester dans votre code initial, cela fonctionnera comme prévu.

Cet indicateur CRYPT_VERIFYCONTEXT est responsable de ne pas autoriser une clé à atteindre la persistance dans le système, une persistance qui a permis au RSA public de crypter et décrypter.