Comment chiffrer un petit bloc de données avec une clé publique RSA uniquement à l'aide de Microsoft ECSP?

StackOverflow https://stackoverflow.com/questions/295345

  •  08-07-2019
  •  | 
  •  

Question

Je dois chiffrer un petit bloc de données (16 octets) à l'aide d'une clé publique RSA 512 bits - une tâche assez facile pour la plupart des bibliothèques de chiffrement que je connais, à l'exception de l'API MS CSP, semble-t-il. La documentation de la fonction CryptEncrypt indique que

  

Le fournisseur cryptographique amélioré de Microsoft prend en charge le cryptage direct avec les clés publiques RSA et le décryptage avec les clés privées RSA. Le chiffrement utilise le remplissage PKCS # 1.

Cela n’a pas fonctionné pour moi cependant. Eh bien, mon code fonctionne et produit un bloc de données chiffré de taille correcte, mais openssl ne parvient pas à le déchiffrer. Il semble que CryptEncrypt utilise toujours le chiffrement symétrique.

Malheureusement, tous les exemples que j'ai trouvés font référence à la cryptographie combinée avec un chiffrement symétrique, je ne dispose donc pas d'un exemple fonctionnel sur les mains qui faciliterait définitivement les choses.

Quelqu'un pourrait-il m'indiquer un tel exemple ou me laisser savoir s'il y a des pièges pas si évidents que j'ai manqués?

Merci.

Était-ce utile?

La solution

Cela ressemble à un problème de endianness . Fonction CryptEncrypt de Microsoft renvoie le texte chiffré au format little-endian, alors qu'OpenSSL s'attend à ce que ses données soient au format big-endian. Vous devrez inverser les données chiffrées avant de les transmettre à OpenSSL.

Autres conseils

Voici le code (juste au cas où quelqu'un aurait googlé ce sujet):

BYTE *spkiData = SPKI; // X.509 ASN.1 encoded SubjectPublicKeyInfo
DWORD dwSPKISize = SPKI_SIZE; // 94 bytes for RSA

DWORD dwBufSize = 0;
// Get buffer size for decoded spki structure
CryptDecodeObject(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, spkiData, dwSPKISize, 0, NULL, &dwBufSize);
BYTE* decBuf = new BYTE[dwBufSize];
CryptDecodeObject( X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, spkiData, dwSPKISize, 0, decBuf, &dwBufSize);
// Now decode the RSA Public key itself
CERT_PUBLIC_KEY_INFO * spki = (CERT_PUBLIC_KEY_INFO *) decBuf;
// Get buffer size for decoded public key structure
CryptDecodeObject( X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, spki->PublicKey.pbData, spki->PublicKey.cbData, 0, 0, &dwBufSize);
// Get the RSA public key blob
BYTE *blobBuf = new BYTE[dwBufSize];
CryptDecodeObject(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB, spki->PublicKey.pbData, spki->PublicKey.cbData, 0, blobBuf, &dwBufSize);
// Acquire crypto provider context
HCRYPTPROV hCryptProv = NULL;
CryptAcquireContext(&hCryptProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
// Import key
HCRYPTKEY key = NULL;
CryptImportKey(hCryptProv, blobBuf, dwBufSize, 0, 0, &key);
// Get the key size
DWORD dwKeySize;
DWORD dwParamSize = sizeof(DWORD);
CryptGetKeyParam(key, KP_KEYLEN, (BYTE*) &dwKeySize, &dwParamSize, 0);
// we need it in bytes for convenience
dwKeySize /= 8;
// Now the fun
// allocate a buffer of key size
BYTE *data = new BYTE[dwKeySize];
// Copy data need to be encrypted
// With PKCS#1 padding data length can not exceed keysize - 11 bytes
DWORD dataLen = 16;
memcpy(data, "0123456789012345", dataLen);
CryptEncrypt(key, 0, TRUE, 0, data, &dataLen, dwKeySize)
// now convert it to big endian (for the rest of the world)
for (int i = 0; i < (dwKeySize / 2); i++) {
    BYTE c = data[i];
    data[i] = data[dwKeySize - 1 - i];
    data[dwKeySize - 1 - i] = c;
}
// now data points to a dwKeySize length block of RSA PKCS#v1.5 encrypted data
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top