Come crittografare piccoli blocchi di dati con solo la chiave pubblica RSA utilizzando Microsoft ECSP?

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

  •  08-07-2019
  •  | 
  •  

Domanda

Ho bisogno di crittografare un piccolo blocco di dati (16 byte) usando una chiave pubblica RSA a 512 bit - un compito abbastanza facile per la maggior parte delle librerie di crittografia a me note, ad eccezione dell'API MS CSP, come sembra. La documentazione per la CryptEncrypt afferma che

  

Il provider crittografico avanzato Microsoft supporta la crittografia diretta con chiavi pubbliche RSA e la decrittografia con chiavi private RSA. La crittografia utilizza l'imbottitura PKCS # 1.

Però non ha funzionato. Bene, il mio codice funziona e produce un blocco di dati crittografato con le dimensioni corrette, ma openssl non riesce a decifrarlo. Sembra che CryptEncrypt utilizzi ancora un cifrario simmetrico.

Sfortunatamente tutti gli esempi che ho trovato si riferiscono alla crittografia combinata con il cifrario simmetrico, quindi non ho un esempio pratico sulle mani che sicuramente renderebbe le cose più facili.

Qualcuno potrebbe indicarmi un esempio del genere o farmi sapere se ci sono alcune insidie ??ovvie che mi sono perso?

Grazie.

È stato utile?

Soluzione

Sembra un problema endianness . Microsoft CryptEncrypt restituisce il testo cifrato in formato little-endian, mentre OpenSSL si aspetta che i suoi dati siano in formato big-endian. Dovrai invertire i dati crittografati prima di passarli a OpenSSL.

Altri suggerimenti

Ecco il codice (nel caso in cui qualcuno abbia cercato su Google questo argomento):

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top