2008-11-17 23 views
2

我需要加密使用512位的RSA公鑰數據(16個字節)的一小塊 - 除了MS CSP API,用於已知最深的密碼庫的相當容易的事,因爲它似乎。 的文檔CryptEncrypt功能指出如何使用Microsoft ECSP僅使用RSA公鑰加密小數據塊?

的Microsoft增強加密提供支持與RSA公共密鑰和解密使用RSA私鑰加密直接。加密使用PKCS#1填充。

它沒有工作對我來說雖然。那麼,我的代碼工作併產生具有正確大小的加密數據塊,但openssl無法解密它。它看起來很像CryptEncrypt仍然使用對稱密碼。

不幸的是所有我發現的例子是指具有對稱CYPHER結合加密技術,所以我沒有動手,這肯定會使事情變得更容易的工作示例。

能取悅任何人點我這樣的例子還是讓我知道,如果有一些不我已經錯過了明顯的缺陷?

謝謝。

回答

8

這聽起來像一個endianness問題。微軟的CryptEncrypt函數返回小尾數格式的密文,而OpenSSL的預計,其數據是在big-endian格式。在將它傳遞給OpenSSL之前,您需要反轉加密的數據。

+0

賓果。 謝謝你指出。 陷阱太明顯了:) – 2008-11-18 09:52:21

7

下面的代碼(以防萬一有人用Google搜索這個話題了):

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, "", 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