CryptEncrypt失败,NTE_BAD_LEN

时间:2014-05-14 14:16:22

标签: winapi rsa public-key-encryption cryptoapi x509

我需要使用X.509 RSA公钥加密消息。我成功导入了DER格式的1024位公钥,但我的程序失败,消息长度大于110字节。我正在调用CryptEncrypt函数并将pbData设置为NULL,因为我需要先计算输出缓冲区的大小。

这是源代码:

screenshot

纯文本版本相同:

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时,它会失败。

有人可以告诉我问题出在哪里吗?

0 个答案:

没有答案