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

#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/des.h>
#include "util/Base.h"
typedef   unsigned   char   BYTE;
/*
*
*产生随机数
*
*/
unsigned char *getRandom(unsigned char *buf, size_t l) {
  if (!RAND_bytes(buf, l)) {
    fprintf(stderr, "The PRNG is not seeded!\n");
    return NULL;
  }
  printf((char*)buf);
  return buf;
}
/**
*
*信封加密解密
*参考openssl编程.chm 21.10编程实例4
*
*/
int    EVP_enc()
{

       int                         ret,ekl[2],npubk,inl,outl,total=0,total2=0;

       unsigned long  e=RSA_3;

       char               *ek[2],iv[8],in[100],out[500],de[500];

       EVP_CIPHER_CTX      ctx,ctx2;

       EVP_CIPHER        *type;

       EVP_PKEY            *pubkey[2];

       RSA                      *rkey;

       BIGNUM               *bne;

       int i;

       /* 生成RSA密钥*/

       bne=BN_new();

       ret=BN_set_word(bne,e);

       rkey=RSA_new();

       ret=RSA_generate_key_ex(rkey,1024,bne,NULL);

       pubkey[0]=EVP_PKEY_new();

       EVP_PKEY_assign_RSA(pubkey[0],rkey);	//初始化一个公钥为RSA的密钥对公钥

       type=EVP_des_ede3_cbc();	//对称密钥的算法

       npubk=1;	//设置一个公钥加密

       EVP_CIPHER_CTX_init(&ctx);	//初始化信封加密上下文

       ek[0]=malloc(500);

       ek[1]=malloc(500);

       ret=EVP_SealInit(&ctx,type,(BYTE**)ek,ekl,iv,pubkey,1);  /* 只有一个公钥,如果为CBC算法IV会被产生*/

       if(ret!=1) goto err;

       strcpy(in,"openssl 编程");	//对称密钥(即将被加密为信封的数据)

       inl=strlen(in);

       ret=EVP_SealUpdate(&ctx,out,&outl,in,inl);	//加密操作
	


       if(ret!=1)goto err;

       total+=outl;

       ret=EVP_SealFinal(&ctx,out+outl,&outl);	//加密剩下的部分
	

       if(ret!=1) goto err;

       total+=outl;
	
 	
	/**
	* 解密信封
	*/
       memset(de,0,500);

       EVP_CIPHER_CTX_init(&ctx2);	//初始化解密信封的上下文

       ret=EVP_OpenInit(&ctx2,EVP_des_ede3_cbc(),ek[0],ekl[0],iv,pubkey[0]);	//设置公钥
	

       if(ret!=1) goto err;

       ret=EVP_OpenUpdate(&ctx2,de,&outl,out,total);
	

       total2+=outl;

       ret=EVP_OpenFinal(&ctx2,de+outl,&outl);
	

       total2+=outl;

       de[total2]=0;

       printf("%s\n",de);

err:

       free(ek[0]);

       free(ek[1]);

       EVP_PKEY_free(pubkey[0]);

       BN_free(bne);

       getchar();

       return 0;

}



/**
*
*数字签名与验证
*参考《精通PKI安全认证技术与编程实现》
*
**/
void tSign()
{
	BYTE sign_value[1024]; //保存签名值的数组
	int sign_len; 	//签名值长度
	EVP_MD_CTX mdctx;	//摘要算法上下文变量
	char messl[] = "Test Message";	//签名的消息
	RSA* rsa = NULL; 	//RSA结构体变量
	EVP_PKEY* evpKey = NULL;	//EVP KEY结构体变量
	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");
	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);		//初始化摘要上下文
	if(!EVP_SignInit_ex(&mdctx,EVP_md5(),NULL))	//签名初始化,设置摘要算法
	{
		printf("err\n");
		EVP_PKEY_free(evpKey);
		RSA_free(rsa);
		return;
	}
	if(!EVP_SignUpdate(&mdctx,messl,strlen(messl)))	//计算签名(摘要)Update
	{
		printf("err\n");
		EVP_PKEY_free(evpKey);
		RSA_free(rsa);
		return;
	}
	if(!EVP_SignFinal(&mdctx,sign_value,&sign_len,evpKey))	//签名输出
	{
		printf("err\n");
		EVP_PKEY_free(evpKey);
		RSA_free(rsa);
		return;
	}
	printf("消息\"%s\"的签名值是:\n",messl);
	for(i = 0; i < sign_len; i++)
	{
		if(i%16==0)
			printf("\n%08xH: ",i);
		printf("&%2x ",sign_value[i]);
	}
	printf("\n");
	EVP_MD_CTX_cleanup(&mdctx);
	
	printf("\n 正在验证签名...\n");
	//以下是验证签名的代码
	EVP_MD_CTX_init(&mdctx);	//初始化摘要上下文
	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, messl, strlen(messl)))	//验证签名(摘要)Update
	{
		printf("err\n");
		EVP_PKEY_free(evpKey);
		RSA_free(rsa);
		return;
	}
	if(!EVP_VerifyFinal(&mdctx,sign_value,sign_len,evpKey))
	{
		printf("verify 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);
	return;
}


/**
*
*in为输入的字节数组,len为输入长度,out为输出hash值,outl为输出长度
*MD5摘要算法得到16字节结果
*
*/
void hash_md5(BYTE *in,int len,BYTE* out,int *outl)
{

	/*************
	*
	*将输入初始化到临时BYTE数组
	*
	**************/
	BYTE intemp[len];
	int j;int          i;
	for(j = 0; j<len;j++)
	{
		intemp[j] = in[j];
	}
	   for(i=0;i<16;i++)
                 printf("%x ",out[i]);	
	printf("\n");
	memset(out,0,16);
     
    	intemp[len] = 0;
	size_t       n;
	unsigned long err;
        
	printf("\nMD5 digesting:\n");
	printf("\n%s\n",intemp);
	
	MD5(intemp,n,out);
	



	printf("\n%d\n",n);
        printf("\n\nMD5 digest result :\n");
		
	 printf("\n%s\n",out); 
	/*****
	*
	*MD5输出为16字节
	*
	******/
	//*outl = 16;
        for(i=0;i<16;i++)
                 printf("%x ",out[i]);	
}


你可能感兴趣的:(编程,加密,算法,解密,null,byte)