md5算法在openssl下的實現這裏就不具體說了,下面代碼的功能是隨機生成一個bignum類型的大數,將該大數(保存大數的部分是unsignedlong指針)轉換成16進制然後保存在字符串中,再把該字符串做md5運算,得到摘要。
int sprintf(char *buffer,const char *format, [argument])
指的是字符串格式化命令,主要功能是把格式化的數據寫入某個字符串中。sprintf 是個變參函數。使用sprintf對於寫入buffer的字符數是沒有限制的,這就存在了buffer溢出的可能性。
還要介紹的是字符數組的一個情況,’\0’也要佔一個地方,也就是char a[5] = “abcde”;這樣會報錯,只能保存4個字符。
我的運行環境中char佔一個字節,int佔4個字節,unsigned long 佔8個字節,這個對我們下面設計程序很重要,再附上一個範圍表。
生成的大數指定了是512個位長度,而一個unsigned long 是64個位,也就是說生成的大數裏面指向unsigned long的指針佔了8個unsigned long空間。
我們依次讀出這8個unsigned long,循環八次。
又要考慮是unsigned long 轉換成int 這裏直接轉換寫成 sprintf(temp1,"%016X",a->d[i]); 會有兩個問題。第一個問題是16在計
算機上沒法表示,計算機最大的是16進制只有F,第二個問題是unsigned long的範圍比int的範圍大太多,會丟掉很多數據。
所以就分兩次讀每次讀一半,十個數。我們看到unsignedlong的最大值是18446744073709551615一共20個數,unsigned int的最大值是4294967295,前十個數不會失真,但後面十個數大於了int所能表達的範圍。
那後面的十個數只能再分開讀取了,理所應當的把存它的temp2定義成temp2[5],因爲我們要往裏面放4個char值,20個數的時候是64位,10個數是32位,5個數是16位。這樣想就錯了。
我們可以算一下4個char,一個char 是4位,那一共是16位,可以表示的最大值是2的16次方減1,查表可知是65536,意思就是
如果這個五個數大於65536了,就存不下了,會報錯,數組越界,於是我們只能多分配一個char,定義爲temp[6],用5個char來存
放,這樣能存的最大值是2的20次方減1,足夠了。
Openssl編程中md5摘要的結果是128位,設計過程和上面一樣。
下面是本人寫的源代碼
#include <stdio.h>
#include <openssl/md5.h>
#include <string.h>
#include <openssl/bn.h>
//隨機產生一個大數 用md5轉換成摘要
int main(int argc, const char * argv[]) {
int i;
//產生大數
BIGNUM *a;
char temp[3] = {0};
char temp1[9] = {0};
char temp2[6] = {0};
unsigned char md[16] = {0};
MD5_CTX ctx;
char data[150] = {0};
unsigned long tempnum;
a = BN_new();
BN_rand(a,512,0,0);//生成的大數佔512個字節
printf("%lu\n",(a->d[0])%10000000000);
for(i= 0;i<8;i++)//不會溢出
{
tempnum = (a->d[i])%10000000000;
sprintf(temp1,"%08X",(a->d[i])/10000000000);
strcat(data, temp1);
sprintf(temp2,"%04X",tempnum/100000);
strcat(data, temp2);
sprintf(temp2,"%04X",tempnum%100000);
strcat(data, temp2);
}
printf("隨機產生的大數轉化成16進制後保存爲:%s\n佔了:%d個char\n",data,strlen(data));
//md5操作
MD5_Init(&ctx);
MD5_Update(&ctx, data,strlen(data));
MD5_Final(md, &ctx);
char buf[33] = {0};
for (i=0;i<16;i++)
{
sprintf(temp, "%02X",md[i]);
strcat(buf, temp);
}
printf("md5哈希後的摘要爲:%s\n",buf);
return 0;
}
運行結果:
分析一下結果,第一個值是用來驗證的,是第一個unsigned long的後十位。4140512874,所以應該對應了8個16進制的值。也就是A1BD324A。我們算一下前面4位16進制A1BD是否等於十進制的41405。結果是相同的,所以程序是正確的。