openssl签名验证、信封加密解密、产生随机数、md5摘要

http://blog.csdn.net/zhouyuqwert/article/details/6603991


  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <openssl/evp.h>  
  4. #include <openssl/rsa.h>  
  5. #include <openssl/x509.h>  
  6. #include <openssl/des.h>  
  7. #include "util/Base.h"  
  8. typedef   unsigned   char   BYTE;  
  9. /* 
  10. * 
  11. *产生随机数 
  12. * 
  13. */  
  14. unsigned char *getRandom(unsigned char *buf, size_t l) {  
  15.   if (!RAND_bytes(buf, l)) {  
  16.     fprintf(stderr, "The PRNG is not seeded!\n");  
  17.     return NULL;  
  18.   }  
  19.   printf((char*)buf);  
  20.   return buf;  
  21. }  
  22. /** 
  23. * 
  24. *信封加密解密 
  25. *参考openssl编程.chm 21.10编程实例4 
  26. * 
  27. */  
  28. int    EVP_enc()  
  29. {  
  30.   
  31.        int                         ret,ekl[2],npubk,inl,outl,total=0,total2=0;  
  32.   
  33.        unsigned long  e=RSA_3;  
  34.   
  35.        char               *ek[2],iv[8],in[100],out[500],de[500];  
  36.   
  37.        EVP_CIPHER_CTX      ctx,ctx2;  
  38.   
  39.        EVP_CIPHER        *type;  
  40.   
  41.        EVP_PKEY            *pubkey[2];  
  42.   
  43.        RSA                      *rkey;  
  44.   
  45.        BIGNUM               *bne;  
  46.   
  47.        int i;  
  48.   
  49.        /* 生成RSA密钥*/  
  50.   
  51.        bne=BN_new();  
  52.   
  53.        ret=BN_set_word(bne,e);  
  54.   
  55.        rkey=RSA_new();  
  56.   
  57.        ret=RSA_generate_key_ex(rkey,1024,bne,NULL);  
  58.   
  59.        pubkey[0]=EVP_PKEY_new();  
  60.   
  61.        EVP_PKEY_assign_RSA(pubkey[0],rkey); //初始化一个公钥为RSA的密钥对公钥  
  62.   
  63.        type=EVP_des_ede3_cbc(); //对称密钥的算法  
  64.   
  65.        npubk=1; //设置一个公钥加密  
  66.   
  67.        EVP_CIPHER_CTX_init(&ctx);   //初始化信封加密上下文  
  68.   
  69.        ek[0]=malloc(500);  
  70.   
  71.        ek[1]=malloc(500);  
  72.   
  73.        ret=EVP_SealInit(&ctx,type,(BYTE**)ek,ekl,iv,pubkey,1);  /* 只有一个公钥,如果为CBC算法IV会被产生*/  
  74.   
  75.        if(ret!=1) goto err;  
  76.   
  77.        strcpy(in,"openssl 编程"); //对称密钥(即将被加密为信封的数据)  
  78.   
  79.        inl=strlen(in);  
  80.   
  81.        ret=EVP_SealUpdate(&ctx,out,&outl,in,inl);   //加密操作  
  82.       
  83.   
  84.   
  85.        if(ret!=1)goto err;  
  86.   
  87.        total+=outl;  
  88.   
  89.        ret=EVP_SealFinal(&ctx,out+outl,&outl);  //加密剩下的部分  
  90.       
  91.   
  92.        if(ret!=1) goto err;  
  93.   
  94.        total+=outl;  
  95.       
  96.       
  97.     /** 
  98.     * 解密信封 
  99.     */  
  100.        memset(de,0,500);  
  101.   
  102.        EVP_CIPHER_CTX_init(&ctx2);  //初始化解密信封的上下文  
  103.   
  104.        ret=EVP_OpenInit(&ctx2,EVP_des_ede3_cbc(),ek[0],ekl[0],iv,pubkey[0]);    //设置公钥  
  105.       
  106.   
  107.        if(ret!=1) goto err;  
  108.   
  109.        ret=EVP_OpenUpdate(&ctx2,de,&outl,out,total);  
  110.       
  111.   
  112.        total2+=outl;  
  113.   
  114.        ret=EVP_OpenFinal(&ctx2,de+outl,&outl);  
  115.       
  116.   
  117.        total2+=outl;  
  118.   
  119.        de[total2]=0;  
  120.   
  121.        printf("%s\n",de);  
  122.   
  123. err:  
  124.   
  125.        free(ek[0]);  
  126.   
  127.        free(ek[1]);  
  128.   
  129.        EVP_PKEY_free(pubkey[0]);  
  130.   
  131.        BN_free(bne);  
  132.   
  133.        getchar();  
  134.   
  135.        return 0;  
  136.   
  137. }  
  138.   
  139.   
  140.   
  141. /** 
  142. * 
  143. *数字签名与验证 
  144. *参考《精通PKI安全认证技术与编程实现》 
  145. * 
  146. **/  
  147. void tSign()  
  148. {  
  149.     BYTE sign_value[1024]; //保存签名值的数组  
  150.     int sign_len;   //签名值长度  
  151.     EVP_MD_CTX mdctx;   //摘要算法上下文变量  
  152.     char messl[] = "Test Message";  //签名的消息  
  153.     RSA* rsa = NULL;    //RSA结构体变量  
  154.     EVP_PKEY* evpKey = NULL;    //EVP KEY结构体变量  
  155.     int i;  
  156.   
  157.     printf("正在产生RSA密钥...");  
  158.     rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);  //产生一个1024位的RSA密钥  
  159.     if(rsa == NULL)  
  160.     {  
  161.         printf("gen rsa err\n");  
  162.         return;  
  163.     }  
  164.     printf("成功.\n");  
  165.     evpKey = EVP_PKEY_new();    //新建一个EVP_PKEY变量  
  166.     if(evpKey == NULL)  
  167.     {  
  168.         printf("EVP_PKEY_new err\n");  
  169.         RSA_free(rsa);  
  170.         return;  
  171.     }  
  172.     if(EVP_PKEY_set1_RSA(evpKey,rsa) != 1)  //保存RSA结构体到EVP_PKEY结构体  
  173.     {  
  174.         printf("EVP_PKEY_set1_RSA err\n");  
  175.         RSA_free(rsa);  
  176.         EVP_PKEY_free(evpKey);  
  177.         return;  
  178.     }  
  179.     //以下是计算签名的代码  
  180.     EVP_MD_CTX_init(&mdctx);        //初始化摘要上下文  
  181.     if(!EVP_SignInit_ex(&mdctx,EVP_md5(),NULL)) //签名初始化,设置摘要算法  
  182.     {  
  183.         printf("err\n");  
  184.         EVP_PKEY_free(evpKey);  
  185.         RSA_free(rsa);  
  186.         return;  
  187.     }  
  188.     if(!EVP_SignUpdate(&mdctx,messl,strlen(messl))) //计算签名(摘要)Update  
  189.     {  
  190.         printf("err\n");  
  191.         EVP_PKEY_free(evpKey);  
  192.         RSA_free(rsa);  
  193.         return;  
  194.     }  
  195.     if(!EVP_SignFinal(&mdctx,sign_value,&sign_len,evpKey))  //签名输出  
  196.     {  
  197.         printf("err\n");  
  198.         EVP_PKEY_free(evpKey);  
  199.         RSA_free(rsa);  
  200.         return;  
  201.     }  
  202.     printf("消息\"%s\"的签名值是:\n",messl);  
  203.     for(i = 0; i < sign_len; i++)  
  204.     {  
  205.         if(i%16==0)  
  206.             printf("\n%08xH: ",i);  
  207.         printf("&%2x ",sign_value[i]);  
  208.     }  
  209.     printf("\n");  
  210.     EVP_MD_CTX_cleanup(&mdctx);  
  211.       
  212.     printf("\n 正在验证签名...\n");  
  213.     //以下是验证签名的代码  
  214.     EVP_MD_CTX_init(&mdctx);    //初始化摘要上下文  
  215.     if(!EVP_VerifyInit_ex(&mdctx, EVP_md5(), NULL)) //验证初始化,设置摘要算法,一定要和签名一致  
  216.     {  
  217.         printf("EVP_VerifyInit_ex err\n");  
  218.         EVP_PKEY_free(evpKey);  
  219.         RSA_free(rsa);  
  220.         return;  
  221.     }  
  222.     if(!EVP_VerifyUpdate(&mdctx, messl, strlen(messl))) //验证签名(摘要)Update  
  223.     {  
  224.         printf("err\n");  
  225.         EVP_PKEY_free(evpKey);  
  226.         RSA_free(rsa);  
  227.         return;  
  228.     }  
  229.     if(!EVP_VerifyFinal(&mdctx,sign_value,sign_len,evpKey))  
  230.     {  
  231.         printf("verify err\n");  
  232.         EVP_PKEY_free(evpKey);  
  233.         RSA_free(rsa);  
  234.         return;  
  235.     }  
  236.     else  
  237.     {  
  238.         printf("验证签名正确.\n");  
  239.     }  
  240.     //释放内存  
  241.     EVP_PKEY_free(evpKey);  
  242.     RSA_free(rsa);  
  243.     EVP_MD_CTX_cleanup(&mdctx);  
  244.     return;  
  245. }  
  246.   
  247.   
  248. /** 
  249. * 
  250. *in为输入的字节数组,len为输入长度,out为输出hash值,outl为输出长度 
  251. *MD5摘要算法得到16字节结果 
  252. * 
  253. */  
  254. void hash_md5(BYTE *in,int len,BYTE* out,int *outl)  
  255. {  
  256.   
  257.     /************* 
  258.     * 
  259.     *将输入初始化到临时BYTE数组 
  260.     * 
  261.     **************/  
  262.     BYTE intemp[len];  
  263.     int j;int          i;  
  264.     for(j = 0; j<len;j++)  
  265.     {  
  266.         intemp[j] = in[j];  
  267.     }  
  268.        for(i=0;i<16;i++)  
  269.                  printf("%x ",out[i]);    
  270.     printf("\n");  
  271.     memset(out,0,16);  
  272.        
  273.         intemp[len] = 0;  
  274.     size_t       n;  
  275.     unsigned long err;  
  276.           
  277.     printf("\nMD5 digesting:\n");  
  278.     printf("\n%s\n",intemp);  
  279.       
  280.     MD5(intemp,n,out);  
  281.       
  282.   
  283.   
  284.   
  285.     printf("\n%d\n",n);  
  286.         printf("\n\nMD5 digest result :\n");  
  287.           
  288.      printf("\n%s\n",out);   
  289.     /***** 
  290.     * 
  291.     *MD5输出为16字节 
  292.     * 
  293.     ******/  
  294.     //*outl = 16;  
  295.         for(i=0;i<16;i++)  
  296.                  printf("%x ",out[i]);    
  297. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值