通过windows cng api 实现rsa非对称加密

参考:

1,使用 CNG 加密数据 - Win32 apps | Microsoft Learn

2,不记得了

  (下文通过cng api演示rsa加密,不做原理性介绍)   

      相对于aes等对称加密算法,rsa加密算法不可逆性更强。非对称加密在通常情况下,使用公钥对数据进行加密之后,如果没有私钥,基本是不可能实现解密的。在一些勒索程序中,非对称加密会经常出现;这里算是填个坑吧。

     下面代码实现:

      1,rsa加密

      2,公钥/私钥导出

#define RsaKeyLen 2048

HRESULT bthr(BOOL b)
{
    return b ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}


//确实不需要直接从 BCryptExportKey 或 NCryptExportKey 进行 base64 编码输出,但需要执行额外的步骤 :
//
//使用 BCryptExportKey(或 NCryptExportKey) BCRYPT_RSAFULLPRIVATE_BLOB(但不是 BCRYPT_RSAPRIVATE_BLOB)或 BCRYPT_RSAPUBLIC_BLOB
//对生成的 BCRYPT_RSAKEY_BLOB 进行编码 CNG_RSA_PRIVATE_KEY_BLOB 或 CNG_RSA_PUBLIC_KEY_BLOB 并放入 CRYPT_PRIVATE_KEY_INFO
//使用 PKCS_PRIVATE_KEY_INFO 对 CRYPT_PRIVATE_KEY_INFO 进行编码 >
//调用CryptBinaryToStringA


HRESULT ExportToPem(_In_ BCRYPT_KEY_HANDLE hKey, BOOL bPrivate, _Out_ PSTR* ppsz, _Out_ PULONG pcch)
{
    HRESULT hr;
    CRYPT_PRIVATE_KEY_INFO PrivateKeyInfo = { 0, {const_cast<PSTR>(szOID_RSA_RSA)} };
    CERT_PUBLIC_KEY_INFO   PublicKeyInfo = { {const_cast<PSTR>(szOID_RSA_RSA)} };
  
    ULONG cbKey = 0;
    PUCHAR pbKey = 0;//really PBCRYPT_RSAKEY_BLOB

    PCWSTR pszBlobType;
    PCSTR lpszStructType;

    if (bPrivate)
    {
        pszBlobType = BCRYPT_RSAFULLPRIVATE_BLOB;
        lpszStructType = CNG_RSA_PRIVATE_KEY_BLOB;
    }
    else
    {
        pszBlobType = BCRYPT_RSAPUBLIC_BLOB;
        lpszStructType = CNG_RSA_PUBLIC_KEY_BLOB;
    }

    while (0 <= (hr = BCryptExportKey(hKey, 0, pszBlobType, pbKey, cbKey, &cbKey, 0)))
    {
        if (pbKey)
        {
            if (bPrivate)
            {
                if (0 <= (hr = bthr(CryptEncodeObjectEx(
                    X509_ASN_ENCODING,
                    lpszStructType,
                    pbKey, 
                    CRYPT_ENCODE_ALLOC_FLAG, 
                    0,
                    &PrivateKeyInfo.PrivateKey.pbData,
                    &PrivateKeyInfo.PrivateKey.cbData))))
                {
                    hr = bthr(CryptEncodeObjectEx(
                        X509_ASN_ENCODING, 
                        PKCS_PRIVATE_KEY_INFO,
                        &PrivateKeyInfo, 
                        CRYPT_ENCODE_ALLOC_FLAG,
                        0,
                        &pbKey, 
                        &cbKey));

                    LocalFree(PrivateKeyInfo.PrivateKey.pbData);
                }
            }
            else
            {
                //public key
                if (0 <= (hr = bthr(CryptEncodeObjectEx(
                    X509_ASN_ENCODING,
                    lpszStructType, 
                    pbKey, 
                    CRYPT_ENCODE_ALLOC_FLAG, 
                    0,
                    &PublicKeyInfo.PublicKey.pbData,
                    &PublicKeyInfo.PublicKey.cbData))))
                {
                    hr = bthr(CryptEncodeObjectEx(
                        X509_ASN_ENCODING,
                        X509_PUBLIC_KEY_INFO,
                        &PublicKeyInfo, 
                        CRYPT_ENCODE_ALLOC_FLAG, 
                        0,
                        &pbKey, 
                        &cbKey));

                    LocalFree(PublicKeyInfo.PublicKey.pbData);
                }
            }

            if (0 <= hr)
            {
                PSTR psz = 0;
                ULONG cch = 0;
                while (0 <= (hr = bthr(CryptBinaryToStringA(
                    pbKey,
                    cbKey,
                    CRYPT_STRING_BASE64HEADER, //CRYPT_STRING_BASE64HEADER without the "---------BEGIN CERTIFICATE---------"
                    psz,
                    &cch))))
                {
                    if (psz)
                    {
                        *ppsz = psz, * pcch = cch;
                        break;
                    }

                    if (!(psz = (PSTR)LocalAlloc(0, cch)))
                    {
                        hr = HRESULT_FROM_WIN32(GetLastError());
                        break;
                    }
                }

                LocalFree(pbKey);
            }

            break;
        }

        pbKey = (PUCHAR)malloc(cbKey);
    }

    return hr;
}

