数字证书采用公钥体制,即利用一对互相匹配的密钥进行加密、解密。每个用户自己设定一把特定的仅为本人所知的私有密钥(私钥),用它进行解密和签名;同时设定一把公共密钥(公钥)并由本人公开,为一组用户所共享,用于加密和验证签名。当发送一份保密文件时,发送方使用接收方的公钥对数据加密,而接收方则使用 自己的私钥解密,这样信息就可以安全无误地到达目的地了。通过数字的手段保证加 密过程是一个不可逆过程,即只有用私有密钥才能解密。在公开密钥密码体制中,常用的一种是RSA体制。其数学原理是将一个大数分解成两个质数的乘积,加密和解密用的是两个不同的密钥。即使已知明文、密文和加密密钥(公开密钥),想要推导出解密密钥(私密密钥),在计算上是不可能的。按现在的计算机技术水平,要破解目前采用的1024位RSA密钥,需要上千年的计算时间。公开密钥技术解决了密钥发布的管理问题,商户可以公开其公开密钥,而保留其私有密钥。购物者可以用人人皆知的公开密钥对发送的信息进行加密,安全地传送给商户,然后由商户用自己的私有密钥 进行解密
用户也可以采用自己的私钥对信息加以处理,由于密钥仅为本人所有,这样就产生了别人无法生成的文件,也就形成了数字签名。采用数字签名,能够确认以下两点:
(1)保证信息是由签名者自己签名发送的,签名者不能否认或难以否认;
(2)保证信息自签发后到收到为止未曾作过任何修改,签发的文件是真实文件
数字签名具体做法是:
(1)将报文按双方约定的HASH算法计算得到一个固定位数的报文摘要。在数学上保证:只要改动报文中任何一位,重新计算出的报文摘要值就会与原先的值不相符。这样就保证了报文的不可更改性
(2)将该报文摘要值用发送者的私人密钥加密,然后连同原报文一起发送给接收者,而产生的报文即称数字签名
(3)接收方收到数字签名后,用同样的HASH算法对报文计算摘要值,然后与用发送者的公开密钥进行解密解开的报文摘要值相比较。如相等则说明报文确实来自所称的发送者。
代码如下,分析见注释
1#ifndef _WIN32_WINNT 2#define _WIN32_WINNT 0x0400 3#endif 4 5#include <stdio.h> 6#include <windows.h> 7#include <wincrypt.h> 8 9#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) 10#define CERT_SUBJECT_NAME "TEST_SIGNER_NAME" 11//函数申明 12void HandleError(char *s); 13HCRYPTPROV GetCryptProv(); 14void ByteToStr( 15 DWORD cb, 16 void* pv, 17 LPSTR sz); 18 19void main(void) 20{ 21 //------------------------------------------------------------------- 22 // 变量申明与初始化 23 24 HCERTSTORE hCertStore = NULL; 25 HCRYPTPROV hCertProv = NULL; 26 HCRYPTKEY hKeySign = NULL; 27 PCCERT_CONTEXT pCertCtxSign = NULL; 28 29 BYTE *Encrypted = NULL; 30 DWORD EncryptedLen = 0; 31 BYTE *Decrypted= NULL; 32 DWORD DecryptedLen = 0; 33 CERT_NAME_BLOB certName = {0}; 34 certName.cbData = 0; 35 certName.pbData = NULL; 36 DWORD cbNameEncoded; 37 BYTE* pbNameEncoded; 38 39 //给CERT_NAME_BLOB结构certName赋值 40 41 CERT_RDN_ATTR rgNameAttr[] = { 42 "2.5.4.3", 43 CERT_RDN_PRINTABLE_STRING, 44 strlen(CERT_SUBJECT_NAME), 45 (BYTE*)CERT_SUBJECT_NAME}; 46 47 CERT_RDN rgRDN[] = { 48 1, 49 &rgNameAttr[0]}; 50 51 52 CERT_NAME_INFO Name = { 53 1, 54 rgRDN}; 55 56 //------------------------------------------------------------------- 57 // 编码CERT_NAME_INFO结构,确定编码后的数据长度 58 59 if(CryptEncodeObject( 60 MY_ENCODING_TYPE, // Encoding type 61 X509_NAME, // Structure type 62 &Name, // Address of CERT_NAME_INFO structure 63 NULL, // pbEncoded 64 &cbNameEncoded)) // pbEncoded size 65 { 66 printf("首次调用函数CryptEncodeObject成功. \n"); 67 } 68 else 69 { 70 HandleError("首次调用函数CryptEncodeObject失败.\ 71 \n公私密钥对不能从密钥容器中导出. \n"); 72 } 73 //------------------------------------------------------------------- 74 // 分配内存 75 76 if(!(pbNameEncoded = (BYTE*)malloc(cbNameEncoded))) 77 HandleError("pbNamencoded malloc operation failed.\n"); 78 79 //------------------------------------------------------------------- 80 // 编码结构体 81 82 if(CryptEncodeObject( 83 MY_ENCODING_TYPE, // Encoding type 84 X509_NAME, // Structure type 85 &Name, // Address of CERT_NAME_INFO structure 86 pbNameEncoded, // pbEncoded 87 &cbNameEncoded)) // pbEncoded size 88 { 89 printf("此结构体已被编码. \n"); 90 } 91 else 92 { 93 free(pbNameEncoded); 94 HandleError("第二次调用函数CryptEncodeObject 失败.\n"); 95 } 96 97 //给certName赋值 98 certName.cbData = cbNameEncoded; 99 certName.pbData = pbNameEncoded; 100 101 102 //获取CSP句柄 103 hCertProv = GetCryptProv() ; 104 105 //产生签名密钥对 106 if (CryptGenKey(hCertProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKeySign)) 107 { 108 printf("在服务证书容器中创建签名密钥成功!\n"); 109 110 } 111 else 112 { 113 HandleError("Protection::Initialise -不能在服务证书容器中创建签名密钥- \n"); 114 115 } 116 117 SYSTEMTIME cs; 118 GetSystemTime(&cs); 119 cs.wYear += 1; 120 121 122 //创建自签名证书 123 if(pCertCtxSign = CertCreateSelfSignCertificate( 124 hCertProv, //CSP句柄 125 &certName, //证书客体名称数据结构指针 126 0, //标志位。默认行为,创建私钥信息,创建签名 127 NULL, //密钥信息结构 128 NULL, //签名算法,null表示默认算法SHA1RSA 129 NULL, //有效期起始时间 ,null表示取当前系统时间 130 &cs, //有效期终止时间,null表示起始时间加1年 131 NULL)) //未设置扩展属性 132 { 133 printf("一个自签名证书已经被创建.\n"); 134 } 135 else 136 { 137 HandleError("CertCreateSelfSignCertificate Error!"); 138 } 139 free(certName.pbData); 140 141 142 //打开证书库 143 if ((hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL , CERT_SYSTEM_STORE_CURRENT_USER , L"My"))) 144 { 145 printf("打开证书库成功.\n"); 146 } 147 else 148 { 149 HandleError("调用函数CertOpenStore 失败.\n"); 150 } 151 152 //把证书加入证书库 153 if(CertAddCertificateContextToStore(hCertStore, 154 pCertCtxSign,CERT_STORE_ADD_NEW,NULL)) 155 { 156 printf("将自签名证书加入到系统证书库成功.\n"); 157 } 158 else 159 { 160 printf("将自签名证书添加到系统证书库中失败.\n"); 161 } 162 163 //释放空间 164 if (Encrypted) 165 free(Encrypted); 166 if (Decrypted) 167 free(Decrypted); 168 if (pCertCtxSign) 169 CertFreeCertificateContext(pCertCtxSign); 170 if (hKeySign) 171 CryptDestroyKey(hKeySign); 172 if (hCertStore) 173 CertCloseStore(hCertStore, 0); 174 if (hCertProv) 175 CryptReleaseContext(hCertProv, 0); 176 177} // End of main 178 179//获取加密提供者句柄 180HCRYPTPROV GetCryptProv() 181{ 182 HCRYPTPROV hCryptProv; // 加密服务提供者句柄 183 184 //获取加密提供者句柄 185 if(CryptAcquireContext( 186 &hCryptProv, // 加密服务提供者句柄 187 "ruanou", // 密钥容器名 188 MS_ENHANCED_PROV, // 加密服务提供者 189 PROV_RSA_FULL, // 加密服务提供者类型,可以提供加密和签名等功能 190 0)) // 标志 191 { 192 printf("加密服务提供者句柄获取成功!\n"); 193 } 194 else 195 { 196 197 //重新建立一个新的密钥集 198 if(!CryptAcquireContext(&hCryptProv, "ruanou", MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET)) 199 { 200 HandleError("重新建立一个新的密钥集出错!"); 201 } 202 203 } 204 return hCryptProv; 205} 206 207//-------------------------------------------------------------------- 208// ByteToStr: 转换BYTE类型数组为字符串 209//参数:cb[in] 需要转换的BYTE数组的长度 210// pv[in] 需要转换的BYTE数组指针 211// sz[out] 字符串指针 212void ByteToStr( 213 DWORD cb, 214 void* pv, 215 LPSTR sz) 216{ 217 BYTE* pb = (BYTE*) pv; 218 DWORD i; 219 int b; 220 221 for (i = 0; i<cb; i++) 222 { 223 //pb的前4位转换为字符 224 b = (*pb & 0xF0) >> 4; 225 *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A'; 226 //pb的后4位转换为字符 227 b = *pb & 0x0F; 228 *sz++ = (b <= 9) ? b + '0' : (b - 10) + 'A'; 229 pb++; 230 } 231 *sz++ = 0; 232} 233 234// HandleError:错误处理函数,打印错误信息,并退出程序 235void HandleError(char *s) 236{ 237 printf("程序执行发生错误!\n"); 238 printf("%s\n",s); 239 printf("错误代码为: %x.\n",GetLastError()); 240 printf("程序终止执行!\n"); 241 exit(1); 242}
$(document).ready(function(){dp.SyntaxHighlighter.HighlightAll('code');});
原文链接: http://blog.csdn.net/yincheng01/article/details/6845806