• Source
    1. #include <stdlib.h>
    2. #include <string.h>
    3. #include <stdio.h>
    4. typedef unsigned int uint;
    5. typedef unsigned char byte;
    6.  
    7. /*
    8.  * Эта утилита считает и выводит контрольную сумму файла (md5)
    9.  */
    10.  
    11. /*
    12.  * Значения циклического сдвига влево
    13.  */
    14. enum
    15. {
    16. S11= 7,
    17. S12= 12,
    18. S13= 17,
    19. S14= 22,
    20.  
    21. S21= 5,
    22. S22= 9,
    23. S23= 14,
    24. S24= 20,
    25.  
    26. S31= 4,
    27. S32= 11,
    28. S33= 16,
    29. S34= 23,
    30.  
    31. S41= 6,
    32. S42= 10,
    33. S43= 15,
    34. S44= 21
    35. };
    36.  
    37. typedef struct Table
    38. {
    39. uint sin; /* 4294967296 * abs(sin(i)) */
    40. byte x; /* Переменная с данными из файла */
    41. byte rot; /* Значение циклического сдвига */
    42. }Table;
    43.  
    44. Table tab[] =
    45. {
    46. /* Раунд 1 */
    47. { 0xd76aa478, 0, S11},
    48. { 0xe8c7b756, 1, S12},
    49. { 0x242070db, 2, S13},
    50. { 0xc1bdceee, 3, S14},
    51. { 0xf57c0faf, 4, S11},
    52. { 0x4787c62a, 5, S12},
    53. { 0xa8304613, 6, S13},
    54. { 0xfd469501, 7, S14},
    55. { 0x698098d8, 8, S11},
    56. { 0x8b44f7af, 9, S12},
    57. { 0xffff5bb1, 10, S13},
    58. { 0x895cd7be, 11, S14},
    59. { 0x6b901122, 12, S11},
    60. { 0xfd987193, 13, S12},
    61. { 0xa679438e, 14, S13},
    62. { 0x49b40821, 15, S14},
    63.  
    64. /* Раунд 2 */
    65. { 0xf61e2562, 1, S21},
    66. { 0xc040b340, 6, S22},
    67. { 0x265e5a51, 11, S23},
    68. { 0xe9b6c7aa, 0, S24},
    69. { 0xd62f105d, 5, S21},
    70. { 0x2441453, 10, S22},
    71. { 0xd8a1e681, 15, S23},
    72. { 0xe7d3fbc8, 4, S24},
    73. { 0x21e1cde6, 9, S21},
    74. { 0xc33707d6, 14, S22},
    75. { 0xf4d50d87, 3, S23},
    76. { 0x455a14ed, 8, S24},
    77. { 0xa9e3e905, 13, S21},
    78. { 0xfcefa3f8, 2, S22},
    79. { 0x676f02d9, 7, S23},
    80. { 0x8d2a4c8a, 12, S24},
    81.  
    82. /* Раунд 3 */
    83. { 0xfffa3942, 5, S31},
    84. { 0x8771f681, 8, S32},
    85. { 0x6d9d6122, 11, S33},
    86. { 0xfde5380c, 14, S34},
    87. { 0xa4beea44, 1, S31},
    88. { 0x4bdecfa9, 4, S32},
    89. { 0xf6bb4b60, 7, S33},
    90. { 0xbebfbc70, 10, S34},
    91. { 0x289b7ec6, 13, S31},
    92. { 0xeaa127fa, 0, S32},
    93. { 0xd4ef3085, 3, S33},
    94. { 0x4881d05, 6, S34},
    95. { 0xd9d4d039, 9, S31},
    96. { 0xe6db99e5, 12, S32},
    97. { 0x1fa27cf8, 15, S33},
    98. { 0xc4ac5665, 2, S34},
    99.  
    100. /* Раунд 4 */
    101. { 0xf4292244, 0, S41},
    102. { 0x432aff97, 7, S42},
    103. { 0xab9423a7, 14, S43},
    104. { 0xfc93a039, 5, S44},
    105. { 0x655b59c3, 12, S41},
    106. { 0x8f0ccc92, 3, S42},
    107. { 0xffeff47d, 10, S43},
    108. { 0x85845dd1, 1, S44},
    109. { 0x6fa87e4f, 8, S41},
    110. { 0xfe2ce6e0, 15, S42},
    111. { 0xa3014314, 6, S43},
    112. { 0x4e0811a1, 13, S44},
    113. { 0xf7537e82, 4, S41},
    114. { 0xbd3af235, 11, S42},
    115. { 0x2ad7d2bb, 2, S43},
    116. { 0xeb86d391, 9, S44},
    117. };
    118.  
    119. typedef struct MD5state
    120. {
    121. uint len;
    122. uint state[4];
    123. } MD5state;
    124. MD5state *nil;
    125.  
    126. void encode(byte*, uint*, uint);
    127. void decode(uint*, byte*, uint);
    128. MD5state* md5(byte*, uint, byte*, MD5state*);
    129. void sum(FILE*, char*);
    130. void printEgg();
    131. void printHelp();
    132.  
    133. int main(int argc, char **argv)
    134. {
    135. int c;
    136. FILE *fd;
    137.  
    138. if(argc < 2) {
    139. printHelp();
    140. system("pause");
    141. return 1;
    142. }
    143.  
    144. argv++; argc--; // Удалить первый аргумент
    145.  
    146. /* Вывод пасхалки */
    147. if( strcmp(argv[0], "-egg") == 0 ) {
    148. printEgg();
    149. return 0;
    150. }
    151.  
    152. /* Вывод помощи */
    153. if( strcmp(argv[0], "-h" ) == 0 ) {
    154. printHelp();
    155. return 0;
    156. }
    157.  
    158. if(argc == 0)
    159. sum(stdin,0);
    160. else for(c = 0; c < argc; c++) {
    161. fd = fopen(argv[c], "r"); // Считываем файл
    162. if( fd == NULL ) {
    163. fprintf(stderr, "can't open file or syntax error \n");
    164. continue; // Выводим ошибку и пропускаем, если не удалось прочитать
    165. }
    166. sum(fd, argv[c]); // Выводим md5 для текущего файла
    167. fclose(fd); // Закрываем файл
    168. }
    169.  
    170. system("pause");
    171. }
    172.  
    173. /*
    174.  * Вывод получившейся контрольной суммы файла
    175.  */
    176. void sum(FILE *fd, char *name)
    177. {
    178. byte *buf;
    179. byte digest[16];
    180. char pr64[25];
    181. int i, n;
    182. MD5state *s;
    183.  
    184. s = nil;
    185. n = 0;
    186. buf = calloc(256,64); // Выделение памяти под буффер
    187. for(;;) {
    188. i = fread(buf+n, 1, 128*64-n, fd);
    189. if(i <= 0)
    190. break;
    191. n += i;
    192. if(n & 0x3f)
    193. continue;
    194. s = md5(buf, n, 0, s);
    195. n = 0;
    196. }
    197. md5(buf, n, digest, s);
    198.  
    199. for(i=0;i<16;i++)
    200. printf("%.2X", digest[i]); // Выводим md5 в 16-ричном формате
    201.  
    202. if(name)
    203. printf("\t%s", name);
    204. printf("\n");
    205. free(buf); // Освобождаем память от буффера
    206. }
    207.  
    208. /*
    209.  * Подсчет контрольной суммы
    210.  */
    211. MD5state* md5(byte *p, uint len, byte *digest, MD5state *s)
    212. {
    213. uint a, b, c, d, tmp;
    214. uint i, done;
    215. Table *t;
    216. byte *end;
    217. uint x[16];
    218.  
    219. if(s == nil){
    220. s = calloc(sizeof(*s),1);
    221. if(s == nil)
    222. return nil;
    223.  
    224. /* Начальные состояния переменных */
    225. s->state[0] = 0x67452301;
    226. s->state[1] = 0xefcdab89;
    227. s->state[2] = 0x98badcfe;
    228. s->state[3] = 0x10325476;
    229. }
    230. s->len += len;
    231.  
    232. i = len & 0x3f;
    233. if(i || len == 0){
    234. done = 1;
    235.  
    236. /* pad the input, assume there's room */
    237. if(i < 56)
    238. i = 56 - i;
    239. else
    240. i = 120 - i;
    241. if(i > 0) {
    242. memset(p + len, 0, i);
    243. p[len] = 0x80;
    244. }
    245. len += i;
    246.  
    247. /* Увеличиваем счетчик */
    248. x[0] = s->len<<3;
    249. x[1] = s->len>>29;
    250. encode(p+len, x, 8);
    251. } else
    252. done = 0;
    253.  
    254. for(end = p+len; p < end; p += 64){
    255. a = s->state[0];
    256. b = s->state[1];
    257. c = s->state[2];
    258. d = s->state[3];
    259.  
    260. decode(x, p, 64);
    261.  
    262. for(i = 0; i < 64; i++){
    263. t = tab + i;
    264. switch(i>>4){
    265. case 0:
    266. a += (b & c) | (~b & d);
    267. break;
    268. case 1:
    269. a += (b & d) | (c & ~d);
    270. break;
    271. case 2:
    272. a += b ^ c ^ d;
    273. break;
    274. case 3:
    275. a += c ^ (b | ~d);
    276. break;
    277. }
    278. a += x[t->x] + t->sin;
    279. a = (a << t->rot) | (a >> (32 - t->rot));
    280. a += b;
    281.  
    282. /* Меняем значения местами */
    283. tmp = d;
    284. d = c;
    285. c = b;
    286. b = a;
    287. a = tmp;
    288. }
    289.  
    290. s->state[0] += a;
    291. s->state[1] += b;
    292. s->state[2] += c;
    293. s->state[3] += d;
    294. }
    295.  
    296. /* Возвратт результата */
    297. if(done){
    298. encode(digest, s->state, 16);
    299. free(s);
    300. return nil;
    301. }
    302. return s;
    303. }
    304.  
    305. /*
    306.  * Переводит тип uint в byte
    307.  */
    308. void encode(byte *output, uint *input, uint len)
    309. {
    310. uint x;
    311. byte *e;
    312.  
    313. for(e = output + len; output < e;) {
    314. x = *input++;
    315. *output++ = x;
    316. *output++ = x >> 8;
    317. *output++ = x >> 16;
    318. *output++ = x >> 24;
    319. }
    320. }
    321.  
    322. /*
    323.  * Переводит тип byte в uint
    324.  */
    325. void decode(uint *output, byte *input, uint len)
    326. {
    327. byte *e;
    328.  
    329. for(e = input+len; input < e; input += 4)
    330. *output++ = input[0] | (input[1] << 8) |
    331. (input[2] << 16) | (input[3] << 24);
    332. }
    333.  
    334. /*
    335.  * Вывод HAPPY NEW YEAR
    336.  */
    337. void printEgg()
    338. {
    339. printf("************************* \n");
    340. printf("*| | /\\ |-\\ |-\\ \\ /*\n");
    341. printf("*|--| /--\\ |-/ |-/ \\ / * \n");
    342. printf("*| |/ \\| | | * \n");
    343. printf("************************* \n");
    344. printf("*|\\ ||--\\ /\\ / * \n");
    345. printf("*| \\ ||-- \\ / \\ / * \n");
    346. printf("*| \\||-- \\/ \\/ * \n");
    347. printf("************************* \n");
    348. printf("*\\ /|-- /\\ |-\\ /\\ *\n");
    349. printf("* \\ / |-- /--\\ |-/ /||\\* \n");
    350. printf("* | |--/ \\| \\ /||\\* \n");
    351. printf("************************* \n");
    352. }
    353.  
    354. /*
    355.  * Вывод помощи
    356.  */
    357.  
    358. void printHelp()
    359. {
    360. printf("md5hash sum of file or files.\n");
    361. printf("Options:\n");
    362. printf("[FILE NAME] [...] : md5 checksum\n");
    363. printf("-egg : easter egg\n");
    364. }