通过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。从表面上来看,非对称加密算法比对称加密算法多一个密钥,这就更安全一点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/265667.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32烧录口锁死问题解决

前言 我在给STM32单片机下载程序时&#xff0c;出现下载成功一次后&#xff0c;后面就下载不了了&#xff0c;识别不到下载器设备&#xff0c;经过排查&#xff0c;最终确认是代码配置有误&#xff0c;导致板子烧录口锁死&#xff0c;下面我将把问题的出现到问题的解决进行复现…

LZ码基本概念

LZ码是一种无损压缩算法&#xff0c;由Lempel和Ziv两位计算机科学家提出并命名。它是一种基于字典的压缩方法&#xff0c;可以将数据有效地压缩存储&#xff0c;同时实现高效的解压缩。 LZ码的基本概念是利用字典来存储先前遇到的字符串&#xff0c;然后用较短的代表符号来表示…

R软件包ConsensusCluster进行共识聚类(Consensus Clustering)

从下面论文看到这个方法&#xff1a; Wang, Xin, et al. "Deep learning using bulk RNA-seq data expands cell landscape identification in tumor microenvironment." Oncoimmunology 11.1 (2022): 2043662. 这篇论文基于 AI 方法对 bulk RNA-seq 数据识别肿瘤微环…

2023年12月GESP Python五级编程题真题解析

【五级编程题1】 【试题名称】&#xff1a;小杨的幸运数 【问题描述】 小杨认为&#xff0c;所有大于等于a的完全平方数都是他的超级幸运数。 小杨还认为&#xff0c;所有超级幸运数的倍数都是他的幸运数。自然地&#xff0c;小杨的所有超级幸运数也都是幸运数。 对于一个…

AI 视频 | 又一款 AI 视频工具火爆全网!DomoAI 实测体验如何?

一、引言 前几期介绍了几款常用的 AI 视频工具&#xff1a;Moonvalley、Runway Gen-2、Stable Video Diffusion&#xff0c;NeverEnds&#xff0c;对 AI 视频工具感兴趣的小伙伴可以移步之前的几篇文章。 程序员X小鹿&#xff1a;【AI视频】免费的 AI 视频生成工具 Moonvalley…

纯搬运 solidworks 2021卸载方法,怎么完全彻底卸载删除清理干净solidworks 2021各种残留注册表和文件?

纯搬运 solidworks 2021卸载方法&#xff0c;怎么完全彻底卸载删除清理干净solidworks 2021各种残留注册表和文件&#xff1f; 网址&#xff1a; solidworks 2021卸载方法&#xff0c;怎么完全彻底卸载删除清理干净solidworks 2021各种残留注册表和文件&#xff1f; solidworks…

js显示实时时间

文章目录 一、效果二、思路三、最后 一、效果 用JS实现XXXX年XX月XX日 星期X XX时XX分XX秒 效果 效果 &#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>time</title><script t…

基于Java SSM框架实现在线课程教育资源考试管理系统项目【项目源码+论文说明】

基于java的SSM框架实现在线课程教育资源考试管理系统演示 摘要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线教育资源管理系统&#xff0c;主要的模块包括管理员&#xff1b;个人中心、学生…

Android wifi基础知识点

1、什么是 CSMA/CA &#xff1f; 以太网用 CSMA/CD 进行传输控制&#xff0c;而 IEEE 802.11 的 WLAN 采用的是 CSMA/CA 。 CSMA/CD &#xff0c;全称 Carrier Sense Multiple Access with Collision Detection &#xff0c;即 载波侦听多路访问/冲突检测协议。 载波侦听(Ca…

Python课程设计-图书管理系统

Python课程设计-图书管理系统 摘要第一章 绪论1.1 开发环境及技术1.2 系统实现功能描述 第二章 功能详细设计与实现2.1 系统框架各层次实现2.1.1 可视页面设计2 数据库设计3 逻辑流程设计 2.2 主要功能的设计与实现1 功能 1用户登录2 功能 2展示图书3 功能 3添加图书4 功能 4删…

个性化邮件营销策略:提升销售额的有效方法

事实上&#xff0c;电子邮件营销人员一直将个性化视为让受众产生强烈参与感的最佳方式之一。对于很多营销人员来说&#xff0c;实施个性化甚至不再是一种选择&#xff0c;而是培养和吸引潜在客户和联系人的必要条件。因此&#xff0c;今天我们将一起来讨论一些成功电子邮件营销…

YZ系列工具之YZ03:高版本Excel的自定义菜单

我给VBA下的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套一部VBA手册&#xff0c;教程分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的…

整数规划-分支定界法

分支定界法 分支定界法由来分支定界法原理分支定界法思想疑惑or改进&#xff1f; 分支定界法由来 谨以此博客作为学习期间的记录 在生活中&#xff0c;整数规划(IP)或者混合整数规划(MIP)往往要比单纯的线性规划(LP)应用更为广泛。生产计划、库存规划等&#xff0c;都有着变量…

STL中优先队列的模拟实现与仿函数的介绍

文章目录 仿函数优先队列的模拟实现 仿函数 上回我们说到&#xff0c;优先队列的实现需要用到仿函数的特性 让我们再回到这里 这里我们发现他传入的用于比较的东西竟然是一个类模板&#xff0c;而不是我们所见到的函数 我们可以先创建一个类&#xff0c;用于比较大小 struc…

【toolschain algorithm cpp ros】cpp工厂模式实现--后续填充具体规划算法,控制器版的已填充了算法接入了仿真器

写在前面 现在局势危机&#xff0c;于是想复习一下之前写的设计模式&#xff0c;之前提到&#xff0c;做过一个闭环仿真器&#xff08;借用ros&#xff09;&#xff0c;见https://blog.csdn.net/weixin_46479223/article/details/134864123我的控制器的建立遵循了工厂模式&…

Excel 获取当前行的行数

ROW() 获取当前行 ROW()1 获取当前行然后支持二次开发

视频号小店一件代发怎么做?

我是电商珠珠 视频号团队于22年7月开始发展自己的电商平台-视频号小店。由于是新平台&#xff0c;并在今年开始有很多人关注。 所以平台相对来说并没有什么很严格的规则&#xff0c;特别是对于无货源一件代发这一块&#xff0c;没有什么成文的规定。 对于商家来说同样可以依…

阅读笔记-PRECISE ADJACENT MARGIN LOSS FOR DEEP FACE RECOGNITION

PRECISE ADJACENT MARGIN LOSS FOR DEEP FACE RECOGNITION 深度人脸识别的精确相邻边缘损失 1、这篇论文要解决什么问题&#xff1f;要验证一个什么科学假设&#xff1f; 问题&#xff1a;首先&#xff0c;在以往的损失函数中提到的“边际”是Softmax 决策边界之间的边际&am…

JDBC 知识点总结篇

JDBC 知识点总结篇 JDBC 接口 Java DataBase Connectivity Java数据库连接&#xff0c;由官方定义的一套操作所有关系型数据库的规则&#xff0c;即接口&#xff0c;各个数据库厂商实现该套接口 代码 // 本代码只提供一个样例&#xff0c;请根据自己实际情况修改代码 // 1.…

如何使用 NFTScan NFT API 在 Base 网络上开发 Web3 应用

Base 是 Coinbase 使用 OP Stack 开发的最新以太坊第 2 层&#xff08;L2&#xff09;网络&#xff0c;用于解决以太坊等主要区块链面临的可扩展性和成本挑战。Coinbase 将其描述为“安全、低成本、对开发人员友好的以太坊 L2&#xff0c;旨在将下一个 10 亿用户带入 Web3”。B…