数字证书采用公钥体制,即利用一对互相匹配的密钥进行加密、解密。每个用户自己设定一把特定的仅为本人所知的私有密钥(私钥),用它进行解密和签名;同时设定一把公共密钥(公钥)并由本人公开,为一组用户所共享,用于加密和验证签名。当发送一份保密文件时,发送方使用接收方的公钥对数据加密,而接收方则使用 自己的私钥解密,这样信息就可以安全无误地到达目的地了。通过数字的手段保证加 密过程是一个不可逆过程,即只有用私有密钥才能解密。在公开密钥密码体制中,常用的一种是RSA体制。其数学原理是将一个大数分解成两个质数的乘积,加密和解密用的是两个不同的密钥。即使已知明文、密文和加密密钥(公开密钥),想要推导出解密密钥(私密密钥),在计算上是不可能的。按现在的计算机技术水平,要破解目前采用的1024位RSA密钥,需要上千年的计算时间。公开密钥技术解决了密钥发布的管理问题,商户可以公开其公开密钥,而保留其私有密钥。购物者可以用人人皆知的公开密钥对发送的信息进行加密,安全地传送给商户,然后由商户用自己的私有密钥 进行解密
  用户也可以采用自己的私钥对信息加以处理,由于密钥仅为本人所有,这样就产生了别人无法生成的文件,也就形成了数字签名。采用数字签名,能够确认以下两点:
  (1)保证信息是由签名者自己签名发送的,签名者不能否认或难以否认;
  (2)保证信息自签发后到收到为止未曾作过任何修改,签发的文件是真实文件
  数字签名具体做法是:
  (1)将报文按双方约定的HASH算法计算得到一个固定位数的报文摘要。在数学上保证:只要改动报文中任何一位,重新计算出的报文摘要值就会与原先的值不相符。这样就保证了报文的不可更改性
  (2)将该报文摘要值用发送者的私人密钥加密,然后连同原报文一起发送给接收者,而产生的报文即称数字签名
  (3)接收方收到数字签名后,用同样的HASH算法对报文计算摘要值,然后与用发送者的公开密钥进行解密解开的报文摘要值相比较。如相等则说明报文确实来自所称的发送者。

代码如下,分析见注释

