php数字签名算法,数字签名算法

#include

#include

#include

#include

#include

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

{

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值