MD5和哈希算法

参考 https://www.zhihu.com/question/26762707
https://www.zhihu.com/question/26762707/answer/40119521

hash(散列、杂凑)函数,是将任意长度的数据映射到有限长度的域上。

为什么MD5说是128位,却只有32个字符?这是因为这两个长度的概念不同;

通常MD5(不止MD5,其它例如sha1、sha256)等hash值通常都是以十六进制表示的,而其内部算法使用的是二进制;

以MD5值为例:e10adc3949ba59abbe56e057f20f883e
用十六进制表示时,使用了32个16进制数;而一个16进制数用二进制表示时,需要占用4位;所以是128个比特位

在密码学中,hash算法的作用主要是用于消息摘要和签名,换句话说,它主要用于对整个消息的完整性进行校验。举个例子,我们登陆知乎的时候都需要输入密码,那么知乎如果明文保存这个密码,那么黑客就很容易窃取大家的密码来登陆,特别不安全。那么知乎就想到了一个方法,使用hash算法生成一个密码的签名,知乎后台只保存这个签名值。

由于hash算法是不可逆的,那么黑客即便得到这个签名,也丝毫没有用处;而如果你在网站登陆界面上输入你的密码,那么知乎后台就会重新计算一下这个hash值,与网站中储存的原hash值进行比对,如果相同,证明你拥有这个账户的密码,那么就会允许你登陆。银行也是如此,银行是万万不敢保存用户密码的原文的,只会保存密码的hash值而而已。

在这些应用场景里,对于抗碰撞和抗篡改能力要求极高,对速度的要求在其次。一个设计良好的hash算法,其抗碰撞能力是很高的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 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
发出的红包

打赏作者

forgetable tree

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

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

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

打赏作者

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

抵扣说明:

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

余额充值