转载声明:http://blog.csdn.net/haroroda/article/details/45935099

这次我分享的是MD5加密算法。其实MD5这个大名在还没上密码学课之前我就听说过了,那时我才刚学PHP,视频里面的讲师说像密码这种重要的信息要用md5()函数处理下再存数据库,这么一说起来其实MD5算是我接触的第一个现代密码呢

考虑到可能有些人是为了科普一下才点进来看的,我还是结合自身经验和课本知识把MD5加密原理讲一下把,MD5算法的具体过程有以下4步:

(1)附加填充位

课本原话:填充一个‘1’和若干个‘0’使其长度模512与448同余,然后再将消息的真实长度以64bit表示附加在填充结果后面,从而使得消息长度恰好为512bit的整数倍。(不知道这段话你们看懂没有,方正我看了很久才看懂的,大概以前语文真的是体育老师教的

举例说明吧:

如明文为iscbupt

其16ascII码是105,115,99,98,117,112,116,转换成二进制便是01101001 01110011 01100011 01100010 01110101 01110000 01110100,这是长度为56,要使其长度模512与448同余,则需补充一个‘1’和391个‘0’。因为消息长度为56,所以用64位二进制表示为00110000   00~00(56个‘0’)。到目前为止512位全部填充完整了~

(2)初始化链接变量

课本原话:MD5中有A、B、C、D 4个32为寄存器,最开始存放4个固定的32位的整数参数,即初始链接变量,这些参数用于第1轮运算。

A=0x12345678,B=0x89ABCDEF,C=0xFEDCBA98,D=0x76543210

(3)分组处理(迭代压缩)

课本原话:MD5算法的分组处理(压缩函数)与分组密码的分组处理相似。它由4轮组成,512bit的消息分组Mi被分成16个子分组(每个子分组为32bit)参与每轮16步函数运算,即每轮包括16个步骤。每步的输入是4个32bit的链接变量(插句话~也就是A、B、C、D)和一个32bit的消息分组(是Mi哦~~),输出为32位值。经过4轮共64步后,得到的4个寄存器值分别与输入链接变量(也就是初始的A、B、C、D)进行模加,即是当前消息的中间散列值。

明文是iscbupt的Mi如下:

M0:01101001 01110011 01100011 01100010

M1:01110101 01110000 01110100 10000000

M2:00000000 00000000 00000000 00000000

................

M14:00111000 00000000 00000000 00000000

M15:00000000 00000000 00000000 00000000

(4)步函数

由于课本的图无法上传,那这里就由我来说下啦~~

所有大轮(上文所说的4轮)里的所有小轮(16轮)都是同一个步函数A=B+((A+f(B,C,D)+M[j]+T[i])<<<s)) 即B、C、D进入f函数(这里的f函数就是课本里的非线性函数,包含F、G、H、I这四种函数),得到的结果与A模加,与M[j]模加(这里的j与第几大轮第几小轮有关),与T[i]模加(这里的i从1取到64),然后进行循环左移(左移的2位数也与第几大轮第几小轮有关),再与B模加,最后得到的结果赋值给A。

一小轮结束后将A赋值给B,B赋值给C,C赋值给D,原本的D赋值给A,赋值完的A、B、C、D便可以进入下一轮。

下面来说下上文j、左移步数step、T[i]的取值情况:

第一大轮:

j在这大轮是按顺序从0取到15

第1、5、9、13小轮step=7;第2、6、10、14小轮step=12;第3、7、11、15小轮step=17;第4、8、12、16小轮step=22

第二大轮:

j的取值顺序为-----1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12

第1、5、9、13小轮step=5;第2、6、10、14小轮step=9;第3、7、11、15小轮step=14;第4、8、12、16小轮step=20

第三大轮:

j的取值顺序为----- 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2

第1、5、9、13小轮step=4;第2、6、10、14小轮step=11;第3、7、11、15小轮step=16;第4、8、12、16小轮step=23

第四大轮:

j的取值顺序为-----0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9

第1、5、9、13小轮step=6;第2、6、10、14小轮step=10;第3、7、11、15小轮step=15;第4、8、12、16小轮step=21

T[i]= 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,

      0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 
   
   MD5的加密原理到这里就讲完了,下面来说下注意事项,也是我这次编程发现的一些理解的误区(这些结论是在明文长度不大于448的情况下成了,大于448是否成立我并没有验证过..):

1.MD5加密算法里面的所有模加都是模2的32次加,而不是模2加。举例说明下模2的32次加:如11101000......(省略了24个‘0’)+01110000.........(省略了24个‘0’)=101011000.......(省略了24个‘0’),共33位,取后32位最终得到01011000........(省略了24个‘0’)。

2.初始的A、B、C、D 4个链接变量与M[j]在进入步函数前要先经过大小端处理,T[i]不需要。

