速速收藏!纯C实现的MD5哈希校验算法~!

速速收藏!纯C实现的MD5哈希校验算法~!


只有一个函数:
void MD5(const void* buf, unsigned int len, unsigned char output[16]);

在线验证网站:https://www.sojson.com/md5/


头文件

/**
 * \file md5.h
 *
 * \brief MD5 message digest algorithm (hash function)
 */

#ifndef MD5_H__
#define MD5_H__

#ifdef __cplusplus
extern "C" {
#endif

void MD5(const void* buf, unsigned int len, unsigned char output[16]);

#ifdef __cplusplus
}
#endif

#endif

源文件

/**
 * \file md5.c
 *
 * \brief MD5 message digest algorithm (hash function)
 */

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

#include "md5.h"

typedef struct
{
    uint32_t total[2];          /*!< number of bytes processed  */
    uint32_t state[4];          /*!< intermediate digest state  */
    unsigned char buffer[64];   /*!< data block being processed */
}md5_context;

/*
 * 32-bit integer manipulation macros (little endian)
 */

#define GET_UINT32_LE(n,b,i)                            \
{                                                       \
    (n) = ( (uint32_t) (b)[(i)    ]       )             \
        | ( (uint32_t) (b)[(i) + 1] <<  8 )             \
        | ( (uint32_t) (b)[(i) + 2] << 16 )             \
        | ( (uint32_t) (b)[(i) + 3] << 24 );            \
}

#define PUT_UINT32_LE(n,b,i)                                    \
{                                                               \
    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
    (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF );    \
    (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF );    \
}

void md5_internal_process(md5_context *ctx, const unsigned char data[64])
{
    uint32_t X[16], A, B, C, D;

    GET_UINT32_LE( X[ 0], data,  0 );
    GET_UINT32_LE( X[ 1], data,  4 );
    GET_UINT32_LE( X[ 2], data,  8 );
    GET_UINT32_LE( X[ 3], data, 12 );
    GET_UINT32_LE( X[ 4], data, 16 );
    GET_UINT32_LE( X[ 5], data, 20 );
    GET_UINT32_LE( X[ 6], data, 24 );
    GET_UINT32_LE( X[ 7], data, 28 );
    GET_UINT32_LE( X[ 8], data, 32 );
    GET_UINT32_LE( X[ 9], data, 36 );
    GET_UINT32_LE( X[10], data, 40 );
    GET_UINT32_LE( X[11], data, 44 );
    GET_UINT32_LE( X[12], data, 48 );
    GET_UINT32_LE( X[13], data, 52 );
    GET_UINT32_LE( X[14], data, 56 );
    GET_UINT32_LE( X[15], data, 60 );

#define S(x,n)                                                          \
    ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) )

#define P(a,b,c,d,k,s,t)                                        \
    do                                                          \
    {                                                           \
        (a) += F((b),(c),(d)) + X[(k)] + (t);                   \
        (a) = S((a),(s)) + (b);                                 \
    } while( 0 )

    A = ctx->state[0];
    B = ctx->state[1];
    C = ctx->state[2];
    D = ctx->state[3];

#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))

    P( A, B, C, D,  0,  7, 0xD76AA478 );
    P( D, A, B, C,  1, 12, 0xE8C7B756 );
    P( C, D, A, B,  2, 17, 0x242070DB );
    P( B, C, D, A,  3, 22, 0xC1BDCEEE );
    P( A, B, C, D,  4,  7, 0xF57C0FAF );
    P( D, A, B, C,  5, 12, 0x4787C62A );
    P( C, D, A, B,  6, 17, 0xA8304613 );
    P( B, C, D, A,  7, 22, 0xFD469501 );
    P( A, B, C, D,  8,  7, 0x698098D8 );
    P( D, A, B, C,  9, 12, 0x8B44F7AF );
    P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
    P( B, C, D, A, 11, 22, 0x895CD7BE );
    P( A, B, C, D, 12,  7, 0x6B901122 );
    P( D, A, B, C, 13, 12, 0xFD987193 );
    P( C, D, A, B, 14, 17, 0xA679438E );
    P( B, C, D, A, 15, 22, 0x49B40821 );

#undef F

#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y))))

    P( A, B, C, D,  1,  5, 0xF61E2562 );
    P( D, A, B, C,  6,  9, 0xC040B340 );
    P( C, D, A, B, 11, 14, 0x265E5A51 );
    P( B, C, D, A,  0, 20, 0xE9B6C7AA );
    P( A, B, C, D,  5,  5, 0xD62F105D );
    P( D, A, B, C, 10,  9, 0x02441453 );
    P( C, D, A, B, 15, 14, 0xD8A1E681 );
    P( B, C, D, A,  4, 20, 0xE7D3FBC8 );
    P( A, B, C, D,  9,  5, 0x21E1CDE6 );
    P( D, A, B, C, 14,  9, 0xC33707D6 );
    P( C, D, A, B,  3, 14, 0xF4D50D87 );
    P( B, C, D, A,  8, 20, 0x455A14ED );
    P( A, B, C, D, 13,  5, 0xA9E3E905 );
    P( D, A, B, C,  2,  9, 0xFCEFA3F8 );
    P( C, D, A, B,  7, 14, 0x676F02D9 );
    P( B, C, D, A, 12, 20, 0x8D2A4C8A );

