用openssl的engine機(jī)制實(shí)現(xiàn)chiper,digest的替換遇到問(wèn)題了,到底EVP是怎么樣調(diào)用init,updata,final以及init,updata,final應(yīng)該如何實(shí)現(xiàn)呢?---------------------------------
消息摘要算法 簡(jiǎn)單接口 簡(jiǎn)單接口使用一個(gè)函數(shù)調(diào)用就可以完成消息摘要計(jì)算,這些接口包括MD2,MD4,MD5,MDC2,RIPEMD,SHA1,函數(shù)聲明都一樣。
以MD5為例,函數(shù)聲明為:
unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md);
其中 d 指向要計(jì)算消息摘要的數(shù)據(jù),n 為數(shù)據(jù)長(zhǎng)度,md 指向保存消息摘要的緩沖區(qū)。如果 md 不為 NULL,那么它的長(zhǎng)度必須能夠容納計(jì)算出來(lái)的消息摘要。對(duì)MD5,這個(gè)長(zhǎng)度至少是 MD5_DIGEST_LENGTH。如果 md 為 NULL,那么計(jì)算出來(lái)的消息摘要保存在一個(gè)靜態(tài)數(shù)組里,函數(shù)返回指向這個(gè)數(shù)組的指針。
下面是一個(gè)使用MD()計(jì)算消息摘要的小程序: //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; }
這個(gè)程序計(jì)算出字符串”Hello,OpenSSL\n”的消息摘要為97aa490ee85f397134404f7bb524b587。可以用Unix下的md5sum程序檢驗(yàn)是否正確:
[root@cat /root]# echo "Hello,OpenSSL" | md5sum
97aa490ee85f397134404f7bb524b587 -
可以看到結(jié)果一樣。
其它算法的計(jì)算類(lèi)似,只用替換源代碼中的md5為相應(yīng)的算法名即可。 標(biāo)準(zhǔn)接口簡(jiǎn)單接口容易使用,但是它要求被摘要數(shù)據(jù)在時(shí)間和空間上都是連續(xù)的。要 計(jì)算不連續(xù)數(shù)據(jù)的摘要,就必須使用標(biāo)準(zhǔn)接口。事實(shí)上,簡(jiǎn)單接口也是通過(guò)調(diào)用標(biāo)準(zhǔn)接口工作的。
以MD5為例,標(biāo)準(zhǔn)接口包括如下函數(shù): 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結(jié)構(gòu),MD5_Update計(jì)算摘要,MD5_Final輸出摘要值。
下面是使用標(biāo)準(zhǔn)接口的 ex1.cpp 程序(只有main函數(shù)不同): //ex2.cpp //包含的頭文件,hexstr函數(shù)都和 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; } 檢驗(yàn): E:\ssl\md5\ex2\Debug>ex2 97aa490ee85f397134404f7bb524b587 可以看出,和 ex1 和 md5sum 的結(jié)果一致。 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方法。任何經(jīng)過(guò)一個(gè)消息摘要BIO的數(shù)據(jù)都 被自動(dòng)摘要。BIO_set_md設(shè)置一個(gè)消息摘要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; }檢驗(yàn)結(jié)果為:97aa490ee85f397134404f7bb524b587,與md5sum的結(jié)果相同, 注意消息摘要BIO比較特殊:數(shù)據(jù)經(jīng)過(guò)這種BIO不被修改,只是摘要值保留在BIO中,需要用BIO_gets而不是BIO_read讀取 |
|