#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif #include <stdio.h> #include <windows.h> #include <wincrypt.h> #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) #define CERT_SUBJECT_NAME "TEST_SIGNER_NAME" //函数申明 void HandleError(char *s); HCRYPTPROV GetCryptProv(); void ByteToStr( DWORD cb, void* pv, LPSTR sz); void main(void) { //------------------------------------------------------------------- // 变量申明与初始化 HCERTSTORE hCertStore = NULL; HCRYPTPROV hCertProv = NULL; HCRYPTKEY hKeySign = NULL; PCCERT_CONTEXT pCertCtxSign = NULL; BYTE *Encrypted = NULL; DWORD EncryptedLen = 0; BYTE *Decrypted= NULL; DWORD DecryptedLen = 0; CERT_NAME_BLOB certName = {0}; certName.cbData = 0; certName.pbData = NULL; DWORD cbNameEncoded; BYTE* pbNameEncoded; //给CERT_NAME_BLOB结构certName赋值 CERT_RDN_ATTR rgNameAttr[] = { "2.5.4.3", CERT_RDN_PRINTABLE_STRING, strlen(CERT_SUBJECT_NAME), (BYTE*)CERT_SUBJECT_NAME}; CERT_RDN rgRDN[] = { 1, &rgNameAttr[0]}; CERT_NAME_INFO Name = { 1, rgRDN}; //------------------------------------------------------------------- // 编码CERT_NAME_INFO结构,确定编码后的数据长度 if(CryptEncodeObject( MY_ENCODING_TYPE, // Encoding type X509_NAME, // Structure type &Name, // Address of CERT_NAME_INFO structure NULL, // pbEncoded &cbNameEncoded)) // pbEncoded size { printf("首次调用函数CryptEncodeObject成功. \n"); } else { HandleError("首次调用函数CryptEncodeObject失败.\ \n公私密钥对不能从密钥容器中导出. \n"); } //------------------------------------------------------------------- // 分配内存 if(!(pbNameEncoded = (BYTE*)malloc(cbNameEncoded))) HandleError("pbNamencoded malloc operation failed.\n"); //------------------------------------------------------------------- // 编码结构体 if(CryptEncodeObject( MY_ENCODING_TYPE, // Encoding type X509_NAME, // Structure type &Name, // Address of CERT_NAME_INFO structure pbNameEncoded, // pbEncoded &cbNameEncoded)) // pbEncoded size { printf("此结构体已被编码. \n"); } else { free(pbNameEncoded); HandleError("第二次调用函数CryptEncodeObject 失败.\n"); } //给certName赋值 certName.cbData = cbNameEncoded; certName.pbData = pbNameEncoded; //获取CSP句柄 hCertProv = GetCryptProv() ; //产生签名密钥对 if (CryptGenKey(hCertProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKeySign)) { printf("在服务证书容器中创建签名密钥成功!\n"); } else { HandleError("Protection::Initialise -不能在服务证书容器中创建签名密钥- \n"); } SYSTEMTIME cs; GetSystemTime(&cs); cs.wYear += 1; //创建自签名证书 if(pCertCtxSign = CertCreateSelfSignCertificate( hCertProv, //CSP句柄 &certName, //证书客体名称数据结构指针 0, //标志位。默认行为,创建私钥信息,创建签名 NULL, //密钥信息结构 NULL, //签名算法,null表示默认算法SHA1RSA NULL, //有效期起始时间 ,null表示取当前系统时间 &cs, //有效期终止时间,null表示起始时间加1年 NULL)) //未设置扩展属性 { printf("一个自签名证书已经被创建.\n"); } else { HandleError("CertCreateSelfSignCertificate Error!"); } free(certName.pbData); //打开证书库 if ((hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL , CERT_SYSTEM_STORE_CURRENT_USER , L"My"))) { printf("打开证书库成功.\n"); } else { HandleError("调用函数CertOpenStore 失败.\n"); } //把证书加入证书库 if(CertAddCertificateContextToStore(hCertStore, pCertCtxSign,CERT_STORE_ADD_NEW,NULL)) { printf("将自签名证书加入到系统证书库成功.\n"); } else { printf("将自签名证书添加到系统证书库中失败.\n"); } //释放空间 if (Encrypted) free(Encrypted); if (Decrypted) free(Decrypted); if (pCertCtxSign) CertFreeCertificateContext(pCertCtxSign); if (hKeySign) CryptDestroyKey(hKeySign); if (hCertStore) CertCloseStore(hCertStore, 0); if (hCertProv) CryptReleaseContext(hCertProv, 0); } // End of main //获取加密提供者句柄 HCRYPTPROV GetCryptProv() { HCRYPTPROV hCryptProv; // 加密服务提供者句柄 //获取加密提供者句柄 if(CryptAcquireContext( &hCryptProv, // 加密服务提供者句柄 "ruanou", // 密钥容器名 MS_ENHANCED_PROV, // 加密服务提供者 PROV_RSA_FULL, // 加密服务提供者类型,可以提供加密和签名等功能 0)) // 标志 { printf("加密服务提供者句柄获取成功!\n"); } else { //重新建立一个新的密钥集 if(!CryptAcquireContext(&hCryptProv, "ruanou", MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { HandleError("重新建立一个新的密钥集出错!"); } } return hCryptProv; } //-------------------------------------------------------------------- // ByteToStr: 转换BYTE类型数组为字符串 //参数:cb[in] 需要转换的BYTE数组的长度 // pv[in] 需要转换的BYTE数组指针 // sz[out] 字符串指针 void ByteToStr( DWORD cb, void* pv, LPSTR sz) { BYTE* pb = (BYTE*) pv; DWORD i; int b; for (i = 0; i<cb; i++) { //pb的前4位转换为字符 b = (*pb & 0xF0) >> 4; *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A'; //pb的后4位转换为字符 b = *pb & 0x0F; *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A'; pb++; } *sz++ = 0; } // HandleError:错误处理函数,打印错误信息,并退出程序 void HandleError(char *s) { printf("程序执行发生错误!\n"); printf("%s\n",s); printf("错误代码为: %x.\n",GetLastError()); printf("程序终止执行!\n"); exit(1); }

转载于:https://www.cnblogs.com/yincheng01/archive/2011/10/05/2213150.html

