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

参考:

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

2,不记得了

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

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

     下面代码实现:

      1,rsa加密

      2,公钥/私钥导出

#define RsaKeyLen 2048HRESULT 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 进行编码 >
//调用CryptBinaryToStringAHRESULT 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_BLOBPCWSTR 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 keyif (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 textPrintBytes(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 textprintf("cipher text length:%d\n", pbcResult);PrintBytes(buf, pbcResult);printf("begin to decrypt \n");//begin to decryptDecryptAnd(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 providerif (!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;}//finalizeif (!NT_SUCCESS(status = BCryptFinalizeKeyPair(hRsaKey,0))){wprintf(L"BCryptFinalizeKeyPair fail,error:%d\n",GetLastError());goto end;}//encrypt and decryptEncryptAnd(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.mzph.cn/news/240640.shtml

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

相关文章

前端传输formDate格式的数据,后端不能用@RequestBody接收

写了个接口&#xff0c;跟前端对接&#xff0c;前端说怎么一直415的报错 我寻思不对啊&#xff0c;我swagger都请求成功了&#xff0c;后来发现前端一直是以formdata格式提交的数据&#xff0c;这样我其实是可以不加RequestBody的&#xff1b; 知识点&#xff1a; RequestBody…

类和对象

1 类定义&#xff1a; class ChecksumAccumulator {// class definition goes here } 你就能创建 ChecksumAccumulator 对象&#xff1a;new CheckSumAccumulator 注&#xff1a;1scala类中成员默认是public类型&#xff0c;若设为私有属性则必须加private关键字。在scala中是…

基于Springboot的留守儿童爱心网站(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的留守儿童爱心网站(有报告)。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring…

技术交底二维码的应用

二维码技术交底可以逐级落实、责任到人、有据可查、是目前最方便、实用的交底方式&#xff0c;下面我们讲解技术交底二维码的应用。 1、生成对应的技术交底二维码&#xff0c;将施工方案、技术资料、安全教育资料等内容上传到二维码里。打印出来现场粘贴&#xff0c;便于作业班…

java中线程相关的面试题

什么是线程安全&#xff0c;造成线程安全的本质是什么&#xff1f; 什么是线程安全呢&#xff1f; 咱们初步去理解话记住一句话就行&#xff1a;如果一个对象可以安全地被多个线程同时使用&#xff0c;那它就是线程安全的。 为什么并发编程会导致线程不安全&#xff1f; 可见…

用友U8CRM系统help2 任意文件读取漏洞复现

用友U8CRM系统的help2文件中接口存在任意文件读取漏洞&#xff0c;攻击者在未登录情况下即可进行漏洞利用。 1.1 漏洞级别 高危 1.2 快速检索 fofa语法&#xff1a; title"用友U8CRM"1.3 漏洞复现 该漏洞利用非常简单&#xff0c;只需构造get请求 访问该地址即可…

青少年CTF-qsnctf-A1-Misc-签到

题目环境&#xff1a; 题目难度&#xff1a;★题目描述&#xff1a;有没有可能&#xff0c;这个平台就是个题目&#xff1f; 一道杂项题 题目说的是这个平台就是题目 那么也就是说flag就在这个平台里面1.从高层次向低层次逐一排查 2.首先对平台首页进行排查进平台首页 第一种解…

HTML---浮动

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.常见的网页布局 二.标准文档流 标准文档流常见标签 标准文档流的组成 块级元素<div…

二叉搜索树 --- C++实现

目录 1.二叉搜索树的概念 2.二叉搜索树的操作 3. 二叉树的实现 4.二叉搜索树的应用 5. 二叉树的性能分析 6. 二叉树进阶练习题 1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左…

JDBC 知识点总结篇

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

MyBatis笔记

Mybatis Mybatis介绍 什么是Mybatis? mybatis是支持普通SQL查询、存储过程和高级映射的优秀持久层框架。 Mybatis优点 几乎消除了JDBC代码和参数的手动设置消除结果集的检索使用XML或注解用于配置和原始映射&#xff0c;将接口和POJOs(实体类)映射成数据库中的记录。 My…

vue微乾坤子应用开发及ele组件开发时问题记录

一. 微乾坤 1. 新增page页面路由,pmi权限中心配置正常&#xff0c;跳转链接正确&#xff0c;但路由未找到403. 解决&#xff1a; 新增的配置是page类型&#xff0c;transformQianKunRoute方法转换微前端路由数据 时&#xff0c;过滤未兼容page型的路由&#xff0c; 解决 [menu,…

react中使用redux最简单最方便的方式,配合rematch简化操作,5分钟学会

react中使用状态管理的方式也很多&#xff0c;比如redux和mobx等&#xff0c;今天这一片就讲一下redux的入门到熟练使用&#xff0c;主要是要理解它redux的组成有哪些&#xff0c;到怎么创建&#xff0c;和组建中怎么使用三个问题。这里先放上官网文档&#xff0c;不理解的地方…

十一.约束(二)

约束 5.自增列:AUTO_INCREMENT5.1作用5.2关键字5.3特点和要求5.4如何指定自增约束5.5如何删除自增列5.6MySQL8.0新特性——自增变量的持久化 6.FOREIGN KEY 约束6.1作用6.2关键字6.3主表和从表/父表和子表6.4特点6.5添加外键约束6.6演示问题6.7约束等级6.8删除外键约束6.9开发场…

鸿蒙开发者工具安装及入门程序

下载工具DevEco Studio IDE 官网下载&#xff1a;HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 开发工具的安装 解压下载好的压缩包&#xff0c;一路无脑安装即可&#xff0c;安装完的使用方法类似于IDEA、WebStorm的使用&#xff0c;快捷键一致&#xff0c;默认黑…

【笔记】Spring的循环依赖

Spring的循环依赖 ObjectFactory:函数式接口&#xff0c;可以将lambda表达式作为参数放在方法的实参种&#xff0c;在方法执行的时候&#xff0c;并不会实际的调用当前lambda表达式&#xff0c;只有在调用getObject方法的时候才回去调用lambda表达式 为什么spring要用三级缓存…

常用的百兆网络变压器与RJ45网口的参考连接电路有哪些,主要注意事项在哪里呢?

Hqst华轩盛(石门盈盛)电子导读&#xff1a;一起来了解常用的百兆网络变压器与RJ45网口的参考连接电路有哪些&#xff0c;主要注意事项在哪里呢&#xff1f; 第一,常用的百兆网络变压器与RJ45网口的参考连接电路 常用百兆网络变压器与网口连接器分开为独立电子元件的分离式参考电…

TrustZone之与非安全虚拟化交互

到目前为止&#xff0c;我们在示例中忽略了非安全状态中可能存在的虚拟化程序。当存在虚拟化程序时&#xff0c;虚拟机与安全状态之间的许多通信将通过虚拟化程序进行。 例如&#xff0c;在虚拟化环境中&#xff0c;SMC用于访问固件功能和可信服务。固件功能包括诸如电源管理之…

Ubuntu 常用命令之 top 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 top命令是Linux下常用的性能分析工具&#xff0c;可以实时动态地查看系统中各个进程的资源占用状况&#xff0c;类似于Windows的任务管理器。它可以显示系统总的和分区的CPU使用率、内存使用率、交换区使用率、系统负载、进程数、…

MFC静态链接+libtiff静态链接提示LNK2005和LNK4098

编译报错 1>msvcrt.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_infoAAEABV0Z) 已经在 libcmtd.lib(typinfo.obj) 中定义 1>msvcrt.lib(ti_inst.obj) : error LNK2005: "pr…