Cryptography 如何使用Microsoft ECSP仅使用RSA公钥加密小数据块?

Cryptography 如何使用Microsoft ECSP仅使用RSA公钥加密小数据块?,cryptography,rsa,cryptoapi,Cryptography,Rsa,Cryptoapi,我需要使用512位RSA公钥对一小块数据(16字节)进行加密——对于我所知的大多数加密库来说,这是一项相当简单的任务,但MSCSPAPI似乎除外。 函数的文档说明 Microsoft增强型加密提供程序支持使用RSA公钥直接加密和使用RSA私钥解密。加密使用PKCS#1填充 但这对我不起作用。好吧,我的代码可以工作并生成大小正确的加密数据块,但openssl无法解密它。看起来CryptEncrypt仍然使用对称密码 不幸的是,我发现的所有例子都提到了使用对称密码的组合密码术,所以我手头上没有一个可

我需要使用512位RSA公钥对一小块数据(16字节)进行加密——对于我所知的大多数加密库来说,这是一项相当简单的任务,但MSCSPAPI似乎除外。 函数的文档说明

Microsoft增强型加密提供程序支持使用RSA公钥直接加密和使用RSA私钥解密。加密使用PKCS#1填充

但这对我不起作用。好吧,我的代码可以工作并生成大小正确的加密数据块,但openssl无法解密它。看起来CryptEncrypt仍然使用对称密码

不幸的是,我发现的所有例子都提到了使用对称密码的组合密码术,所以我手头上没有一个可以让事情变得更简单的有效例子

请任何人给我举一个这样的例子,或者让我知道我是否遗漏了一些不太明显的陷阱

谢谢。

这听起来像个问题。微软的函数以小端格式返回密文,而OpenSSL则希望其数据采用大端格式。在将加密数据传递给OpenSSL之前,您需要将其反转。

以下是代码(以防有人用谷歌搜索出此主题):

BYTE*spkiData=SPKI;//X.509 ASN.1编码主题PublicKeyInfo
DWORD dwSPKISize=SPKI_SIZE;//RSA为94字节
DWORD dwBufSize=0;
//获取已解码spki结构的缓冲区大小
CryptDecodeObject(X509_ASN_编码、X509_公钥_信息、spkiData、dwSPKISize、0、NULL和dwBufSize);
字节*decBuf=新字节[dwBufSize];
CryptDecodeObject(X509_ASN_编码、X509_公钥_信息、spkiData、dwSPKISize、0、decBuf和dwBufSize);
//现在解码RSA公钥本身
证书公开密钥信息*spki=(证书公开密钥信息*)decBuf;
//获取已解码公钥结构的缓冲区大小
CryptDecodeObject(X509_ASN_编码、RSA_CSP_PUBLICKEYBLOB、spki->PublicKey.pbData、spki->PublicKey.cbData、0、0和dwBufSize);
//获取RSA公钥blob
BYTE*blobBuf=新字节[dwBufSize];
CryptDecodeObject(X509_ASN_编码、RSA_CSP_PUBLICKEYBLOB、spki->PublicKey.pbData、spki->PublicKey.cbData、0、blobBuf和dwBufSize);
//获取加密提供程序上下文
HCRYPTPROV HCRYPTPROV=NULL;
CryptAcquireContext(&hCryptProv,0,MS_增强型_PROV,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT);
//导入密钥
HCRYPTKEY=NULL;
CryptImportKey(hCryptProv、blobBuf、dwBufSize、0、0和key);
//获取密钥大小
DWORD dwKeySize;
DWORD dwParamSize=sizeof(DWORD);
CryptGetKeyParam(key,KP_KEYLEN,(BYTE*)&dwKeySize和dwParamSize,0);
//为了方便起见,我们需要用字节表示
dwKeySize/=8;
//现在有趣了
//分配一个密钥大小的缓冲区
字节*数据=新字节[dwKeySize];
//复制数据需要加密
//对于PKCS#1填充,数据长度不能超过keysize-11字节
DWORD dataLen=16;
memcpy(数据,“0123456789012345”,数据长度);
CryptEncrypt(key、0、TRUE、0、data和dataLen、dwKeySize)
//现在将其转换为big endian(适用于世界其他地区)
对于(int i=0;i<(dwKeySize/2);i++){
字节c=数据[i];
数据[i]=数据[dwKeySize-1-i];
数据[dwKeySize-1-i]=c;
}
//现在数据指向RSA PKCS#v1.5加密数据的dwKeySize长度块

Bingo。谢谢你指出这一点。陷阱太明显了:)
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