#undef F

#define F(x,y,z) ((x) ^ (y) ^ (z))

    P( A, B, C, D,  5,  4, 0xFFFA3942 );
    P( D, A, B, C,  8, 11, 0x8771F681 );
    P( C, D, A, B, 11, 16, 0x6D9D6122 );
    P( B, C, D, A, 14, 23, 0xFDE5380C );
    P( A, B, C, D,  1,  4, 0xA4BEEA44 );
    P( D, A, B, C,  4, 11, 0x4BDECFA9 );
    P( C, D, A, B,  7, 16, 0xF6BB4B60 );
    P( B, C, D, A, 10, 23, 0xBEBFBC70 );
    P( A, B, C, D, 13,  4, 0x289B7EC6 );
    P( D, A, B, C,  0, 11, 0xEAA127FA );
    P( C, D, A, B,  3, 16, 0xD4EF3085 );
    P( B, C, D, A,  6, 23, 0x04881D05 );
    P( A, B, C, D,  9,  4, 0xD9D4D039 );
    P( D, A, B, C, 12, 11, 0xE6DB99E5 );
    P( C, D, A, B, 15, 16, 0x1FA27CF8 );
    P( B, C, D, A,  2, 23, 0xC4AC5665 );

#undef F

#define F(x,y,z) ((y) ^ ((x) | ~(z)))

    P( A, B, C, D,  0,  6, 0xF4292244 );
    P( D, A, B, C,  7, 10, 0x432AFF97 );
    P( C, D, A, B, 14, 15, 0xAB9423A7 );
    P( B, C, D, A,  5, 21, 0xFC93A039 );
    P( A, B, C, D, 12,  6, 0x655B59C3 );
    P( D, A, B, C,  3, 10, 0x8F0CCC92 );
    P( C, D, A, B, 10, 15, 0xFFEFF47D );
    P( B, C, D, A,  1, 21, 0x85845DD1 );
    P( A, B, C, D,  8,  6, 0x6FA87E4F );
    P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
    P( C, D, A, B,  6, 15, 0xA3014314 );
    P( B, C, D, A, 13, 21, 0x4E0811A1 );
    P( A, B, C, D,  4,  6, 0xF7537E82 );
    P( D, A, B, C, 11, 10, 0xBD3AF235 );
    P( C, D, A, B,  2, 15, 0x2AD7D2BB );
    P( B, C, D, A,  9, 21, 0xEB86D391 );

#undef F

    ctx->state[0] += A;
    ctx->state[1] += B;
    ctx->state[2] += C;
    ctx->state[3] += D;
}

/*
 * MD5 process buffer
 */
static void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen)
{
    size_t fill;
    uint32_t left;

    if( ilen == 0 )
        return;

    left = ctx->total[0] & 0x3F;
    fill = 64 - left;

    ctx->total[0] += (uint32_t) ilen;
    ctx->total[0] &= 0xFFFFFFFF;

    if( ctx->total[0] < (uint32_t) ilen )
        ctx->total[1]++;

    if( left && ilen >= fill )
    {
        memcpy( (void *) (ctx->buffer + left), input, fill );
        md5_internal_process( ctx, ctx->buffer );
        input += fill;
        ilen  -= fill;
        left = 0;
    }

    while( ilen >= 64 )
    {
    	md5_internal_process( ctx, input );
        input += 64;
        ilen  -= 64;
    }

    if( ilen > 0 )
    {
        memcpy( (void *) (ctx->buffer + left), input, ilen );
    }
}

/*
 * MD5 final digest
 */
static void md5_finish( md5_context *ctx, unsigned char output[16])
{
    uint32_t used;
    uint32_t high, low;

    /*
     * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
     */
    used = ctx->total[0] & 0x3F;

    ctx->buffer[used++] = 0x80;

    if( used <= 56 )
    {
        /* Enough room for padding + length in current block */
        memset( ctx->buffer + used, 0, 56 - used );
    }
    else
    {
        /* We'll need an extra block */
        memset( ctx->buffer + used, 0, 64 - used );

        md5_internal_process( ctx, ctx->buffer );

        memset( ctx->buffer, 0, 56 );
    }

    /*
     * Add message length
     */
    high = ( ctx->total[0] >> 29 )
         | ( ctx->total[1] <<  3 );
    low  = ( ctx->total[0] <<  3 );

    PUT_UINT32_LE( low,  ctx->buffer, 56 );
    PUT_UINT32_LE( high, ctx->buffer, 60 );

    md5_internal_process( ctx, ctx->buffer );

    /*
     * Output final state
     */
    PUT_UINT32_LE( ctx->state[0], output,  0 );
    PUT_UINT32_LE( ctx->state[1], output,  4 );
    PUT_UINT32_LE( ctx->state[2], output,  8 );
    PUT_UINT32_LE( ctx->state[3], output, 12 );
}

