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

news2025/1/21 16:37:17

参考:

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

玩转大数据22:常见的关联规则挖掘算法

引言 关联规则挖掘是数据挖掘中的一种重要技术&#xff0c;主要用于发现数据集中项之间的有趣关系。关联规则挖掘在许多领域都有广泛的应用&#xff0c;如市场篮子分析、推荐系统等。常见的关联规则挖掘算法包括Apriori算法和FP-Growth算法。 一、Apriori算法 关联规则挖掘是…

Java中的抽象abstract

抽象abstract 什么是抽象类抽象类的注意事项、特点 使用好处常见应用场景&#xff1a;模版方法设计模式可以使用final关键字修饰模版方法 什么是抽象类 在Java中有一个关键字叫:abstract&#xff0c;它就是抽象的意思&#xff0c;可以用它修饰类、成员方法。abstract修饰类&am…

python读取Excel内容并展示成json

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 伙伴们&#xff0c;又是许久未曾见面了。最近也是在忙着加班&#xff0c;加上没有新技术的输入和产出&…

SpaceDesk如何连接平板/PC(生产力副屏)

1、下载安装 分为安卓端和PC端&#xff0c;两个设备都需要安装对应的软件。 SpaceDesk官网 https://link.zhihu.com/?targethttp%3A//spacedesk.net/ 需要魔法上网。安装过程比较简单&#xff0c;无脑下一步即可。 我已经把安装包准备好了&#xff0c;如果不想自己找&#…

公众号申请已达上限解决方法

一般可以申请多少个公众号&#xff1f;自2018年11月16日起&#xff0c;进行申请上限调整&#xff1a;1、同一个邮箱只能申请1个公众号&#xff1b;2、同一个手机号码可绑定5个公众号&#xff1b;3、同一身份证申请个人类型公众号数量上限为1个&#xff1b;4、同一企业、个体工商…

WebAssembly 的魅力:高效、安全、跨平台(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

ElasticSearch学习篇9_文本相似度计算方法现状以及基于改进的 Jaccard 算法代码实现

背景 XOP亿级别题库的试题召回以及搜题的举一反三业务场景都涉及使用文本相似搜索技术&#xff0c;学习此方面技术以便更好的服务于业务场景。 目前基于集合的Jaccard算法以及基于编辑距离的Levenshtein在计算文本相似度场景中有着各自的特点&#xff0c;为了优化具体的计算时…

windos/ubuntu20.4下UE4.27.2像素流送

windows/ubuntu20.4下UE4.27.2像素流送 像素流送技术可以将服务器端打包的虚幻引擎应用程序在客户端的浏览器上运行&#xff0c;用户可以通过浏览器操作虚幻引擎应用程序&#xff0c;客户端无需下载虚幻引擎&#xff0c;本文实现两台机器通过物理介质网线实现虚幻引擎应用程序…

Jenkins Pipeline脚本优化:为Kubernetes应用部署增加状态检测

引言 在软件部署的世界中&#xff0c;Jenkins已经成为自动化流程的代名词。不断变化的技术环境要求我们持续改进部署流程以满足现代应用部署的需要。在本篇博客中&#xff0c;作为一位资深运维工程师&#xff0c;我将分享如何将Jenkins Pipeline进化至不仅能支持部署应用直至R…

【电源专题】Buck电源上电震荡谁的错?

在文章:【电源专题】案例:Buck芯片上电瞬间波形震荡?从别的人案例中来学习软启参数中我们通过别人的文章了解到了Buck芯片上电瞬间波形震荡有几个方法可以解决,但主要还是围绕着软启动参数去学习。因为文章中无法知道编者所用的电源芯片和电路,所以无法进行分析。 最近我…

Mysql之约束下篇

Mysql之约束下篇 自增列(AUTO_INCREMENT)关键字特点和要求添加自增约束删除自增约束Mysql8.0新特性-自增变量的持久化 FOREIGN KEY 约束关键字主表和从表/父表和子表特点添加外键约束约束等级删除外键约束面试问题 DEFAULT约束作用关键字添加默认值约束删除默认值约束 CHECK约束…

Leetcode—445.两数相加II【中等】

2023每日刷题&#xff08;六十七&#xff09; Leetcode—445.两数相加II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2…

k8s启动docker容器Error: Could not find or load main class ${start-class}报错

前行提要&#xff1a; 今天部署采集点服务&#xff08;docker项目&#xff09;发现报这个错误。 提出假设&#xff1a; 1&#xff0c;配置文件错误&#xff08;工程需要配置的东西比较多&#xff09; 之后开始一一排查&#xff0c;发现配置有问题&#xff0c;但是不是这个错误…

Blazor 混合开发_MAUI+Vue_WPF+Vue

MAUI&#xff0b;Vue 混合开发 背景混合开发的核心为什么必须使用 wwwroot 文件夹放置 Web 项目文件 创建 MAUI 项目创建 wwwroot 文件夹服务注册创建 _import.razor添加 Main.razor 组件修改 MainPage.xaml 文件 创建 WPF 项目创建 wwwroot 文件夹服务注册创建 _import.razor添…

DALL-E:Zero-Shot Text-to-Image Generation

DALL-E 论文是一个文本生成图片模型。 训练分为两个阶段 第一阶段&#xff0c;训练一个dVAE&#xff08;discrete variational autoencoder离散变分自动编码器&#xff09;&#xff0c;其将256 x 256的RGB图片转换为32 x 32的图片token。目的&#xff1a;降低图片的分辨率。图…

12 Vue3中使用v-if指令实现条件渲染

概述 v-if指令主要用来实现条件渲染&#xff0c;在实际项目中使用得也非常多。 v-if通常会配合v-else-if、v-else指令一起使用&#xff0c;可以达到多个条件执行一个&#xff0c;两个条件执行一个&#xff0c;满足一个条件执行等多种场景。 下面&#xff0c;我们分别演示这三…

最新国内AI绘画Midjourney绘画提示词Prompt分享

一、Midjourney绘画工具 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭…

Linux的常用命令及用法案例

概述 Linux 文件与目录结构 Linux 文件 Linux 系统中一切皆文件。 Linux 目录结构 VI/VIM 编辑器 是什么 VI 是 Unix 操作系统和类 Unix 操作系统中最通用的文本编辑器。 VIM 编辑器是从 VI 发展出来的一个性能更强大的文本编辑器。可以主动的以字体颜 色辨别语法的正确性…

GrayLog日志平台的基本使用-docker容器日志接入

1、/etc/docker/daemon.json中加入如下配置并重启服务 [rootlocalhost src]# cat /etc/docker/daemon.json { "registry-mirrors": ["https://dhq9bx4f.mirror.aliyuncs.com"], "log-driver": "gelf", "log-opts":…

Vue2+Vue3组件间通信方式汇总(2)------$emit

组件间通信方式是前端必不可少的知识点&#xff0c;前端开发经常会遇到组件间通信的情况&#xff0c;而且也是前端开发面试常问的知识点之一。接下来开始组件间通信方式第二弹------$emit,并讲讲分别在Vue2、Vue3中的表现。 Vue2Vue3组件间通信方式汇总&#xff08;1&#xff0…