我需要使用X.509 RSA公钥加密消息。我成功导入了DER格式的1024位公钥,但我的程序失败,消息长度大于110字节。我正在调用CryptEncrypt
函数并将pbData
设置为NULL,因为我需要先计算输出缓冲区的大小。
这是源代码:
纯文本版本相同:
bool CCrypt::RSAEncrypt() {
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
CParam *pubKey = coreData.local.overlay->getItem(3);
// Decode the binary key blob in DER format into a CERT_PUBLIC_KEY_INFO
CERT_PUBLIC_KEY_INFO* publicKeyInfo = NULL;
DWORD publicKeyInfoSize;
if (CryptDecodeObjectEx(
X509_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
(LPBYTE) pubKey->getVal(),
pubKey->getLength(),
CRYPT_DECODE_ALLOC_FLAG/* | CRYPT_DECODE_NOCOPY_FLAG*/,
NULL, // TODO: Pass a CRYPT_DECODE_PARA to use own heap management to allocate memory
&publicKeyInfo,
&publicKeyInfoSize
)) {
// Import the public using the context
if (CryptImportPublicKeyInfo(
hProv,
X509_ASN_ENCODING,
publicKeyInfo,
&hKey
)) {
// Get the size of a key
DWORD dwBlockLen = NULL;
DWORD dwValLen = sizeof(DWORD);
if (CryptGetKeyParam(hKey, KP_BLOCKLEN, (LPBYTE) &dwBlockLen, &dwValLen, 0)) {
dwBlockLen = (dwBlockLen + 7) / 8; // Transform to bytes legth
BYTE msg[] = "Lorem ipsum dolor sit .... [3000+ characters here]";
DWORD dwMsgLen = I(str)->lengthA((LPSTR) msg);
//dwMsgLen = 110;
DBG(C_INFO, "CryptGetKeyParam succeed. dwMsgLen: %d, dwBlockLen: %d", dwMsgLen, dwBlockLen);
// pbData [in, out] set to NULL to calculate actual size of a buffer required
if (CryptEncrypt(hKey, 0, TRUE, CRYPT_OAEP, NULL, &dwMsgLen, 0)) {
DBG(C_INFO, "CryptEncrypt succeed. dwMsgLen: %d", dwMsgLen);
// TODO: Fails here
} else {
DBG(C_ERROR, "CryptEncrypt error.");
}
} else {
DBG(C_ERROR, "CryptGetKeyParam error.");
}
CryptDestroyKey(hKey);
}
LocalFree(publicKeyInfo);
}
CWA(advapi32, CryptReleaseContext)(hProv, 0);
}
return false;
}
bool CCrypt::RSAEncrypt() {
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
CParam *pubKey = coreData.local.overlay->getItem(3);
// Decode the binary key blob in DER format into a CERT_PUBLIC_KEY_INFO
CERT_PUBLIC_KEY_INFO* publicKeyInfo = NULL;
DWORD publicKeyInfoSize;
if (CryptDecodeObjectEx(
X509_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
(LPBYTE) pubKey->getVal(),
pubKey->getLength(),
CRYPT_DECODE_ALLOC_FLAG/* | CRYPT_DECODE_NOCOPY_FLAG*/,
NULL, // TODO: Pass a CRYPT_DECODE_PARA to use own heap management to allocate memory
&publicKeyInfo,
&publicKeyInfoSize
)) {
// Import the public using the context
if (CryptImportPublicKeyInfo(
hProv,
X509_ASN_ENCODING,
publicKeyInfo,
&hKey
)) {
// Get the size of a key
DWORD dwBlockLen = NULL;
DWORD dwValLen = sizeof(DWORD);
if (CryptGetKeyParam(hKey, KP_BLOCKLEN, (LPBYTE) &dwBlockLen, &dwValLen, 0)) {
dwBlockLen = (dwBlockLen + 7) / 8; // Transform to bytes legth
BYTE msg[] = "Lorem ipsum dolor sit .... [3000+ characters here]";
DWORD dwMsgLen = I(str)->lengthA((LPSTR) msg);
//dwMsgLen = 110;
DBG(C_INFO, "CryptGetKeyParam succeed. dwMsgLen: %d, dwBlockLen: %d", dwMsgLen, dwBlockLen);
// pbData [in, out] set to NULL to calculate actual size of a buffer required
if (CryptEncrypt(hKey, 0, TRUE, CRYPT_OAEP, NULL, &dwMsgLen, 0)) {
DBG(C_INFO, "CryptEncrypt succeed. dwMsgLen: %d", dwMsgLen);
// TODO: Fails here
} else {
DBG(C_ERROR, "CryptEncrypt error.");
}
} else {
DBG(C_ERROR, "CryptGetKeyParam error.");
}
CryptDestroyKey(hKey);
}
LocalFree(publicKeyInfo);
}
CWA(advapi32, CryptReleaseContext)(hProv, 0);
}
return false;
}
我的调试器输出:
[16:08:14] TC=1093889010, PID=25484(0x638C), TID=26340(0x66E4), LE=0(0x0), F=CCrypt::RSAEncrypt, FL=d:\c\source\client\../common/Crypt.cpp (62)
INFO: CryptGetKeyParam succeed. dwMsgLen: 2175, dwBlockLen: 128
[16:08:14] TC=1093889010, PID=25484(0x638C), TID=26340(0x66E4), LE=2148073476(0x80090004), F=CCrypt::RSAEncrypt, FL=d:\c\source\client\../common/Crypt.cpp (69)
ERROR: CryptEncrypt error.
如您所见,此函数在CryptEncrypt失败,错误为NTE_BAD_LEN(0x80090004)。但是,当我手动将[16:08:14] TC=1093889010, PID=25484(0x638C), TID=26340(0x66E4), LE=0(0x0), F=CCrypt::RSAEncrypt, FL=d:\c\source\client\../common/Crypt.cpp (62)
INFO: CryptGetKeyParam succeed. dwMsgLen: 2175, dwBlockLen: 128
[16:08:14] TC=1093889010, PID=25484(0x638C), TID=26340(0x66E4), LE=2148073476(0x80090004), F=CCrypt::RSAEncrypt, FL=d:\c\source\client\../common/Crypt.cpp (69)
ERROR: CryptEncrypt error.
设置为110 [见第61行]时,它可以正常工作。当我将此变量设置为120时,它会失败。
有人可以告诉我问题出在哪里吗?