BCryptDecrypt 因 STATUS_INVALID_PARAMETER 失败

问题描述 投票:0回答:2

我正在尝试使用 Windows api cng 的 Bcrypt 库对缓冲区进行 RSA 加密。但是我第一次打电话给

BCryptDecrypt
失败了
STATUS_INVALID_PARAMETER
...

    status = BCryptDecrypt(
        hKey,
        pbEncryptedBuffer,
        cbEncryptedBuffer,
        NULL,
        NULL,
        0,
        NULL,
        0,
        pcbDecryptedBuffer,
        BCRYPT_PAD_PKCS1);

我看了这些例子:
如何使用BCrypt进行RSA(非对称加密) https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/007a0e26-7fc0-4079-9b63-2ad23f866836/bug-in-rsa-encryptiondecryption-using-cng?forum=windowssdk
考虑到我需要填充。但是,如果我删除

BCRYPT_PAD_PKCS1
参数,那么第一次调用
BCryptDecrypt
就会成功。然后,无论
BCryptDecrypt
标志是否存在,第二次调用
STATUS_INVALID_PARAMETER
都会失败并显示
BCRYPT_PAD_PKCS1

下面是完整代码:

#include <windows.h>
#include <bcrypt.h>
#include <winternl.h>
#include <stdio.h>

#pragma comment(lib, "Bcrypt.lib")

#define NT_SUCCESS(Status)          (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL         ((NTSTATUS)0xC0000001L)

BOOL Encrypt(PBYTE pbPrivKey, DWORD cbPrivKey, PBYTE pbInputData, DWORD cbInputData,
             BYTE** ppbEncryptedBuffer, PDWORD pcbEncryptedBuffer)
{
    BOOL bRet = TRUE;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    BCRYPT_ALG_HANDLE hAlgorithm = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;

    ///
    // Open provider.
    ///
    status = BCryptOpenAlgorithmProvider(
        &hAlgorithm,
        BCRYPT_RSA_ALGORITHM,
        NULL,
        0);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

    ///
    // Import private key.
    ///
    status = BCryptImportKeyPair(hAlgorithm,
        NULL,
        BCRYPT_RSAPRIVATE_BLOB,
        &hKey,
        pbPrivKey,
        cbPrivKey,
        BCRYPT_NO_KEY_VALIDATION);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

    ///
    // Get encrypted buffer size.
    ///
    status = BCryptEncrypt(
        hKey,
        pbInputData,
        cbInputData,
        NULL,
        NULL,
        0,
        NULL,
        0,
        pcbEncryptedBuffer,
        BCRYPT_PAD_PKCS1);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptEncrypt\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

    ///
    // Encrypt buffer.
    ///
    *ppbEncryptedBuffer = HeapAlloc(GetProcessHeap(), 0, *pcbEncryptedBuffer);
    if (*ppbEncryptedBuffer == NULL)
    {
        wprintf(L"**** Error 0x%x returned by HeapAlloc\n", GetLastError());
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

    status = BCryptEncrypt(hKey,
        pbInputData,
        cbInputData,
        NULL,
        NULL,
        0,
        *ppbEncryptedBuffer,
        *pcbEncryptedBuffer,
        pcbEncryptedBuffer,
        BCRYPT_PAD_PKCS1);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptEncrypt\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

LBL_CLEANUP:

    if (hAlgorithm)
        BCryptCloseAlgorithmProvider(hAlgorithm, 0);

    if (hKey)
        BCryptDestroyKey(hKey);

    return bRet;
}

BOOL Decrypt(PBYTE pbPubKey, DWORD cbPubKey, PBYTE pbEncryptedBuffer, DWORD cbEncryptedBuffer,
             BYTE** ppbDecryptedBuffer, PDWORD pcbDecryptedBuffer)
{
    BOOL bRet = TRUE;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    BCRYPT_ALG_HANDLE hAlgorithm = NULL;
    BCRYPT_KEY_HANDLE hKey = NULL;

    ///
    // Open provider.
    ///
    status = BCryptOpenAlgorithmProvider(
        &hAlgorithm,
        BCRYPT_RSA_ALGORITHM,
        NULL,
        0);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

    ///
    // Import public key.
    ///
    status = BCryptImportKeyPair(hAlgorithm,
        NULL,
        BCRYPT_RSAPUBLIC_BLOB,
        &hKey,
        pbPubKey,
        cbPubKey,
        BCRYPT_NO_KEY_VALIDATION);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }
    
    ///
    // Get decrypted buffer size.
    ///
    status = BCryptDecrypt(
        hKey,
        pbEncryptedBuffer,
        cbEncryptedBuffer,
        NULL,
        NULL,
        0,
        NULL,
        0,
        pcbDecryptedBuffer,
        BCRYPT_PAD_PKCS1);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptDecrypt\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

    ///
    // Decrypt buffer.
    ///
    *ppbDecryptedBuffer = HeapAlloc(GetProcessHeap(), 0, *pcbDecryptedBuffer);
    if (*ppbDecryptedBuffer == NULL)
    {
        wprintf(L"**** Error 0x%x returned by HeapAlloc\n", GetLastError());
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

    status = BCryptDecrypt(
        hKey,
        pbEncryptedBuffer,
        cbEncryptedBuffer,
        NULL,
        NULL,
        0,
        *ppbDecryptedBuffer,
        *pcbDecryptedBuffer,
        pcbDecryptedBuffer,
        BCRYPT_PAD_PKCS1);
    if (!NT_SUCCESS(status))
    {
        wprintf(L"**** Error 0x%x returned by BCryptDecrypt\n", status);
        bRet = FALSE;
        goto LBL_CLEANUP;
    }

LBL_CLEANUP:

    if (hAlgorithm)
        BCryptCloseAlgorithmProvider(hAlgorithm, 0);

    if (hKey)
        BCryptDestroyKey(hKey);

    return bRet;
}

BYTE PubKey[91] = {
    0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x01, 0xD5, 0x0F, 0xFD, 0x75, 0xA3, 0xDC, 0xCD, 0xCA, 0xC1,
    0x38, 0xBB, 0x3A, 0x8F, 0x6F, 0xC5, 0x53, 0xF7, 0xAC, 0x29, 0x5E, 0x14,
    0xF5, 0x95, 0xA1, 0x76, 0xAA, 0xD0, 0xAB, 0xAA, 0x4E, 0x02, 0xFE, 0x28,
    0xF5, 0xE0, 0xD7, 0xAC, 0x2E, 0x23, 0x5B, 0x20, 0x53, 0x22, 0x0D, 0x78,
    0x33, 0x2B, 0x05, 0x93, 0xF7, 0xD2, 0x28, 0x24, 0xD4, 0x48, 0xC5, 0xEE,
    0x1B, 0xE7, 0x41, 0x2E, 0x1A, 0x05, 0x7D
};

BYTE PrivKey[155] = {
    0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
    0x40, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x01, 0xD5, 0x0F, 0xFD, 0x75, 0xA3, 0xDC, 0xCD, 0xCA, 0xC1,
    0x38, 0xBB, 0x3A, 0x8F, 0x6F, 0xC5, 0x53, 0xF7, 0xAC, 0x29, 0x5E, 0x14,
    0xF5, 0x95, 0xA1, 0x76, 0xAA, 0xD0, 0xAB, 0xAA, 0x4E, 0x02, 0xFE, 0x28,
    0xF5, 0xE0, 0xD7, 0xAC, 0x2E, 0x23, 0x5B, 0x20, 0x53, 0x22, 0x0D, 0x78,
    0x33, 0x2B, 0x05, 0x93, 0xF7, 0xD2, 0x28, 0x24, 0xD4, 0x48, 0xC5, 0xEE,
    0x1B, 0xE7, 0x41, 0x2E, 0x1A, 0x05, 0x7D, 0xF3, 0x4A, 0xE4, 0x0A, 0xF6,
    0xCA, 0xBC, 0xB6, 0xE2, 0x10, 0xF3, 0x9F, 0x8D, 0x3B, 0x07, 0x7D, 0x83,
    0x59, 0x51, 0xAA, 0x3C, 0xBA, 0x89, 0x2C, 0xCF, 0x69, 0x29, 0x8D, 0x96,
    0x2C, 0x80, 0x67, 0xE0, 0x30, 0xE3, 0x27, 0xDC, 0x2C, 0x85, 0xF3, 0x8B,
    0x47, 0xB0, 0x10, 0xC2, 0x49, 0x09, 0x14, 0x15, 0x47, 0x90, 0xAF, 0x5C,
    0xF1, 0x3D, 0x4C, 0x6D, 0x88, 0xAB, 0x98, 0x7B, 0x80, 0x8C, 0x7B
};

BYTE Msg[10] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A };