BOOL DecryptAnd(BCRYPT_KEY_HANDLE hKey, PUCHAR pbData, ULONG cbData)
{
    UCHAR buf[0x1000] = { 0 };
    ULONG pbcResult = 0;
    NTSTATUS status = 0;

    if (!NT_SUCCESS(BCryptDecrypt(
        hKey,
        pbData,
        cbData,
        NULL,
        NULL,
        0,
        buf,
        0x1000,
        &pbcResult,
        BCRYPT_PAD_PKCS1)))
    {
        wprintf(L"BCryptDecrypt fail,error:%d\n", GetLastError());
        goto end;
    }

    //print cipher text
    PrintBytes(buf, pbcResult);

end:
    return status == 0 ? TRUE : FALSE;
}

BOOL EncryptAnd(BCRYPT_KEY_HANDLE hKey, PUCHAR pbData, ULONG cbData)
{
    UCHAR buf[0x1000] = { 0 };
    ULONG pbcResult = 0;
    NTSTATUS status = 0;

    printf("plain text length:%d\n", cbData);

    if (!NT_SUCCESS(BCryptEncrypt(
        hKey,
        pbData,
        cbData,
        NULL,
        NULL,
        0,
        buf,
        0x1000,
        &pbcResult,
        BCRYPT_PAD_PKCS1)))
    {
        wprintf(L"BCryptEncrypt fail,error:%d\n", GetLastError());
        goto end;
    }

    //print cipher text
    printf("cipher text length:%d\n", pbcResult);

    PrintBytes(buf, pbcResult);

    printf("begin to decrypt \n");
    //begin to decrypt
    DecryptAnd(hKey, buf, pbcResult);

end:
    return status == 0 ? TRUE : FALSE;
}





void UnsymmetricEncrypt()
{
    NTSTATUS status =0;
    BCRYPT_ALG_HANDLE hAlgRsa=NULL;
    BCRYPT_KEY_HANDLE hRsaKey=NULL;

    DWORD rsaPublicKeyLen = (RsaKeyLen) * 2;
    UCHAR rsaPublicKey[(RsaKeyLen) * 2] = { 0 };
    UCHAR rsaPrivateKey[(RsaKeyLen) * 2] = { 0 };
    ULONG cbResult = 0;
    PSTR PublicKey = NULL;
    PSTR PrivateKey = NULL;

    UCHAR plainText[0x20] = "abcdefghijklm";

    //opne rsa algorithm provider
    if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
        &hAlgRsa,
        BCRYPT_RSA_ALGORITHM,
        NULL,
        0)))
    {
        wprintf(L"BCryptOpenAlgorithmProvider fail,error:%d\n", GetLastError());
        goto end;
   }

    //generate key pair 
    if (!NT_SUCCESS(status = BCryptGenerateKeyPair(
        hAlgRsa,
        &hRsaKey,
        RsaKeyLen,
        0
    )))
    {
        wprintf(L"BCryptGenerateKeyPair fail,error:%d\n", GetLastError());
        goto end;
    }

    //finalize
    if (!NT_SUCCESS(status = BCryptFinalizeKeyPair(
        hRsaKey,
        0)))
    {
        wprintf(L"BCryptFinalizeKeyPair fail,error:%d\n",GetLastError());
        goto end;
    }

    //encrypt and decrypt
    EncryptAnd(hRsaKey, plainText, 13);
    printf("\n");

    if (!NT_SUCCESS(status = BCryptExportKey(
        hRsaKey,
        NULL,
        BCRYPT_RSAPUBLIC_BLOB,
        rsaPublicKey,
        rsaPublicKeyLen,
        &cbResult,
        0)))
    {
        wprintf(L"BCryptExportKey fail,error:%d\n", GetLastError());
        goto end;
    }
    else
    {
        //printf public key
        //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, 0xb4, 0x7a, 0xb0, 0x43, 0xee,
        //0x48, 0xbf, 0x53, 0x05, 0x60, 0xe3, 0x0e, 0xd9, 0xe2, 0x52, 0xa3, 0xb2, 0xef, 0x08, 0x20, 0xef,
        //0xe4, 0x39, 0x40, 0xb7, 0xf9, 0xf3, 0x72, 0xe5, 0xf7, 0x3c, 0x25, 0x7e, 0x88, 0xe8, 0xe8, 0x9a,
        //0x13, 0x67, 0xca, 0x5d, 0x45, 0xd6, 0x33, 0x6f, 0x9d, 0xda, 0xcc, 0xae, 0x07, 0x44, 0x2c, 0x11,
        //0x5c, 0x82, 0xdf, 0xe9, 0x87, 0xd9, 0xf0, 0xcd, 0xb7, 0xb2, 0xc1,
        printf("rsa public key blob:\n");
        PrintBytes(rsaPublicKey, cbResult);

        //if (S_OK != ExportToPem(
        //    hRsaKey,
        //    TRUE,
        //    &PrivateKey,
        //    &cbResult))
        //{
        //    wprintf(L"ExportToPem PrivateKey fail!\n");
        //    goto end;
        //}

        if (S_OK != ExportToPem(
            hRsaKey,
            FALSE,
            &PublicKey,
            &cbResult))
        {
            wprintf(L"ExportToPem PrivateKey fail!\n");
            goto end;
        }

        printf("\npublic key in pem:\n%s\n", PublicKey);
        //printf("private key in pem:\n%s\n", PrivateKey);
    }

    wprintf(L"\n UnsymmetricEncrypt success!\n");
end:
    if (hAlgRsa)
    {
        BCryptCloseAlgorithmProvider(hAlgRsa, 0);
    }
    if (hRsaKey)
    {
        BCryptDestroyKey(hRsaKey);
    }
}

运行结果如下图:

第一次运行

                                                                  第二次运行

通过运行结果可以看出,调用系统cng api 每次生成的密钥对都不一样,这就很ok。从表面上来看,非对称加密算法比对称加密算法多一个密钥,这就更安全一点。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值