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
#include
#include
#include
//随机产生一个大数 用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。结果是相同的,所以程序是正确的。