MD5哈希算法(C语言实现)

MD5哈希算法(C语言实现)

主要是做个记录,害怕以后代码丢了,先放到这里了。
MD5 暂时就不进行介绍了,最基础的哈希算法,网上到处都是。
转载请注明出处:https://www.cnblogs.com/wangyanzhong123/p/13784318.html

说明

这个版本用了很多位运算,也没有添加注释,所以可能阅读起来会有一些困难。但是可以保证的是结果一定是正确的,并且速度也是经过优化的,应该会很快。

源代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>

#define LEFTSHIFT(x,c) (((x) << (c)) | ((x) >> (32-(c))))

const uint32_t k[64] = {
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 };
 
// per-round shift amounts
const uint32_t r[64] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
                      5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20, 5,  9, 14, 20,
                      4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
                      6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};

void to_bytes(uint32_t val, uint8_t *bytes){
    bytes[0] = (uint8_t) val;
    bytes[1] = (uint8_t) (val >> 8);
    bytes[2] = (uint8_t) (val >> 16);
    bytes[3] = (uint8_t) (val >> 24);
}

uint32_t to_int32(const uint8_t *bytes){
    return (uint32_t)bytes[0] 
    | ((uint32_t)bytes[1] << 8) 
    | ((uint32_t)bytes[2] << 16) 
    | ((uint32_t)bytes[3] << 24);
}

void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t* digest){
    size_t new_len, offset;
    uint32_t words[16];
    uint8_t *newmsg = NULL;
    uint32_t h0, h1, h2, h3, a, b, c, d, f, g, temp;
    h0 = 0x67452301;
    h1 = 0xefcdab89;
    h2 = 0x98badcfe;
    h3 = 0x10325476;
    // Pre-processing
    // calculate new length (not included last 8bytes)
    for (new_len = initial_len+1; new_len % (512/8) != 448/8; new_len++);
    newmsg = (uint8_t*)malloc(new_len+8); // 8 bytes for length recording
    memcpy(newmsg, initial_msg, initial_len);
    newmsg[initial_len]=0x80; // padding "1" first, then all "0"
    for (offset = initial_len+1; offset < new_len; offset++)
        newmsg[offset] = 0x00;
    // append the len in bits at the end of buffer ??? why << 3
    to_bytes(initial_len << 3, newmsg + new_len);
    to_bytes(initial_len >> 29, newmsg + new_len + 4);

    // process the message per 512-bits
    for (offset = 0; offset < new_len; offset += (512/8)){
        // break 512 bits into 16 words(32-bit)
        for (uint32_t i = 0; i < 16; i ++)
            words[i] = to_int32(newmsg + offset + i*4);
        a = h0; b = h1; c = h2; d = h3;
        for (uint32_t i = 0; i < 64; i ++){
            if (i < 16) {
                f = (b & c) | ((~b) & d);
                g =  i;
            } else if (i < 32) {
                f = (d & b) | ((~d) & c);
                g = (5*(i-16) + 1) % 16;
            } else if (i < 48) {
                f = b ^ c ^ d;
                g = (3*(i-32) + 5) % 16;
            } else {
                f = c ^ (b | (~d));
                g = (7*(i-48)) % 16;
            }
            temp = d;
            d = c;
            c = b;
            b = b + LEFTSHIFT((a+f+k[i]+words[g]), r[i]);
            a = temp;
        }
        h0 += a;
        h1 += b;
        h2 += c;
        h3 += d;
    }
    free(newmsg);
    to_bytes(h0, digest);
    to_bytes(h1, digest+4);
    to_bytes(h2, digest+8);
    to_bytes(h3, digest+12);
}


int main(int argc, char **argv){
    char *msg;
    clock_t start,finish;
    double duration;
    size_t msglen;
    uint8_t result[16];
    char *inputstring = "-s";
    char *inputfile = "-f";
    if (argc < 2){
        printf("usage: %s 'string'\n", argv[0]);
        return 1;
    } else if (!strcmp(argv[1],inputstring)){
        msg = argv[2];
        msglen = strlen(msg);
        start = clock();
        md5((uint8_t*)msg, msglen, result);
        for (int i = 0; i < 16; i++)
            printf("%2.2x", result[i]);
        printf("\n");
        finish = clock();
        duration = (double)(finish - start) / CLOCKS_PER_SEC;
        printf("time cost: %f\n", duration);
        system("pause");
        return 0;
    } else if (!strcmp(argv[1],inputfile)){
        FILE *infile;
        infile = fopen(argv[2],"rb");
        if (infile == NULL){
            printf("%s not exist\n",argv[2]);
            return -1;
        } else {
            fseek(infile, 0, SEEK_END);
            size_t filesize = ftell(infile);
            rewind(infile);
            uint8_t *buffer = (uint8_t*)malloc(sizeof(uint8_t)*filesize);
            fread(buffer, sizeof(uint8_t), filesize, infile);
            start = clock();
            md5(buffer, filesize, result);
            for (int i = 0; i < 16; i++)
                printf("%2.2x", result[i]);
            printf("\n");
            finish = clock();
            duration = (double)(finish - start) / CLOCKS_PER_SEC;
            printf("time cost: %f\n", duration);
            system("pause");
            return 0;
        }
    }
}
posted @ 2020-10-09 10:11  hikonaka  阅读(1859)  评论(0编辑  收藏  举报