Wie kleinen Datenblock mit nur öffentlichem RSA-Schlüssel mit Microsoft ECSP verschlüsseln?

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

  •  08-07-2019
  •  | 
  •  

Frage

Ich brauche einen kleinen Block von Daten zu verschlüsseln (16 Bytes) mit 512-Bit-RSA-Public-Key - ganz leichte Aufgabe für die meisten Kryptographie-Bibliotheken mir bekannt, mit Ausnahme von MS CSP API, wie es scheint. Dokumentation für CryptEncrypt Funktion besagt, dass

  

Der Microsoft Enhanced Cryptographic Provider unterstützt die direkte Verschlüsselung mit RSA öffentlichen Schlüssel und die Entschlüsselung mit RSA privaten Schlüssel. Die Verschlüsselung verwendet PKCS # 1 Padding.

Es ist nicht, obwohl ich zu arbeiten. Nun, mein Code funktioniert und Datenblock erzeugt mit der richtigen Größe verschlüsselt, aber openssl versagt es zu entziffern. Es sieht aus wie CryptEncrypt noch symmetrische Chiffre verwendet wird.

Leider sind alle Beispiele, die ich gefunden habe, mit symmetrischen Chiffre für den kombinierten Kryptographie beziehen, so dass ich nicht über ein funktionierendes Beispiel auf den Händen, die auf jeden Fall die Dinge einfacher machen würde.

Könnte jemand zeigen Sie mir auf ein solches Beispiel bitte oder lassen Sie mich wissen, wenn es einige nicht so offensichtlich sind Fallen ich verpasst habe?

Danke.

War es hilfreich?

Lösung

Das klingt wie ein endianness Problem. Microsofts CryptEncrypt Funktion gibt den verschlüsselten Text in little-endian-Format, während OpenSSL seine Daten im big-endian-Format sein erwartet. Sie müssen die verschlüsselten Daten umkehren, bevor es zu OpenSSL vorbei.

Andere Tipps

Hier ist der Code (nur für den Fall, dass jemand dieses Thema aus gegoogelt hat):

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top