我需要使用512位RSA公钥加密一小块数据(16字节) - 对于我所知的大多数加密库来说,这是一项非常简单的任务,除了MS CSP API之外,它似乎也是如此.CryptEncrypt函数的文档说明了这一点
Microsoft增强加密提供程序支持使用RSA公钥进行直接加密,并使用RSA私钥进行解密.加密使用PKCS#1填充.
但它对我没用.好吧,我的代码工作并生成具有正确大小的加密数据块,但是openssl无法对其进行decypher.它看起来很像CryptEncrypt仍然使用对称密码.
不幸的是,我发现的所有例子都是指带有对称密码的组合密码术,所以我手上没有一个工作示例,这肯定会让事情变得更容易.
可以请任何人指出我这样的例子或让我知道是否有一些我错过的明显陷阱?
谢谢.
这听起来像一个字节序问题.Microsoft的CryptEncrypt函数以little-endian格式返回密文,而OpenSSL期望其数据采用big-endian格式.在将加密数据传递给OpenSSL之前,您需要将其反转.
这是代码(以防万一有人用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, "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