openssl签名验证、信封加密解密、产生随机数、md5摘要
2017-03-07 17:11
1176 查看
from : http://blog.csdn.net/xyyangkun/article/details/8708510
#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]);
}
#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]);
}
相关文章推荐
- openssl签名验证、信封加密解密、产生随机数、md5摘要
- openssl签名验证、信封加密解密、产生随机数、md5摘要
- openssl 非对称加密 RSA 加密解密以及签名验证签名
- C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
- openssl学习篇之base64编码、解码;md5 摘要;sha1摘要;3des加密,解密;rsa算法
- openssl 生成秘钥公钥加密解密签名验证
- C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
- C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
- Openssl Crypto 加/解密功能封装之二:MD5 摘要生成与验证
- C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa)
- 可再发行平台 SDK:CAPICOM ,对数据进行数字签名、对代码签名、验证数字签名、包封保密数据、对数据进行散列处理、加密及解密数据的SDK
- RSA加密解密及RSA签名和验证(RSAHelper)
- 公钥加密 私钥解密,私钥数字签名 公钥验证
- C#中RSA加密解密和签名与验证的实现
- 跨语言平台的RSA加密、解密、签名、验证算法的实现
- PHP实现超简单的SSL加密解密、验证及签名的方法示例
- RSA加密解密及RSA签名和验证
- PHP下SSL加密解密、验证、签名方法(很简单)
- RSA加密解密及RSA签名和验证
- 使用证书对数据进行签名、验签、加密、解密以及openssl的常用方法