void MD5(const void* buf, unsigned int len, unsigned char output[16])
{
    md5_context ctx = {0};
    ctx.total[0] = 0;
    ctx.total[1] = 0;
    ctx.state[0] = 0x67452301;
    ctx.state[1] = 0xEFCDAB89;
    ctx.state[2] = 0x98BADCFE;
    ctx.state[3] = 0x10325476;
    md5_update(&ctx, (unsigned char *)buf, len);
    md5_finish(&ctx, output);
}


#if 0
#include <stdio.h>
#include <stdlib.h>
#include "md5.h"

/*

verify online: https://www.sojson.com/md5/

testdata:helloworld1234567890
md5(hex):cee76d16b6c243c1cd7c7ecc677de87d

 */

int main(void)
{
	const char* testdata = "helloworld1234567890";
	uint8_t md5[16];
	MD5(testdata, strlen(testdata), md5);
	printf("testdata:%s\n", testdata);
	printf("md5(hex):");
	for(int i = 0; i < 16; i++)
	{
		printf("%02x", md5[i]);
	}
	printf("\n");
	return 0;
}
#endif

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MD5是一种常见的哈算法,可以将任意长度的数据转换为固定长度的哈值。以下是一个使用C语言实现MD5哈算法的例子: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) { // 初始化变量 uint32_t h0, h1, h2, h3; h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; // 消息填充 uint8_t *msg = NULL; size_t new_len, offset; for (new_len = initial_len + 1; new_len % 64 != 56; new_len++); msg = (uint8_t*)calloc(new_len + 8, 1); memcpy(msg, initial_msg, initial_len); msg[initial_len] = 0x80; offset = new_len - 8; *((uint64_t*)(msg + offset)) = (uint64_t)initial_len * 8; // 处理消息块 uint32_t *w = (uint32_t *)msg; uint32_t a, b, c, d, i, f, g, temp; for (i = 0; i < new_len; i += 16) { a = h0; b = h1; c = h2; d = h3; // Round 1 for (uint8_t j = 0; j < 16; j++) { f = (b & c) | ((~b) & d); g = j; temp = d; d = c; c = b; b = b + LEFTROTATE((a + f + w[g] + 0x5A827999), 5); a = temp; } // Round 2 for (uint8_t j = 16; j < 32; j++) { f = (d & b) | ((~d) & c); g = (5 * j + 1) % 16; temp = d; d = c; c = b; b = b + LEFTROTATE((a + f + w[g] + 0x6ED9EBA1), 5); a = temp; } // Round 3 for (uint8_t j = 32; j < 48; j++) { f = b ^ c ^ d; g = (3 * j + 5) % 16; temp = d; d = c; c = b; b = b + LEFTROTATE((a + f + w[g] + 0x8F1BBCDC), 5); a = temp; } // Round 4 for (uint8_t j = 48; j < 64; j++) { f = c ^ (b | (~d)); g = (7 * j) % 16; temp = d; d = c; c = b; b = b + LEFTROTATE((a + f + w[g] + 0xCA62C1D6), 5); a = temp; } // 更新哈值 h0 += a; h1 += b; h2 += c; h3 += d; } // 释放内存 free(msg); // 生成哈值 *((uint32_t*)(digest)) = h0; *((uint32_t*)(digest + 4)) = h1; *((uint32_t*)(digest + 8)) = h2; *((uint32_t*)(digest + 12)) = h3; } int main() { uint8_t digest[16]; char *msg = "hello world"; md5((uint8_t*)msg, strlen(msg), digest); for (int i = 0; i < 16; i++) { printf("%02x", digest[i]); } return 0; } ``` 在这个例子中,我们使用了C语言和标准库函数来实现MD5哈算法。首先,我们定义了一个`md5`函数,该函数接受输入消息、输入长度和哈值缓冲区,并将哈值存储在缓冲区中。 在`md5`函数中,我们首先初始化了四个32位的变量`h0`、`h1`、`h2`和`h3`,这些变量将用于存储哈值。然后,我们对输入消息进行填充,以确保其长度为64的倍数。接下来,我们将填充后的消息分成16个32位的块,并使用四个循环来处理每个块。 在每个循环中,我们使用一系列运算来更新哈值。具体来说,我们使用了四个轮(Round 1、Round 2、Round 3和Round 4),每个轮使用不同的逻辑函数和常量。最后,我们将更新后的哈值存储在变量`h0`、`h1`、`h2`和`h3`中,并将其转换为字节序列,存储在哈值缓冲区中。 在`main`函数中,我们定义了一个输入消息字符串,并使用`md5`函数将其哈为一个16字节的哈值。最后,我们打印出哈值的十六进制表示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

觉皇嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值