OpenSSL: 消息摘要算法

来源:互联网 发布:android 解析json数组 编辑:程序博客网 时间:2024/05/18 02:00

转载自:http://blog.chinaunix.net/uid-7811535-id-2043442.html  ,感谢作者weigongwan。


opensslengine机制实现chiper,digest的替换遇到问题了,到底EVP是怎么样调用init,updata,final以及init,updata,final应该如何实现呢?

---------------------------------

消息摘要算法

简单接口

简单接口使用一个函数调用就可以完成消息摘要计算,这些接口包括MD2,MD4,MD5,MDC2,RIPEMD,SHA1,函数声明都一样。

MD5为例,函数声明为:

unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md);

其中 d 指向要计算消息摘要的数据,n 为数据长度,md 指向保存消息摘要的缓冲区。如果 md 不为 NULL,那么它的长度必须能够容纳计算出来的消息摘要。对MD5,这个长度至少是 MD5_DIGEST_LENGTH。如果 md 为 NULL,那么计算出来的消息摘要保存在一个静态数组里,函数返回指向这个数组的指针。

    下面是一个使用MD()计算消息摘要的小程序:

//ex1.cpp

#include <stdio.h>

#include <string.h>

#include <openssl/md5.h> 

static char *hexstr(unsigned char *buf,int len)

{

     const char *set = "0123456789abcdef";

     static char str[65],*tmp;

     unsigned char *end; 

     if (len > 32)

         len = 32; 

     end = buf + len;

     tmp = &str[0]; 

     while (buf < end)

     {

         *tmp++ = set[ (*buf) >> 4 ];

         *tmp++ = set[ (*buf) & 0xF ];

         buf ++;

     }

     *tmp = ''; 

     return str;

}

int main(int argc, char* argv[])

{

     char *buf = "Hello,OpenSSL\n";

     unsigned char *md; 

     md = MD5((const unsigned char*)buf,strlen(buf),NULL);

     printf("%s\n",hexstr(md,MD5_DIGEST_LENGTH)); 

     return 0;

} 

这个程序计算出字符串”Hello,OpenSSL\n”的消息摘要为97aa490ee85f397134404f7bb524b587。可以用Unix下的md5sum程序检验是否正确:

[root@cat /root]# echo "Hello,OpenSSL" | md5sum

97aa490ee85f397134404f7bb524b587  -

可以看到结果一样。

其它算法的计算类似,只用替换源代码中的md5为相应的算法名即可。 

标准接口

简单接口容易使用,但是它要求被摘要数据在时间和空间上都是连续的。要

计算不连续数据的摘要,就必须使用标准接口。事实上,简单接口也是通过调用标准接口工作的。

    以MD5为例,标准接口包括如下函数:

    void MD5_Init(MD5_CTX *c);

    void MD5_Update(MD5_CTX *c,const void *data,unsigned long len);

    void MD5_Final(unsigned char *md, MD5_CTX *c);

MD5_Init初始化MD5_CTX结构,MD5_Update计算摘要,MD5_Final输出摘要值。

    下面是使用标准接口的 ex1.cpp 程序(只有main函数不同):

//ex2.cpp

//包含的头文件,hexstr函数都和 ex1.cpp一样

int main(int argc, char* argv[])

{

     char *buf = "Hello";

     char *buf2 = ",";

     char *buf3 = "OpenSSL\n";

     unsigned char md[MD5_DIGEST_LENGTH];

     MD5_CTX ctx;

     MD5_Init(&ctx);

     MD5_Update(&ctx,buf,strlen(buf));

     MD5_Update(&ctx,buf2,strlen(buf2));

     MD5_Update(&ctx,buf3,strlen(buf3));

     MD5_Final(md,&ctx);

    

     printf("%s\n",hexstr(md,MD5_DIGEST_LENGTH));

     return 0;

}

检验:

    E:\ssl\md5\ex2\Debug>ex2

97aa490ee85f397134404f7bb524b587

可以看出,和 ex1 和 md5sum 的结果一致。   

EVP 接口

#include <stdio.h>

#include <string.h>

#include <openssl/evp.h> 

static char *hexstr(unsigned char *buf,int len)

{

     const char *set = "0123456789abcdef";

     static char str[65],*tmp;

     unsigned char *end; 

     if (len > 32)

         len = 32; 

     end = buf + len;

     tmp = &str[0]; 

     while (buf < end)

     {

         *tmp++ = set[ (*buf) >> 4 ];

         *tmp++ = set[ (*buf) & 0xF ];

         buf ++;

     }

     *tmp = ''; 

     return str;

}

