Chinaunix首页 | 论坛 | 博客
  • 博客访问: 681924
  • 博文数量: 85
  • 博客积分: 1797
  • 博客等级: 上尉
  • 技术积分: 1238
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-02 08:53
个人简介

职位:技术总监 1、精通c++(linux平台、vc++Mfc、qt)、java、php、unity3d,略懂python 2、用c++开发过嵌入式产品,用c++开发过大型银行运维产品 3、用java开发大型银行运维产品,学校教务系统 4、用php开发进销存系统(在销售中),用php开发淘宝小程序 5、用unity3d开发衣柜设计软件,在运营中

文章分类

全部博文(85)

分类: 网络与安全

2011-08-27 00:23:17

 
 

#include<stdio.h>
#include<openssl/evp.h>
#include<string.h>
#include<windows.h>
#include<openssl/x509.h>
  
void sign_test()
{
    unsigned char sign_value[1024]; //保存签名值的数组

    int sign_len; //签名的长度

    EVP_MD_CTX mdctx; //摘要算法上下文变量

    char mess1[]="Text Message"; //签名的信息

    RSA *rsa=NULL; //RSA结构体变量

    EVP_PKEY *evpKey=NULL; //EVPKEY 结构体变量

    int i;
  
    printf("正在产生RSA密钥....");
    rsa=RSA_generate_key(1024,RSA_F4,NULL,NULL); //产生一个1024 位的RSA密钥

    if (rsa==NULL)
    {
        printf("gen rsa err\n");
        return;
    }
    printf("成功。\n");
    
    //The EVP_PKEY_new() function allocates an empty EVP_PKEY structure which is used by OpenSSL to store private keys.

    evpKey=EVP_PKEY_new();//新建一个EVP_PKEY 变量


    if (evpKey==NULL)
    {
        printf("EVP_PKEY_new err\n");
        RSA_free(rsa);
        return;
    }


    if (EVP_PKEY_set1_RSA(evpKey,rsa) !=1) //保存RSA结构体到EVP_PKEY 结构体

    {
        printf("EVP_PKEY_set1_RSA err\n");
        RSA_free(rsa);
        EVP_PKEY_free(evpKey);
        return;
    }
    EVP_MD_CTX_init(&mdctx); //初始化摘要上下文

    
    //该函数是一个宏定义函数#define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c)

    // int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);

    //EVP_DigestInit_ex() sets up digest context ctx to use a digest type from ENGINE impl.

    //ctx must be initialized before calling this function. type will typically be supplied by a functionsuch as EVP_sha1().

    //If impl is NULL then the default implementation of digest type is used.

    if (!EVP_SignInit_ex(&mdctx,EVP_md5(),NULL))
    {
        printf("Init err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }

    //int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);

    //EVP_DigestUpdate() hashes cnt bytes of data at d into the digest context ctx.

    //This function can be called several times on the same ctx to hash additional data.

    if (!EVP_SignUpdate(&mdctx,mess1,strlen(mess1))) //计算签名(摘要)Update

    {
        printf("EVP_SignUpdate err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }

    //int EVP_SignFinal(EVP_MD_CTX *ctx,unsigned char *sig,unsigned int *s, EVP_PKEY *pkey);

    //这是签名系列函数跟信息摘要函数开始不同的地方,其实,该函数是将签名操作的信息摘要结构ctx拷贝一份,

    //然后调用EVP_DigestFinal_ex完成信息摘要工作,然后开始对摘要信息用私钥pkey进行签名,并将签名信息保存在参数sig里面。

    //如果参数s不为NULL,那么就会将签名信息数据的长度(单位字节)保存在该参数中,通常写入的数据是EVP_PKEY_size(key)。

    //因为操作的时候是拷贝了一份ctx,所以,原来的ctx结构还可以继续使用EVP_SignUpdate和EVP_SignFinal函数来完成更多信息的签名工作。

    //不过,最后一定要使用EVP_MD_CTX_cleanup函数清除和释放ctx结构,否则就会造成内存泄漏。


    if(!EVP_SignFinal(&mdctx,sign_value,(unsigned int *)(&sign_len),evpKey))//签名输出

    {
        printf("EVP_SignFinal err \n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    printf("消息\"%s\"的签名值是:\n",mess1);
    for(i=0;i<sign_len;i++)
    {
        if (i%6==0)
            printf("\n%08xH:",i);
            printf("%02x ",sign_value[i]);
    }
    printf("\n");
    EVP_MD_CTX_cleanup(&mdctx);
    printf("\n 正在验证签名......\n");
    //以下为验证代码

    if (!EVP_VerifyInit_ex(&mdctx,EVP_md5(),NULL))
    {
        printf("EVP_VerifyInit_ex err\n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    if (!EVP_VerifyUpdate(&mdctx,mess1,strlen(mess1)))
    {
        printf ("EVP_VerifyUpdate err \n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    if (!EVP_VerifyFinal(&mdctx,sign_value,sign_len,evpKey))
    {
        printf("EVP_VerifyFinal err \n");
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        return;
    }
    else
    {
        printf ("验证签名正确..\n");
    }
        EVP_PKEY_free(evpKey);
        RSA_free(rsa);
        EVP_MD_CTX_cleanup(&mdctx);
        printf ("--------------------------------------\n");
        return;
}


阅读(7049) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~