VC++网络安全编程范例(2)-创建自签名证书相关推荐

  1. VC++网络安全编程范例(1)--数字证书有效期验证

    数字证书就是互联网通讯中标志通讯各方身份信息的一系列数据,提供了一种在Internet上验证您身份的方式,其作用类似于司机的驾驶执照或日常生活中的身份证.它是由一个由权威机构-----CA机构,又称为 ...

  2. vc++网络安全编程范例(19)实现数字信封打包与拆解

    数字信封是将对称密钥通过非对称加密(即:有公钥和私钥两个)的结果分发对称密钥的方法. PKCS#7中将数字信封作为术语进行定义,而在正文中对进行了如下解释:数字信封包含被加密的内容和被加密的用于加密该 ...

  3. vc++网络安全编程范例(14)-openssl bio编程

    OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库.SSL协议库以及应用程序.OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的. 作为一个基于密码学的安全开发包,OpenS ...

  4. Mac如何创建自签名证书?Mac创建自签名证书图文教程

    Mac上怎么创建自签名证书?您可以使用"钥匙串访问"中的"证书助理"创建自签名证书.自签名证书不提供由证书颁发机构所签名的证书中的各种保证,但如果证书的签名人可 ...

  5. 如何在Windows上为代码签名创建自签名证书

    出自http://www.imooc.com/wenda/detail/577483 由于这篇文章搜索实在费劲,机缘巧合中才找到,为了后面课程学习方便查找,斗胆转载,侵删 慕森王 更新的答案 如果您使 ...

  6. 简便方法创建自签名证书

    前面我们详细介绍了证书的创建和颁发,这里给大家介绍一个新的方法创建自签名的私钥 1.私钥和证书放在同一个文件里 ]#cd /etc/pki/tls/certs/ ]#make httpd.pem 2. ...

  7. 自签名证书和私有CA签名的证书的区别 创建自签名证书 创建私有CA 证书类型 证书扩展名

    自签名的证书无法被吊销,CA签名的证书可以被吊销 能不能吊销证书的区别在于,如果你的私钥被黑客获取,如果证书不能被吊销,则黑客可以伪装成你与用户进行通信 如果你的规划需要创建多个证书,那么使用私有CA ...

  8. 私钥创建,申请证书,吊销证书,创建自签名证书

    CentOS7 中使用 gpg 创建 RSA 非对称密钥对 gpg --gen-key #在最后需要对设备进行操作的时候,可以在打开一个终端,然后 dd if=/dev/sda of=/dev/nul ...

  9. VC多线程编程之线程创建与示例

    一.问题的提出 编写一个耗时的单线程程序: 新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX ...

最新文章

  1. 为什么LED内部不集成限流电阻呢?
  2. java drawimage 参数_小程序中canvas的drawImage方法参数使用详解
  3. (87)FPGA面试题-同步FIFO与异步FIFO区别?异步FIFO代码设计
  4. Delphi 集合和字符串互转
  5. JS向NPAPI传递参数,并返回结果
  6. 西门子plc烧录单片机_用51单片机做简易PLC
  7. 【工具使用】apizza和postman中post请求下form-data、x-www-form-urlencoded、raw、binary的区别
  8. 神州数码交换机配置基本命令
  9. 心知天气html,esp8266初级入门实用教程一之访问心知天气读取实时天气数据
  10. Golang GC算法解读
  11. Could not initialize class com.android.build.gradle.internal.VariantManager解决方案
  12. 如何计算机画函数图形,Excel中怎么绘制出好看的函数图像
  13. vs中资源文件和外部依赖项是什么意思?
  14. [Linux] Linux中/tmp目录下文件莫名丢失
  15. 带有源代码的2020年20种最佳HTML5游戏模板
  16. idea热部署插件JRebel激活(强烈推荐,试试就离不开了)
  17. kendoUI系列教程之DropDownList下拉菜单
  18. iOS 多线程使用示例
  19. 字典生成----在线密码破解工具hydra和medusa的使用
  20. 如何将nii图像文件转换为png图像,亲测有效!!!

热门文章

  1. Vue打包并发布项目
  2. 报错xmlbase 不兼容 expecting up to 23, got 24
  3. android edittext不可复制_Android 禁止输入框 EditText 复制粘贴
  4. java post加密_使用Java和PHP的BCrypt,发送加密的密码并对其进行解码 - java
  5. Flex布局实现筛子3
  6. bzoj 2464: 中山市选[2009]小明的游戏(BFS)
  7. bzoj 1066: [SCOI2007]蜥蜴(最大流)
  8. 吴恩达神经网络和深度学习-学习笔记-27-多任务学习
  9. python机器学习案例系列教程——LightGBM算法
  10. C#解析xml文件获取中国的省市县地区名称和zipcode编号