int main(int argc, char* argv[])

{

     char *buf = "Hello";

     char *buf2 = ",";

     char *buf3 = "OpenSSL\n";

     unsigned int mdlen;

     unsigned char md[EVP_MAX_MD_SIZE];

     EVP_MD_CTX ctx;

     const EVP_MD *type = EVP_md5(); 

     OpenSSL_add_all_digests(); 

     if (argc > 1)

     {

         type = EVP_get_digestbyname(argv[1]);

         if (type == NULL)

         {

              fprintf(stderr,"Use default : MD5\n");

              type = EVP_md5();

         }

     } 

     EVP_DigestInit(&ctx,type); 

     EVP_DigestUpdate(&ctx,buf,strlen(buf));

     EVP_DigestUpdate(&ctx,buf2,strlen(buf2));

     EVP_DigestUpdate(&ctx,buf3,strlen(buf3)); 

     EVP_DigestFinal(&ctx,md,&mdlen);    

     printf("%s\n",hexstr(md,mdlen)); 

     return 0;

}

BIO 接口

BIO_f_md()返回消息摘要的BIO方法。任何经过一个消息摘要BIO的数据都

被自动摘要。BIO_set_md设置一个消息摘要BIO所使用的摘要算法。

    下面是使用BIO的MD5例子:

#include <stdio.h>

#include <string.h>

#include <openssl/evp.h>

#include <openssl/bio.h> 

static char *hexstr(unsigned char *buf,int len)

{

     const char *set = "0123456789abcdef";

     static char str[65],*tmp;

     unsigned char *end; 

     if (len > 32)

         len = 32; 

     end = buf + len;

     tmp = &str[0]; 

     while (buf < end)

     {

         *tmp++ = set[ (*buf) >> 4 ];

         *tmp++ = set[ (*buf) & 0xF ];

         buf ++;

     }

     *tmp = ''; 

     return str;

}

int main(int argc, char* argv[])

{

     int len;

     const char *str = "Hello,OpenSSL\n";

     BIO *bio_null,*bio_md;

     unsigned char md[EVP_MAX_MD_SIZE]; 

     bio_null = BIO_new(BIO_s_null());

     bio_md = BIO_new(BIO_f_md());

     BIO_set_md(bio_md,EVP_md5());

     bio_md = BIO_push(bio_md,bio_null); 

     BIO_write(bio_md,str,strlen(str));

     BIO_flush(bio_md); 

     len = BIO_gets(bio_md,(char*)md,EVP_MAX_MD_SIZE);

     printf("%s\n",hexstr(md,len)); 

     BIO_free_all(bio_md);

     return 0;

}     

检验结果为:97aa490ee85f397134404f7bb524b587,与md5sum的结果相同, 注意消息摘要BIO比较特殊:数据经过这种BIO不被修改,只是摘要值保留在BIO中,需要用BIO_gets而不是BIO_read读取

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝卖假货遇到打假师怎么办 网店遇到职业打假人怎么办 职业打假师把我起诉法院怎么办 被职业打假举报了怎么办 车档杆拉不动显示不在p档怎么办 宜人贷还不起了怎么办 买高跟鞋一只脚合适一只脚挤怎么办 脚瘦穿高跟鞋撑不起来怎么办 银川市阅海幼儿园进不去怎么办 考编专业不对口怎么办 北京55中国际部怎么办 初中数学没学好高中怎么办 靴子大了一码怎么办 靴子买大了一码怎么办 马丁靴大了一码怎么办 社保掌上通登录密码忘记怎么办 录微课时忘词怎么办 微课掌上通看不到信息怎么办 五年级学生上课很吵新老师怎么办 跟财务老师吵起来怎么办 qq把微信冻结了怎么办 微信给封号了怎么办 微信久了没登录冻结了怎么办 换手机号了微店怎么办 ai文件置入后都是字怎么办 excel加载项被禁用了怎么办 被期刊网骗了怎么办 发表的文章不想被收录怎么办? 农村长说的眼睛害了怎么办 普通党员不认同领导的决定怎么办 大学读不下去了怎么办 教师因病长期不能上班怎么办 长按win键黑屏了怎么办 巡视组巡视出问题后续怎么办 货运资格证两次没继续教育怎么办 电子注册备案表学信网查不到怎么办 学信网学籍档案没照片怎么办 信访局不给答复怎么办 发票跳了一个号怎么办 报税用的ca证书怎么办 报税u盘丢了怎么办