3.位数填充时(64bit),若长度的二进制位数不足,需要在二进制前补齐至8的整数倍而不是4的整数倍。如400=110010000

补齐后是00000001 10010000而不是00011001 00000000

4.大小端处理不是单纯指12345678->78563412,之所以有前面这种变换,是因为12、34、56、78分别表示4个十进制数,也就是说表示第1个十进制数的十六进制数经过转换放在最后,第2个放在第1个前。。当1234表示第1个十进制数、5678表示第2个十进制数时,12345678->56781234而不是78563412。如:明文长度为400,M[14]为0x01900000,转换后为0x00000190而不是0x00009001

下面附上代码(输入的明文字符个数不大于64)

[cpp]  view plain copy
  1. #include<stdio.h>
  2. /*各函数声明*/
  3. void shizhuaner(int in, int n, int *md5);
  4. void shizhuaner_weishu(int in, int *md5);
  5. void shiliuzhuaner(char *t, int *temp);
  6. void c_out(int *a);
  7. void abcd_out(int *a);
  8. void F(int *b, int *c, int *d, int *temp1, int *temp2);
  9. void G(int *b, int *c, int *d, int *temp1, int *temp2);
  10. void H(int *b, int *c, int *d, int *temp);
  11. void I(int *b, int *c, int *d, int *temp);
  12. void yu(int *a, int *b, int *temp);
  13. void huo(int *a, int *b, int *temp);
  14. void fei(int *a, int *temp);
  15. void yihuo(int *a, int *b, int *temp);
  16. void jia(int *a, int *b, int *temp);
  17. /*十进制转二进制函数*/
  18. void shizhuaner(int in, int n, int *md5)
  19. {
  20. int j, s, w;
  21. s = n / 4 + 1;  //s是md5里面组的排位数,w是该组里面的位数
  22. w = n % 4;
  23. j = 1;
  24. do
  25. {
  26. md5[32 * s - 8 * w - j] = in % 2;
  27. in = in / 2;
  28. j++;
  29. } while (in != 0);
  30. while (j <=8)  //二进制不够八位时补零
  31. {
  32. md5[32 * s - 8 * w - j] = 0;
  33. j++;
  34. }
  35. }
  36. /* 位数填充时所用到的十进制转二进制函数 */
  37. void shizhuaner_weishu(int in, int *md5)
  38. {
  39. int i,j,temp, a[64];
  40. for (i = 0; in!= 0; i++)
  41. {
  42. a[i] = in % 2;
  43. in = in / 2;
  44. }
  45. while (i % 8 != 0)  //二进制位数不够八的整数倍时补零
  46. {
  47. a[i] = 0;
  48. i++;
  49. }
  50. for (j = 0; j <i/2; j++)
  51. {
  52. temp = a[i - j - 1];
  53. a[i - j-1] = a[j];
  54. a[j] = temp;
  55. }
  56. temp = i/8;
  57. for (i=i-1; i < 64; i++)
  58. a[i] = 0;
  59. for (i = 0; i < 4; i++)
  60. {
  61. for (j = 0; j < 8; j++)
  62. md5[512 - temp * 8 + j - 32] = a[i * 8 + j];
  63. temp = temp - 1;
  64. }
  65. for (i = 0; i < 4; i++)
  66. {
  67. for (j = 0; j < 8; j++)
  68. md5[512 - (i + 1) * 8 + j ] = a[i * 8 + j+32];
  69. }
  70. }
  71. /* 十六进制转二进制函数 */
  72. void shiliuzhuaner(char *t, int *temp)
  73. {
  74. int i;
  75. for (i = 0; i < 8; i++)
  76. {
  77. switch (t[i])
  78. {
  79. case '0':{temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 0; }break;
  80. case '1':{temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 1; }break;
  81. case '2':{temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 1; temp[4 * i + 3] = 0; }break;
  82. case '3':{temp[4 * i] = 0; temp[4 * i + 1] = 0; temp[4 * i + 2] = 1; temp[4 * i + 3] = 1; }break;
  83. case '4':{temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 0; temp[4 * i + 3] = 0; }break;
  84. case '5':{temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 0; temp[4 * i + 3] = 1; }break;
  85. case '6':{temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 1; temp[4 * i + 3] = 0; }break;
  86. case '7':{temp[4 * i] = 0; temp[4 * i + 1] = 1; temp[4 * i + 2] = 1; temp[4 * i + 3] = 1; }break;
  87. case '8':{temp[4 * i] = 1; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 0; }break;
  88. case '9':{temp[4 * i] = 1; temp[4 * i + 1] = 0; temp[4 * i + 2] = 0; temp[4 * i + 3] = 1; }break;
  89. case 'a':{temp[4 * i] = 1; temp[4 * i + 1] = 0; temp[4 * i + 2] = 1; temp[4 * i + 3] = 0; }break;
  90. case 'b':{temp[4 * i] = 1; temp[4 * i + 1] = 0; temp[4 * i + 2] = 1; temp[4 * i + 3] = 1; }break;
  91. case 'c':{temp[4 * i] = 1; temp[4 * i + 1] = 1; temp[4 * i + 2] = 0; temp[4 * i + 3] = 0; }break;
  92. case 'd':{temp[4 * i] = 1; temp[4 * i + 1] = 1; temp[4 * i + 2] = 0; temp[4 * i + 3] = 1; }break;
  93. case 'e':{temp[4 * i] = 1; temp[4 * i + 1] = 1; temp[4 * i + 2] = 1; temp[4 * i + 3] = 0; }break;
  94. case 'f':{temp[4 * i] = 1; temp[4 * i + 1] = 1; temp[4 * i + 2] = 1; temp[4 * i + 3] = 1; }break;
  95. }
  96. }
  97. }
  98. /* 密文输出函数 */
  99. void c_out(int *a)
  100. {
  101. int i,add;
  102. for (i = 1; i <= 4; i++)  //二进制转换成十六进制输出
  103. {
  104. add = a[32 - i * 8] * 8 + a[32 - i * 8 + 1] * 4 + a[32 - i * 8 + 2] * 2 + a[32 - i * 8 + 3];
  105. if (add >= 10)
  106. {
  107. switch (add)
  108. {
  109. case 10:printf("a"); break;
  110. case 11:printf("b"); break;
  111. case 12:printf("c"); break;
  112. case 13:printf("d"); break;
  113. case 14:printf("e"); break;
  114. case 15:printf("f"); break;
  115. }
  116. }
  117. else
  118. printf("%d", add);
  119. add = a[32 - i * 8+4] * 8 + a[32 - i * 8 + 5] * 4 + a[32 - i * 8 + 6] * 2 + a[32 - i * 8 + 7];
  120. if (add >= 10)
  121. {
  122. switch (add)
  123. {
  124. case 10:printf("a"); break;
  125. case 11:printf("b"); break;
  126. case 12:printf("c"); break;
  127. case 13:printf("d"); break;
  128. case 14:printf("e"); break;
  129. case 15:printf("f"); break;
  130. }
  131. }
  132. else
  133. printf("%d", add);
  134. }
  135. }
  136. /* 中间过程的输出函数 */
  137. void abcd_out(int *a)
  138. {
  139. int i, add;
  140. for (i = 0; i < 4; i++)  //二进制转换成十六进制输出
  141. {
  142. add = a[i * 8] * 8 + a[i * 8 + 1] * 4 + a[i * 8 + 2] * 2 + a[i * 8 + 3];
  143. if (add >= 10)
  144. {
  145. switch (add)
  146. {
  147. case 10:printf("a"); break;
  148. case 11:printf("b"); break;
  149. case 12:printf("c"); break;
  150. case 13:printf("d"); break;
  151. case 14:printf("e"); break;
  152. case 15:printf("f"); break;
  153. }
  154. }
  155. else
  156. printf("%d", add);
  157. add = a[i * 8 + 4] * 8 + a[i * 8 + 5] * 4 + a[i * 8 + 6] * 2 + a[i * 8 + 7];
  158. if (add >= 10)
  159. {
  160. switch (add)
  161. {
  162. case 10:printf("a"); break;
  163. case 11:printf("b"); break;
  164. case 12:printf("c"); break;
  165. case 13:printf("d"); break;
  166. case 14:printf("e"); break;
  167. case 15:printf("f"); break;
  168. }
  169. }
  170. else
  171. printf("%d", add);
  172. }
  173. }
  174. /* 与函数 */
  175. void yu(int *a, int *b,int *temp)
  176. {
  177. int i;
  178. for (i = 0; i < 32; i++)  //同为1为1,否则为0
  179. {
  180. if (a[i] == 1 && b[i] == 1)
  181. temp[i] = 1;
  182. else
  183. temp[i] = 0;
  184. }
  185. }
  186. /* 或函数 */
  187. void huo(int *a, int *b, int *temp)
  188. {
  189. int i;
  190. for (i = 0; i < 32; i++)  //同0为0,否则为1
  191. {
  192. if (a[i] == 0 && b[i] == 0)
  193. temp[i] = 0;
  194. else
  195. temp[i] = 1;
  196. }
  197. }
  198. /* 非函数 */
  199. void fei(int *a, int *temp)
  200. {
  201. int i;
  202. for (i = 0; i < 32; i++)
  203. {
  204. if (a[i] == 0)
  205. temp[i] = 1;
  206. else
  207. temp[i] = 0;
  208. }
  209. }
  210. /*异或函数*/
  211. void yihuo(int *a, int *b, int *temp)
  212. {
  213. int i;
  214. for (i = 0; i < 32; i++)  //相同为0,不同为1
  215. {
  216. if (a[i] != b[i])
  217. temp[i] = 1;
  218. else
  219. temp[i] = 0;
  220. }
  221. }
  222. /* 模二的32次加 */
  223. void jia(int *a, int *b, int *temp)
  224. {
  225. int i,jin;
  226. jin = 0;
  227. for (i = 0; i < 32; i++)
  228. {
  229. if (a[31 - i] + b[31 - i] + jin>1)
  230. {
  231. temp[31 - i] = a[31 - i] + b[31 - i] + jin - 2;
  232. jin = 1;
  233. }
  234. else
  235. {
  236. temp[31 - i] = a[31 - i] + b[31 - i]+jin;
  237. jin = 0;
  238. }
  239. }
  240. }
  241. /* F函数 */
  242. void F(int *b, int *c, int *d,int *temp1,int *temp2)
  243. {
  244. /* F(x,y,z)=(x∧y)∨(¬x∧z) */
  245. yu(b, c, temp1);
  246. fei(b, temp2);
  247. yu(temp2, d, temp2);
  248. huo(temp1, temp2, temp2);
  249. }
  250. /* G函数 */
  251. void G(int *b, int *c, int *d, int *temp1, int *temp2)
  252. {
  253. /* G(x,y,z)=(x∧z)∨(y∧¬z) */
  254. yu(b, d, temp1);
  255. fei(d, temp2);
  256. yu(temp2, c, temp2);
  257. huo(temp1, temp2, temp2);
  258. }
  259. /* H函数 */
  260. void H(int *b, int *c, int *d, int *temp)
  261. {
  262. /* H(x,y,z)=x⊕y⊕z */
  263. yihuo(b, c, temp);
  264. yihuo(temp, d, temp);
  265. }
  266. /* I函数 */
  267. void I(int *b, int *c, int *d, int *temp)
  268. {
  269. /* I(x,y,z)=y⊕(x∨¬z) */
  270. fei(d, temp);
  271. huo(b, temp, temp);
  272. yihuo(c, temp, temp);
  273. }
  274. /*左移函数*/
  275. void move(int step, int *temp1, int *temp2)
  276. {
  277. int i;
  278. for (i = 0; i < 32 - step; i++)
  279. temp2[i] = temp1[i + step];
  280. for (i = 0; i < step; i++)
  281. temp2[32 - step + i] = temp1[i];
  282. }
  283. /*每一大轮的16小轮循环函数*/
  284. void round(int *a, int *b, int *c, int *d, int *m, int *md5, int r, char *t1,
  285. char *t2, char *t3, char *t4, char *t5, char *t6, char *t7, char *t8, char *t9,
  286. char *t10, char *t11, char *t12, char *t13, char *t14, char *t15, char *t16 )
  287. {
  288. int i, j, in, step , temp1[32], temp2[32];
  289. for (i = 0; i < 16; i++)
  290. {
  291. switch (r)  //根据r判断所选的逻辑函数
  292. {
  293. case 1:F(b, c, d, temp1, temp2); break;
  294. case 2:G(b, c, d, temp1, temp2); break;
  295. case 3:H(b, c, d, temp2); break;
  296. case 4:I(b, c, d, temp2); break;
  297. }
  298. in = m[i];
  299. for (j = 0; j < 32; j++)
  300. temp1[j] = md5[in * 32 + j];
  301. jia(temp2, temp1, temp2);
  302. switch (i + 1)  //选择t[]
  303. {
  304. case 1:shiliuzhuaner(t1, temp1); break;
  305. case 2:shiliuzhuaner(t2, temp1); break;
  306. case 3:shiliuzhuaner(t3, temp1); break;
  307. case 4:shiliuzhuaner(t4, temp1); break;
  308. case 5:shiliuzhuaner(t5, temp1); break;
  309. case 6:shiliuzhuaner(t6, temp1); break;
  310. case 7:shiliuzhuaner(t7, temp1); break;
  311. case 8:shiliuzhuaner(t8, temp1); break;
  312. case 9:shiliuzhuaner(t9, temp1); break;
  313. case 10:shiliuzhuaner(t10, temp1); break;
  314. case 11:shiliuzhuaner(t11, temp1); break;
  315. case 12:shiliuzhuaner(t12, temp1); break;
  316. case 13:shiliuzhuaner(t13, temp1); break;
  317. case 14:shiliuzhuaner(t14, temp1); break;
  318. case 15:shiliuzhuaner(t15, temp1); break;
  319. case 16:shiliuzhuaner(t16, temp1); break;
  320. }
  321. jia(temp2, temp1, temp2);
  322. jia(temp2, a, temp2);
  323. switch(r)  //根据r为左移步数step赋值
  324. {
  325. case 1:switch (i % 4 + 1){ case 1:step = 7; break; case 2:step = 12; break; case 3:step = 17; break; case 4:step = 22; break; }break;
  326. case 2:switch (i % 4 + 1){ case 1:step = 5; break; case 2:step = 9; break; case 3:step = 14; break; case 4:step = 20; break; }break;
  327. case 3:switch (i % 4 + 1){ case 1:step = 4; break; case 2:step = 11; break; case 3:step = 16; break; case 4:step = 23; break; }break;
  328. case 4:switch (i % 4 + 1){ case 1:step = 6; break; case 2:step = 10; break; case 3:step = 15; break; case 4:step = 21; break; }break;
  329. }
  330. move(step, temp2, temp1);
  331. jia(temp1, b, temp2);
  332. for (j = 0; j < 32; j++)
  333. {
  334. a[j] = d[j];
  335. d[j] = c[j];
  336. c[j] = b[j];
  337. b[j] = temp2[j];
  338. }
  339. /*若想输出每轮a、b、c、d的值,把下面的注释取消即可*/
  340. /*printf("第%d大轮的第%d小轮\n", r, i);
  341. abcd_out(a);
  342. printf("   ");
  343. abcd_out(b);
  344. printf("   ");
  345. abcd_out(c);
  346. printf("   ");
  347. abcd_out(d);
  348. printf("\n");*/
  349. }
  350. }
  351. /* 主函数 */
  352. int main()
  353. {
  354. char ch,
  355. /* 一大坨t[] */
  356. t1[8] = { 'd', '7', '6', 'a', 'a', '4', '7', '8' },
  357. t2[8] = { 'e', '8', 'c', '7', 'b', '7', '5', '6' },
  358. t3[8] = { '2', '4', '2', '0', '7', '0', 'd', 'b' },
  359. t4[8] = { 'c', '1', 'b', 'd', 'c', 'e', 'e', 'e' },
  360. t5[8] = { 'f', '5', '7', 'c', '0', 'f', 'a', 'f' },
  361. t6[8] = { '4', '7', '8', '7', 'c', '6', '2', 'a' },
  362. t7[8] = { 'a', '8', '3', '0', '4', '6', '1', '3' },
  363. t8[8] = { 'f', 'd', '4', '6', '9', '5', '0', '1' },
  364. t9[8] = { '6', '9', '8', '0', '9', '8', 'd', '8' },
  365. t10[8] = { '8', 'b', '4', '4', 'f', '7', 'a', 'f' },
  366. t11[8] = { 'f', 'f', 'f', 'f', '5', 'b', 'b', '1' },
  367. t12[8] = { '8', '9', '5', 'c', 'd', '7', 'b', 'e' },
  368. t13[8] = { '6', 'b', '9', '0', '1', '1', '2', '2' },
  369. t14[8] = { 'f', 'd', '9', '8', '7', '1', '9', '3' },
  370. t15[8] = { 'a', '6', '7', '9', '4', '3', '8', 'e' },
  371. t16[8] = { '4', '9', 'b', '4', '0', '8', '2', '1' },
  372. t17[8] = { 'f', '6', '1', 'e', '2', '5', '6', '2' },
  373. t18[8] = { 'c', '0', '4', '0', 'b', '3', '4', '0' },
  374. t19[8] = { '2', '6', '5', 'e', '5', 'a', '5', '1' },
  375. t20[8] = { 'e', '9', 'b', '6', 'c', '7', 'a', 'a' },
  376. t21[8] = { 'd', '6', '2', 'f', '1', '0', '5', 'd' },
  377. t22[8] = { '0', '2', '4', '4', '1', '4', '5', '3' },
  378. t23[8] = { 'd', '8', 'a', '1', 'e', '6', '8', '1' },
  379. t24[8] = { 'e', '7', 'd', '3', 'f', 'b', 'c', '8' },
  380. t25[8] = { '2', '1', 'e', '1', 'c', 'd', 'e', '6' },
  381. t26[8] = { 'c', '3', '3', '7', '0', '7', 'd', '6' },
  382. t27[8] = { 'f', '4', 'd', '5', '0', 'd', '8', '7' },
  383. t28[8] = { '4', '5', '5', 'a', '1', '4', 'e', 'd' },
  384. t29[8] = { 'a', '9', 'e', '3', 'e', '9', '0', '5' },
  385. t30[8] = { 'f', 'c', 'e', 'f', 'a', '3', 'f', '8' },
  386. t31[8] = { '6', '7', '6', 'f', '0', '2', 'd', '9' },
  387. t32[8] = { '8', 'd', '2', 'a', '4', 'c', '8', 'a' },
  388. t33[8] = { 'f', 'f', 'f', 'a', '3', '9', '4', '2' },
  389. t34[8] = { '8', '7', '7', '1', 'f', '6', '8', '1' },
  390. t35[8] = { '6', 'd', '9', 'd', '6', '1', '2', '2' },
  391. t36[8] = { 'f', 'd', 'e', '5', '3', '8', '0', 'c' },
  392. t37[8] = { 'a', '4', 'b', 'e', 'e', 'a', '4', '4' },
  393. t38[8] = { '4', 'b', 'd', 'e', 'c', 'f', 'a', '9' },
  394. t39[8] = { 'f', '6', 'b', 'b', '4', 'b', '6', '0' },
  395. t40[8] = { 'b', 'e', 'b', 'f', 'b', 'c', '7', '0' },
  396. t41[8] = { '2', '8', '9', 'b', '7', 'e', 'c', '6' },
  397. t42[8] = { 'e', 'a', 'a', '1', '2', '7', 'f', 'a' },
  398. t43[8] = { 'd', '4', 'e', 'f', '3', '0', '8', '5' },
  399. t44[8] = { '0', '4', '8', '8', '1', 'd', '0', '5' },
  400. t45[8] = { 'd', '9', 'd', '4', 'd', '0', '3', '9' },
  401. t46[8] = { 'e', '6', 'd', 'b', '9', '9', 'e', '5' },
  402. t47[8] = { '1', 'f', 'a', '2', '7', 'c', 'f', '8' },
  403. t48[8] = { 'c', '4', 'a', 'c', '5', '6', '6', '5' },
  404. t49[8] = { 'f', '4', '2', '9', '2', '2', '4', '4' },
  405. t50[8] = { '4', '3', '2', 'a', 'f', 'f', '9', '7' },
  406. t51[8] = { 'a', 'b', '9', '4', '2', '3', 'a', '7' },
  407. t52[8] = { 'f', 'c', '9', '3', 'a', '0', '3', '9' },
  408. t53[8] = { '6', '5', '5', 'b', '5', '9', 'c', '3' },
  409. t54[8] = { '8', 'f', '0', 'c', 'c', 'c', '9', '2' },
  410. t55[8] = { 'f', 'f', 'e', 'f', 'f', '4', '7', 'd' },
  411. t56[8] = { '8', '5', '8', '4', '5', 'd', 'd', '1' },
  412. t57[8] = { '6', 'f', 'a', '8', '7', 'e', '4', 'f' },
  413. t58[8] = { 'f', 'e', '2', 'c', 'e', '6', 'e', '0' },
  414. t59[8] = { 'a', '3', '0', '1', '4', '3', '1', '4' },
  415. t60[8] = { '4', 'e', '0', '8', '1', '1', 'a', '1' },
  416. t61[8] = { 'f', '7', '5', '3', '7', 'e', '8', '2' },
  417. t62[8] = { 'b', 'd', '3', 'a', 'f', '2', '3', '5' },
  418. t63[8] = { '2', 'a', 'd', '7', 'd', '2', 'b', 'b' },
  419. t64[8] = { 'e', 'b', '8', '6', 'd', '3', '9', '1' };
  420. int in, n = 0, i,j,addup;
  421. int md5[512],
  422. /*每一大轮m[]的调用顺序*/
  423. m1[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
  424. m2[16] = { 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 },
  425. m3[16] = { 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 },
  426. m4[16] = { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 },
  427. /* a[]、b[]、c[]、d[]的初始值(已经过大小端处理) */
  428. /* 把a[]、b[]、c[]、d[]赋值给a1[]、b1[]、c1[]、d1[]*/
  429. a[32] = { 0, 1, 1, 0, 0, 1, 1, 1,
  430. 0, 1, 0, 0, 0, 1, 0, 1,
  431. 0, 0, 1, 0, 0, 0, 1, 1,
  432. 0, 0, 0, 0, 0, 0, 0, 1 },
  433. a1[32] = { 0, 1, 1, 0, 0, 1, 1, 1,
  434. 0, 1, 0, 0, 0, 1, 0, 1,
  435. 0, 0, 1, 0, 0, 0, 1, 1,
  436. 0, 0, 0, 0, 0, 0, 0, 1 },
  437. b[32] = { 1, 1, 1, 0, 1, 1, 1, 1,
  438. 1, 1, 0, 0, 1, 1, 0, 1,
  439. 1, 0, 1, 0, 1, 0, 1, 1,
  440. 1, 0, 0, 0, 1, 0, 0, 1 },
  441. b1[32] = { 1, 1, 1, 0, 1, 1, 1, 1,
  442. 1, 1, 0, 0, 1, 1, 0, 1,
  443. 1, 0, 1, 0, 1, 0, 1, 1,
  444. 1, 0, 0, 0, 1, 0, 0, 1 },
  445. c[32] = { 1, 0, 0, 1, 1, 0, 0, 0,
  446. 1, 0, 1, 1, 1, 0, 1, 0,
  447. 1, 1, 0, 1, 1, 1, 0, 0,
  448. 1, 1, 1, 1, 1, 1, 1, 0 },
  449. c1[32] = { 1, 0, 0, 1, 1, 0, 0, 0,
  450. 1, 0, 1, 1, 1, 0, 1, 0,
  451. 1, 1, 0, 1, 1, 1, 0, 0,
  452. 1, 1, 1, 1, 1, 1, 1, 0 },
  453. d[32] = { 0, 0, 0, 1, 0, 0, 0, 0,
  454. 0, 0, 1, 1, 0, 0, 1, 0,
  455. 0, 1, 0, 1, 0, 1, 0, 0,
  456. 0, 1, 1, 1, 0, 1, 1, 0 },
  457. d1[32] = { 0, 0, 0, 1, 0, 0, 0, 0,
  458. 0, 0, 1, 1, 0, 0, 1, 0,
  459. 0, 1, 0, 1, 0, 1, 0, 0,
  460. 0, 1, 1, 1, 0, 1, 1, 0 };
  461. printf("请输入需加密的明文(长度不大于56)\n");
  462. ch = getchar();
  463. while (ch!='\n'&&n<57)  //用getchar()函数接收字符,直到接收到回车符或字符数超过56为止
  464. {
  465. in = (int)ch;
  466. shizhuaner(in, n, md5);
  467. n++;
  468. ch = getchar();
  469. }
  470. i = 0;
  471. addup = n;
  472. while (n% 4 != 0 && n<56)  //长度不是4的倍数,补一个1和0直到长度为4的倍数,,最终实现用1与0使其长度模512与448同于,在这个程序里也就是448
  473. {
  474. int s, w, j;
  475. s = n / 4 + 1;
  476. w = n % 4;
  477. j = 1;
  478. do
  479. {
  480. md5[32 * s - 8 * w - j] = 0;
  481. j++;
  482. } while (j<=7);
  483. if (i == 0)
  484. {
  485. md5[32 * s - 8 * w - j] = 1;
  486. i = 1;
  487. }
  488. n++;
  489. }
  490. if (i == 0)  //长度不是4的倍数,补一个1和31个0
  491. {
  492. for (j = 0; j < 32; j++)
  493. md5[n * 8 + j] = 0;
  494. md5[8 * n + 24] = 1;
  495. }
  496. for (i = 0; i < 512; i++)  //补零,任何不为1的数都设为0
  497. {
  498. if (md5[i] == 1)
  499. md5[i] = 1;
  500. else
  501. md5[i] = 0;
  502. }
  503. printf("\n");
  504. shizhuaner_weishu(addup * 8, md5);  //64位数填充
  505. /*若想看m[0]~m[15],把下面注释去掉即可*/
  506. /*printf("m[0]~m[15]如下:\n");
  507. for (i = 0; i < 512; i++)
  508. {
  509. printf("%d ", md5[i]);
  510. if (i % 8 == 7)
  511. printf("\n");
  512. if (i % 32 == 31)
  513. printf("\n");
  514. }
  515. printf("\n");*/
  516. /* 第一、二、三、四大轮,每一大轮下有16小轮 */
  517. round(a, b, c, d, m1, md5, 1, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16);
  518. round(a, b, c, d, m2, md5, 2, t17, t18, t19, t20, t21, t22, t23, t24, t25, t26, t27, t28, t29, t30, t31, t32);
  519. round(a, b, c, d, m3, md5, 3, t33, t34, t35, t36, t37, t38, t39, t40, t41, t42, t43, t44, t45, t46, t47, t48);
  520. round(a, b, c, d, m4, md5, 4, t49, t50, t51, t52, t53, t54, t55, t56, t57, t58, t59, t60, t61, t62, t63, t64);
  521. printf("\n");
  522. /* 最终的a、b、c、d分别与最初的a、b、c、d相加 */
  523. jia(a, a1, a);
  524. jia(b, b1, b);
  525. jia(c, c1, c);
  526. jia(d, d1, d);
  527. /*密文输出*/
  528. printf("密文:\n");
  529. c_out(a);
  530. c_out(b);
  531. c_out(c);
  532. c_out(d);
  533. printf("\n");
  534. return 0;
  535. }

运行结果:

示例1

示例2

示例3

使用说明:

1.因为我对位运算不是很了解,所以这份代码是没有使用位运算的。如果看时觉得混乱可以发邮件给我

2.默认情况下这份代码是不输出M[0]~M[15]和4大轮16小轮中A、B、C、D的变化情况的,如果想输出以上内容的话,在适当的位置取消注释便可(代码中有注释说明位置)

C语言实现MD5加密算法相关推荐

  1. php md5加密算法源码,MD5加密和哈希算法

    MD5加密算法为现在应用最广泛的哈希算法之一,该算法广泛应用于互联网网站的用户文件加密,能够将用户密码加密为128位的长整数.数据库并不明文存储用户密码,而是在用户登录时将输入密码字符串进行MD5加密 ...

  2. md5加密算法原理及其GO语言实现

    md5加密算法原理及其GO语言实现 MD5讯息摘要演算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码杂凑函数,可以产生出一个128位元(16位元组)的散列值 ...

  3. c语言压缩并加密算法,C语言压缩文件和用MD5算法校验文件完整性的实例教程

    使用lzma SDK对7z文件简单解压缩有时候我们只需要单纯对lzma算法压缩的7z文件进行解压,有时需要在嵌入式设备上解压,使用p7zip虽然支持多种格式,但是不容易裁剪,使用lzma SDK是首选 ...

  4. 简要分析用MD5加密算法加密信息(如有疑问,敬请留言)

    一.引言 最近看了媒体的一篇关于"网络上公开叫卖个人隐私信息"报导,不法分子通过非法手段获得的个人隐私信息,其详细.准确程度简直令人瞠口结舌.在互联网飞速发展的现在,我们不难想到, ...

  5. MD5加密算法及Java实现

    MD5加密算法及Java实现 上个学期在学数据库的时候,大作业是用Java Web+MySQL实现一个简易的系统,其中老师就提到了MD5算法,用来将用户提交的密码进行加密后放在数据库中,以防被泄露.在 ...

  6. go语言之各种加密算法的使用

    go语言之各种加密算法的使用 加密算法常用于数据传输中的封装,下面看看如何使用go语言库封装好的加密算法. 直接看代码. package main import ( "encoding/ba ...

  7. c++Builder XE6 MD5 加密算法 BASE64 URL 编码

    xe6,xe7 BASE64XE6 MD5 加密算法Delphifunction MD5(const texto: string): string; varidmd5: TIdHashMessageD ...

  8. 一种增强的md5加密算法

    一种增强的md5加密算法 2008-06-04 16:26:48 标签:加密算法 md5 一种 增强的 [推送到技术圈] 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一种增强的md5加密算法 ...

  9. python md5加密解密_Python使用MD5加密算法对字符串进行加密操作示例

    本文实例讲述了Python使用MD5加密算法对字符串进行加密操作.分享给大家供大家参考,具体如下: # encoding: utf-8 from __future__ import division ...

最新文章

  1. TCP 为什么是三次握手,而不是两次或四次?
  2. Linux Kernel TCP/IP Stack — L1 Layer — NIC bonding
  3. autosar can协议栈 源码解读_我用一晚上时间给女朋友讲懂CAN总线的AUTOSAR网络管理...
  4. [Linux]进程(十二)--task_struct结构体
  5. 求离散马尔科夫链的平稳分布+按照一定概率分布生成想要的样本
  6. java邮件实例_java邮件小实例
  7. 如何修改ant-input的高度_如何利用好Solidworks零件及装配体的多种配置方法?
  8. Linux启动芯片的初始代码,Linux系统初始化流程(简述)
  9. 记一次Java面试中遇到的三个问题及感悟!
  10. [hdu2089]不要62(数位dp)
  11. C++ 编译期封装-Pimpl技术
  12. [解决方案]在Sql Server 2008/2005 数据库还原出现 3154错误
  13. 3D建模软件的选择(UG,Solidworks,ProE)
  14. 【爱情】男女关系大实话 婚姻篇
  15. HTC Desire获取ROOT方法--HTC Desire rooting guide (now with new improved / easier root method!)
  16. Google pixel Android 8.0 模拟器
  17. 中科院JCR期刊分区微信公众号查询平台升级
  18. 计量经济学学习笔记:导论
  19. android sony 镜像,Xperia 1 II将索尼的无镜像相机技术引入智能手机
  20. 80后都有幸看过的20大经典动漫‘禁片’

热门文章

  1. flex简介——css
  2. 什么是:堡垒机、虚拟专用网、日志审计、数据库防水坝、防火墙
  3. 组播地址MAC的计算
  4. Matlab中reshape函数的使用
  5. Linux中 strsep 函数 详解
  6. 全球与中国板上芯片LED行业发展规模及投资前景预测报告2022-2028年
  7. exec 和 exec_
  8. 不干胶标签的印刷工艺
  9. 用css解决Unigui在IE系列浏览器中字体变小的问题
  10. Linux下批处理文件编写