当前位置:编程学习 > VC++ >>

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

数字证书采用公钥体制,即利用一对互相匹配的密钥进行加密、解密。每个用户自己设定一把特定的仅为本人所知的私有密钥(私钥),用它进行解密和签名;同时设定一把公共密钥(公钥)并由本人公开,为一组用户所共享,用于加密和验证签名。当发送一份保密文件时,发送方使用接收方的公钥对数据加密,而接收方则使用 自己的私钥解密,这样信息就可以安全无误地到达目的地了。通过数字的手段保证加 密过程是一个不可逆过程,即只有用私有密钥才能解密。在公开密钥密码体制中,常用的一种是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,  &n

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,