ubuntu下链接c语言实现md5出错
题中所示代码中,python实现了计算空字符串的MD5值,并对MD5的值的十六进制的字符串所表示的字节进行BASE64处理。
不像Python内部有实现md5功能,根据ANSI C标准,C语言的标准库里是没有md5功能的;
但是RFC1231规定了MD5功能的C实现并提供了附件,可以直接用,也可以直接获取现成的实现,在编译链接时指定正确的h头文件和lib静态链接库文件;
这里我采取前者的做法(电脑上没有装VC,有VC就简单很多,使用的是minGW)大概六七百行代码左右。
然后这里展示不完,给个实现效果图
这是我整理的实现代码,其中BASE64部分使用了github上littlestar的b64c,然后MD5计算部分直接参考了RFC1231标准的附录。RFC1231文件有计算方法
BASE64的编码原理
版本 2
支持库 dp1
支持库 spec
子程序 _按钮1_被单击
局部变量 取得的MD5, 字节集
局部变量 路径, 文本型
路径 = “C:\WINDOWS\explorerexe”
如果 (文件是否存在 (路径)) ' 如果文件存在
路径 = 取数据摘要 (读入文件 (路径))
调试输出 (路径)
如果真 (路径 ≠ 编辑框1内容) ' 文件MD5对不上PS:编辑框1的内容就是用来对比的MD5值
' 这里写文件MD5对不上的代码就是你的说下载东东
如果真结束
否则
' 这里写文件不存在的相关代码
和你写了个例程复制进去看看吧 有注释
你的命令写得有问题:
gcc -o maino md5o
-o参数用来指定输出文件名,你这里把maino传给它了,试试:
gcc -o app maino md5o
其实你可以直接一步完成:
gcc md5c mainc -o main
#ifndef MD5_H
#define MD5_H
typedef struct
{
unsigned int count[2];
unsigned int state[4];
unsigned char buffer[64];
}MD5_CTX;
#define F(x,y,z) ((x & y) | (~x & z))
#define G(x,y,z) ((x & z) | (y & ~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y ^ (x | ~z))
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
#define FF(a,b,c,d,x,s,ac) \
{ \
a += F(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define GG(a,b,c,d,x,s,ac) \
{ \
a += G(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define HH(a,b,c,d,x,s,ac) \
{ \
a += H(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
#define II(a,b,c,d,x,s,ac) \
{ \
a += I(b,c,d) + x + ac; \
a = ROTATE_LEFT(a,s); \
a += b; \
}
void MD5Init(MD5_CTX context);
void MD5Update(MD5_CTX context,unsigned char input,unsigned int inputlen);
void MD5Final(MD5_CTX context,unsigned char digest[16]);
void MD5Transform(unsigned int state[4],unsigned char block[64]);
void MD5Encode(unsigned char output,unsigned int input,unsigned int len);
void MD5Decode(unsigned int output,unsigned char input,unsigned int len);
#endif
源文件md5c
#include <memoryh>
#include "md5h"
unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void MD5Init(MD5_CTX context)
{
context->count[0] = 0;
context->count[1] = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
}
void MD5Update(MD5_CTX context,unsigned char input,unsigned int inputlen)
{
unsigned int i = 0,index = 0,partlen = 0;
index = (context->count[0] >> 3) & 0x3F;
partlen = 64 - index;
context->count[0] += inputlen << 3;
if(context->count[0] < (inputlen << 3))
context->count[1]++;
context->count[1] += inputlen >> 29;
if(inputlen >= partlen)
{
memcpy(&context->buffer[index],input,partlen);
MD5Transform(context->state,context->buffer);
for(i = partlen;i+64 <= inputlen;i+=64)
MD5Transform(context->state,&input[i]);
index = 0;
}
else
{
i = 0;
}
memcpy(&context->buffer[index],&input[i],inputlen-i);
}
void MD5Final(MD5_CTX context,unsigned char digest[16])
{
unsigned int index = 0,padlen = 0;
unsigned char bits[8];
index = (context->count[0] >> 3) & 0x3F;
padlen = (index < 56)(56-index):(120-index);
MD5Encode(bits,context->count,8);
MD5Update(context,PADDING,padlen);
MD5Update(context,bits,8);
MD5Encode(digest,context->state,16);
}
void MD5Encode(unsigned char output,unsigned int input,unsigned int len)
{
unsigned int i = 0,j = 0;
while(j < len)
{
output[j] = input[i] & 0xFF;
output[j+1] = (input[i] >> 8) & 0xFF;
output[j+2] = (input[i] >> 16) & 0xFF;
output[j+3] = (input[i] >> 24) & 0xFF;
i++;
j+=4;
}
}
void MD5Decode(unsigned int output,unsigned char input,unsigned int len)
{
unsigned int i = 0,j = 0;
while(j < len)
{
output[i] = (input[j]) |
(input[j+1] << 8) |
(input[j+2] << 16) |
(input[j+3] << 24);
i++;
j+=4;
}
}
void MD5Transform(unsigned int state[4],unsigned char block[64])
{
unsigned int a = state[0];
unsigned int b = state[1];
unsigned int c = state[2];
unsigned int d = state[3];
unsigned int x[64];
MD5Decode(x,block,64);
FF(a, b, c, d, x[ 0], 7, 0xd76aa478); / 1 /
FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); / 2 /
FF(c, d, a, b, x[ 2], 17, 0x242070db); / 3 /
FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); / 4 /
FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); / 5 /
FF(d, a, b, c, x[ 5], 12, 0x4787c62a); / 6 /
FF(c, d, a, b, x[ 6], 17, 0xa8304613); / 7 /
FF(b, c, d, a, x[ 7], 22, 0xfd469501); / 8 /
FF(a, b, c, d, x[ 8], 7, 0x698098d8); / 9 /
FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); / 10 /
FF(c, d, a, b, x[10], 17, 0xffff5bb1); / 11 /
FF(b, c, d, a, x[11], 22, 0x895cd7be); / 12 /
FF(a, b, c, d, x[12], 7, 0x6b901122); / 13 /
FF(d, a, b, c, x[13], 12, 0xfd987193); / 14 /
FF(c, d, a, b, x[14], 17, 0xa679438e); / 15 /
FF(b, c, d, a, x[15], 22, 0x49b40821); / 16 /
分类: 资源共享
解析:
WinMD5 MD5简介
MD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。
Message-Digest泛指字节串(Message)的Hash变换,就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词,是因为这种变换只与字节的值有关,与字符集或编码方式无关。
MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。
MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,你将一段话写在一个叫 readmetxt文件中,并对这个readmetxt产生一个MD5的值并记录在案,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。
MD5还广泛用于加密和解密技术上,在很多操作系统中,用户的密码是以MD5值(或类似的其它算法)的方式保存的, 用户Login的时候,系统是把用户输入的密码计算成MD5值,然后再去和系统中保存的MD5值进行比较,而系统并不“知道”用户的密码是什么。
一些黑客破获这种密码的方法是一种被称为“跑字典”的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。
即使假设密码的最大长度为8,同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是P(62,1)+P (62,2)…+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB级的磁盘组,而且这种方法还有一个前提,就是能获得目标账户的密码MD5值的情况下才可以。
在很多电子商务和社区应用中,管理用户的Account是一种最常用的基本功能,尽管很多 Application Server提供了这些基本组件,但很多应用开发者为了管理的更大的灵活性还是喜欢采用关系数据库来管理用户,懒惰的做法是用户的密码往往使用明文或简单的变换后直接保存在数据库中,因此这些用户的密码对软件开发者或系统管理员来说可以说毫无保密可言,本文的目的是介绍MD5的Java Bean的实现,同时给出用MD5来处理用户的Account密码的例子,这种方法使得管理员和程序设计者都无法看到用户的密码,尽管他们可以初始化它们。但重要的一点是对于用户密码设置习惯的保护。
有兴趣的读者可以从这里取得MD5也就是RFC 1321的文本。
ietf/rfc/rfc1321txt
------------------------------------------------------------------
MD5算法说明
一、补位
二、补数据长度
三、初始化MD5参数
四、处理位操作函数
五、主要变换过程
六、输出结果
补位:
MD5算法先对输入的数据进行补位,使得数据位长度LEN对512求余的结果是448。即数据扩展至K512+448位。即K64+56个字节,K为整数。
具体补位操作:补一个1,然后补0至满足上述要求。
补数据长度:
用一个64位的数字表示数据的原始长度B,把B用两个32位数表示。这时,数据就被填补成长度为512位的倍数。
初始化MD5参数:
四个32位整数 (A,B,C,D) 用来计算信息摘要,初始化使用的是十六进制表示的数字
A=0X
B=0X89abcdef
C=0Xfedcba98
D=0X
处理位操作函数:
X,Y,Z为32位整数。
F(X,Y,Z) = X&Y|NOT(X)&Z
G(X,Y,Z) = X&Z|Y(Z)
H(X,Y,Z) = X xor Y xor Z
I(X,Y,Z) = Y xor (X|not(Z))
主要变换过程:
使用常数组T[1 64], T[i]为32位整数用16进制表示,数据用16个32位的整数数组M[]表示。
具体过程如下:
/ 处理数据原文 /
For i = 0 to N/16-1 do
/每一次,把数据原文存放在16个元素的数组X中 /
For j = 0 to 15 do
Set X[j] to M[i16+j]
end /结束对J的循环
/ Save A as AA, B as BB, C as CC, and D as DD/
AA = A
BB = B
CC = C
DD = D
/ 第1轮/
/ 以 [abcd k s i]表示如下操作 a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) /
/ Do the following 16 operations /
[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 322 4]
[ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 722 8]
[ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA11 22 12]
[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
/ 第2轮 /
/ 以 [abcd k s i]表示如下操作 a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s) /
/ Do the following 16 operations /
[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA0 20 20]
[ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA8 20 28]
[ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA12 20 32]
/ 第3轮/
/ 以 [abcd k s i]表示如下操作 a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s) /
/ Do the following 16 operations /
[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
[ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA10 23 40]
[ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
/ 第4轮/
/ 以 [abcd k s i]表示如下操作 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s) /
/ Do the following 16 operations /
[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
[ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
[ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
[ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
/ 然后进行如下操作 /
A = A + AA
B = B + BB
C = C + CC
D = D + DD
end / 结束对I的循环/
输出结果。
(此文档转自汉化新世纪 余飞雨,特此声明、致谢!)
0条评论