int main()
{
    BOOL bRet = TRUE;

    PBYTE pbEncryptedMessage = NULL;
    DWORD cbEncryptedMessage = 0;
    PBYTE pbDecryptedMessage = NULL;
    DWORD cbDecryptedMessage = 0;

    bRet = Encrypt(
        PrivKey, 
        sizeof(PrivKey), 
        Msg, 
        sizeof(Msg), 
        &pbEncryptedMessage, 
        &cbEncryptedMessage);
    if (bRet == FALSE)
    {
        wprintf(L"**** Error FALSE returned by Encrypt\n");
        goto LBL_CLEANUP;
    }
    wprintf(L"Encryption Success!\n");

    bRet = Decrypt(
        PubKey, 
        sizeof(PubKey), 
        pbEncryptedMessage, 
        cbEncryptedMessage, 
        &pbDecryptedMessage, 
        &cbDecryptedMessage);
    if (bRet == FALSE)
    {
        wprintf(L"**** Error FALSE returned by Decrypt\n");
        goto LBL_CLEANUP;
    }
    wprintf(L"Decryption Success!\n");

LBL_CLEANUP:

    if (pbEncryptedMessage)
        HeapFree(GetProcessHeap(), 0, pbEncryptedMessage);

    if (pbDecryptedMessage)
        HeapFree(GetProcessHeap(), 0, pbDecryptedMessage);
}```
c winapi encryption bcrypt cng
2个回答
1
投票

我看不懂,我回答了两次这个问题,每次我的评论都被版主删除了。如果您是版主,请在删除之前添加评论说明您认为我的答案不正确的原因。 我再次复制答案,因为我确定它是正确的。

问候,

米歇尔·特里斯 当然你可以删除这个


1
投票

NCryptDecrypt
无法解密缓冲区时返回
STATUS_INVALID_PARAMETER
;这并不意味着您的参数无效。

在您的情况下,您使用私钥加密并使用公钥解密。尝试相反的方法,它会起作用。

这是发生了什么:私钥的句柄实际上知道私钥和公钥,如果您使用它来加密,则使用公钥而不是预期的私钥。只需测试一下:获取应该只是私钥的句柄,并使用相同的句柄解密,它可以工作。它已使用公钥加密并使用私钥解密。

© www.soinside.com 2019 - 2024. All rights reserved.