XingYun blog
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具

XingYun

冲!
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具
  • 算法图解阅读笔记
  • MD5算法
    • JS实现常见排序
    • 邓俊辉算法与数据结构
    • JS实现队列
    • JS实现树的几种遍历方式
    • 二叉树相关
    • 哈希算法
    • 进制转换与js实现
    • JS实现链表
    • JS实现栈与栈应用
    • 算法与数据结构
    XingYun
    2022-03-08
    目录

    MD5算法

    # MD5 是什么

    MD5 全称为   消息摘要算法版本 5 (Message Digest Algorithm 5)

    它是一种 Hash 算法。作用是为了信息安全。再具体点,MD5 值就是一串 128 位二进制数。也就是 32 位(当然还有 16 位, 一般默认为 32 位)的十六进制数。

    MD5 的核心是 通过算法把任意长度的原始数据映射成 128 bit 的数据 。这一点跟 CRC 类似,都是把一串数据经过处理,得到另一个固定长度的数据。

    MD5 的特点:

    1. 长度固定:任意长度的数据,算出的 MD5 值长度都是固定的 128 位
    2. 容易计算:从源数据计算出 MD5 值很容易
    3. 抗修改性:对原数据进行任何改动(哪怕一个字节),所得到的 MD5 值都有很大的区别
    4. 强抗碰撞:向找到两个不同的数据,使它们具有相同的 MD5 值,是非常困难的
    5. 不可逆(除非暴力破解)

    MD5 到底算不算加密算法?仁者见仁智者见智吧。说它是加密,因为它确实把原始数据,比如用户密码,变成了一般人看不懂的 MD5 值;说它不是加密,因为它不能解密。可以把它理解为 单向加密算法。

    # 工作原理

    1. 把消息分为 n 个分组
    2. 对最后一个消息分组进行填充
    3. 和输入量进行运算,运算结果位下一个分组的输入量
    4. 输出最终结果

    js 实现

    function md5(string) {
      function md5_RotateLeft(lValue, iShiftBits) {
        return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits))
      }
      function md5_AddUnsigned(lX, lY) {
        var lX4, lY4, lX8, lY8, lResult
        lX8 = lX & 0x80000000
        lY8 = lY & 0x80000000
        lX4 = lX & 0x40000000
        lY4 = lY & 0x40000000
        lResult = (lX & 0x3fffffff) + (lY & 0x3fffffff)
        if (lX4 & lY4) {
          return lResult ^ 0x80000000 ^ lX8 ^ lY8
        }
        if (lX4 | lY4) {
          if (lResult & 0x40000000) {
            return lResult ^ 0xc0000000 ^ lX8 ^ lY8
          } else {
            return lResult ^ 0x40000000 ^ lX8 ^ lY8
          }
        } else {
          return lResult ^ lX8 ^ lY8
        }
      }
      function md5_F(x, y, z) {
        return (x & y) | (~x & z)
      }
      function md5_G(x, y, z) {
        return (x & z) | (y & ~z)
      }
      function md5_H(x, y, z) {
        return x ^ y ^ z
      }
      function md5_I(x, y, z) {
        return y ^ (x | ~z)
      }
      function md5_FF(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(
          a,
          md5_AddUnsigned(md5_AddUnsigned(md5_F(b, c, d), x), ac)
        )
        return md5_AddUnsigned(md5_RotateLeft(a, s), b)
      }
      function md5_GG(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(
          a,
          md5_AddUnsigned(md5_AddUnsigned(md5_G(b, c, d), x), ac)
        )
        return md5_AddUnsigned(md5_RotateLeft(a, s), b)
      }
      function md5_HH(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(
          a,
          md5_AddUnsigned(md5_AddUnsigned(md5_H(b, c, d), x), ac)
        )
        return md5_AddUnsigned(md5_RotateLeft(a, s), b)
      }
      function md5_II(a, b, c, d, x, s, ac) {
        a = md5_AddUnsigned(
          a,
          md5_AddUnsigned(md5_AddUnsigned(md5_I(b, c, d), x), ac)
        )
        return md5_AddUnsigned(md5_RotateLeft(a, s), b)
      }
      function md5_ConvertToWordArray(string) {
        var lWordCount
        var lMessageLength = string.length
        var lNumberOfWords_temp1 = lMessageLength + 8
        var lNumberOfWords_temp2 =
          (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64
        var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16
        var lWordArray = Array(lNumberOfWords - 1)
        var lBytePosition = 0
        var lByteCount = 0
        while (lByteCount < lMessageLength) {
          lWordCount = (lByteCount - (lByteCount % 4)) / 4
          lBytePosition = (lByteCount % 4) * 8
          lWordArray[lWordCount] =
            lWordArray[lWordCount] |
            (string.charCodeAt(lByteCount) << lBytePosition)
          lByteCount++
        }
        lWordCount = (lByteCount - (lByteCount % 4)) / 4
        lBytePosition = (lByteCount % 4) * 8
        lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition)
        lWordArray[lNumberOfWords - 2] = lMessageLength << 3
        lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29
        return lWordArray
      }
      function md5_WordToHex(lValue) {
        var WordToHexValue = '',
          WordToHexValue_temp = '',
          lByte,
          lCount
        for (lCount = 0; lCount <= 3; lCount++) {
          lByte = (lValue >>> (lCount * 8)) & 255
          WordToHexValue_temp = '0' + lByte.toString(16)
          WordToHexValue =
            WordToHexValue +
            WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2)
        }
        return WordToHexValue
      }
      function md5_Utf8Encode(string) {
        string = string.replace(/\r\n/g, '\n')
        var utftext = ''
        for (var n = 0; n < string.length; n++) {
          var c = string.charCodeAt(n)
          if (c < 128) {
            utftext += String.fromCharCode(c)
          } else if (c > 127 && c < 2048) {
            utftext += String.fromCharCode((c >> 6) | 192)
            utftext += String.fromCharCode((c & 63) | 128)
          } else {
            utftext += String.fromCharCode((c >> 12) | 224)
            utftext += String.fromCharCode(((c >> 6) & 63) | 128)
            utftext += String.fromCharCode((c & 63) | 128)
          }
        }
        return utftext
      }
      var x = Array()
      var k, AA, BB, CC, DD, a, b, c, d
      var S11 = 7,
        S12 = 12,
        S13 = 17,
        S14 = 22
      var S21 = 5,
        S22 = 9,
        S23 = 14,
        S24 = 20
      var S31 = 4,
        S32 = 11,
        S33 = 16,
        S34 = 23
      var S41 = 6,
        S42 = 10,
        S43 = 15,
        S44 = 21
      string = md5_Utf8Encode(string)
      x = md5_ConvertToWordArray(string)
      a = 0x67452301
      b = 0xefcdab89
      c = 0x98badcfe
      d = 0x10325476
      for (k = 0; k < x.length; k += 16) {
        AA = a
        BB = b
        CC = c
        DD = d
        a = md5_FF(a, b, c, d, x[k + 0], S11, 0xd76aa478)
        d = md5_FF(d, a, b, c, x[k + 1], S12, 0xe8c7b756)
        c = md5_FF(c, d, a, b, x[k + 2], S13, 0x242070db)
        b = md5_FF(b, c, d, a, x[k + 3], S14, 0xc1bdceee)
        a = md5_FF(a, b, c, d, x[k + 4], S11, 0xf57c0faf)
        d = md5_FF(d, a, b, c, x[k + 5], S12, 0x4787c62a)
        c = md5_FF(c, d, a, b, x[k + 6], S13, 0xa8304613)
        b = md5_FF(b, c, d, a, x[k + 7], S14, 0xfd469501)
        a = md5_FF(a, b, c, d, x[k + 8], S11, 0x698098d8)
        d = md5_FF(d, a, b, c, x[k + 9], S12, 0x8b44f7af)
        c = md5_FF(c, d, a, b, x[k + 10], S13, 0xffff5bb1)
        b = md5_FF(b, c, d, a, x[k + 11], S14, 0x895cd7be)
        a = md5_FF(a, b, c, d, x[k + 12], S11, 0x6b901122)
        d = md5_FF(d, a, b, c, x[k + 13], S12, 0xfd987193)
        c = md5_FF(c, d, a, b, x[k + 14], S13, 0xa679438e)
        b = md5_FF(b, c, d, a, x[k + 15], S14, 0x49b40821)
        a = md5_GG(a, b, c, d, x[k + 1], S21, 0xf61e2562)
        d = md5_GG(d, a, b, c, x[k + 6], S22, 0xc040b340)
        c = md5_GG(c, d, a, b, x[k + 11], S23, 0x265e5a51)
        b = md5_GG(b, c, d, a, x[k + 0], S24, 0xe9b6c7aa)
        a = md5_GG(a, b, c, d, x[k + 5], S21, 0xd62f105d)
        d = md5_GG(d, a, b, c, x[k + 10], S22, 0x2441453)
        c = md5_GG(c, d, a, b, x[k + 15], S23, 0xd8a1e681)
        b = md5_GG(b, c, d, a, x[k + 4], S24, 0xe7d3fbc8)
        a = md5_GG(a, b, c, d, x[k + 9], S21, 0x21e1cde6)
        d = md5_GG(d, a, b, c, x[k + 14], S22, 0xc33707d6)
        c = md5_GG(c, d, a, b, x[k + 3], S23, 0xf4d50d87)
        b = md5_GG(b, c, d, a, x[k + 8], S24, 0x455a14ed)
        a = md5_GG(a, b, c, d, x[k + 13], S21, 0xa9e3e905)
        d = md5_GG(d, a, b, c, x[k + 2], S22, 0xfcefa3f8)
        c = md5_GG(c, d, a, b, x[k + 7], S23, 0x676f02d9)
        b = md5_GG(b, c, d, a, x[k + 12], S24, 0x8d2a4c8a)
        a = md5_HH(a, b, c, d, x[k + 5], S31, 0xfffa3942)
        d = md5_HH(d, a, b, c, x[k + 8], S32, 0x8771f681)
        c = md5_HH(c, d, a, b, x[k + 11], S33, 0x6d9d6122)
        b = md5_HH(b, c, d, a, x[k + 14], S34, 0xfde5380c)
        a = md5_HH(a, b, c, d, x[k + 1], S31, 0xa4beea44)
        d = md5_HH(d, a, b, c, x[k + 4], S32, 0x4bdecfa9)
        c = md5_HH(c, d, a, b, x[k + 7], S33, 0xf6bb4b60)
        b = md5_HH(b, c, d, a, x[k + 10], S34, 0xbebfbc70)
        a = md5_HH(a, b, c, d, x[k + 13], S31, 0x289b7ec6)
        d = md5_HH(d, a, b, c, x[k + 0], S32, 0xeaa127fa)
        c = md5_HH(c, d, a, b, x[k + 3], S33, 0xd4ef3085)
        b = md5_HH(b, c, d, a, x[k + 6], S34, 0x4881d05)
        a = md5_HH(a, b, c, d, x[k + 9], S31, 0xd9d4d039)
        d = md5_HH(d, a, b, c, x[k + 12], S32, 0xe6db99e5)
        c = md5_HH(c, d, a, b, x[k + 15], S33, 0x1fa27cf8)
        b = md5_HH(b, c, d, a, x[k + 2], S34, 0xc4ac5665)
        a = md5_II(a, b, c, d, x[k + 0], S41, 0xf4292244)
        d = md5_II(d, a, b, c, x[k + 7], S42, 0x432aff97)
        c = md5_II(c, d, a, b, x[k + 14], S43, 0xab9423a7)
        b = md5_II(b, c, d, a, x[k + 5], S44, 0xfc93a039)
        a = md5_II(a, b, c, d, x[k + 12], S41, 0x655b59c3)
        d = md5_II(d, a, b, c, x[k + 3], S42, 0x8f0ccc92)
        c = md5_II(c, d, a, b, x[k + 10], S43, 0xffeff47d)
        b = md5_II(b, c, d, a, x[k + 1], S44, 0x85845dd1)
        a = md5_II(a, b, c, d, x[k + 8], S41, 0x6fa87e4f)
        d = md5_II(d, a, b, c, x[k + 15], S42, 0xfe2ce6e0)
        c = md5_II(c, d, a, b, x[k + 6], S43, 0xa3014314)
        b = md5_II(b, c, d, a, x[k + 13], S44, 0x4e0811a1)
        a = md5_II(a, b, c, d, x[k + 4], S41, 0xf7537e82)
        d = md5_II(d, a, b, c, x[k + 11], S42, 0xbd3af235)
        c = md5_II(c, d, a, b, x[k + 2], S43, 0x2ad7d2bb)
        b = md5_II(b, c, d, a, x[k + 9], S44, 0xeb86d391)
        a = md5_AddUnsigned(a, AA)
        b = md5_AddUnsigned(b, BB)
        c = md5_AddUnsigned(c, CC)
        d = md5_AddUnsigned(d, DD)
      }
      return (
        md5_WordToHex(a) +
        md5_WordToHex(b) +
        md5_WordToHex(c) +
        md5_WordToHex(d)
      ).toLowerCase()
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226

    参考 百度百科

    # 应用

    # 1. 密码认证

    一般我们在一些“正规”网站上的注册账号密码时,一般不会在数据库直接保存用户的密码, 而是保存的密码的 MD5 值

    用户登陆时,将用户输入的密码在客户端转换为 MD5,传输到后端,后端拿着 MD5 值与数据库存储的 MD5 值匹配, 如果一致就认为密码正确,允许登陆。

    上图可以看出,腾讯微信公众号后台就是采用的这种模式。

    虽然 md5 加密能提供一定的安全性,但是如果你的密码足够简单,那么一样可能被攻击,比如你的密码设为了 88888888, 那么它转换后的 md5 为 8ddcff3a80f4189ca1c9d4d902c3c909, 如果是 66666666 转换后等于 7c497868c9e6d3e4cf2e87396372cd3b

    如果黑客手上维护了一张 MD5 常见密码表

    MD5 密码
    8ddcff3a80f4189ca1c9d4d902c3c909 88888888
    7c497868c9e6d3e4cf2e87396372cd3b 66666666
    25d55ad283aa400af464c76d713c07ad 12345678
    dd4b21e9ef71e1291183a46b913ae6f2 00000000
    。。。。 。。。。

    那么黑客拿着这些 MD5 值循环试探密码,你的账户就会被破解。 所以很多网站强制要求密码为数字+字母+符号的组合,且必须大于多少位, 就是为了防止这种攻击。

    提供一个可以在线查询 MD5 的网站: MD5 查询 (opens new window)

    # 2. MD5 有一个很大的用途就是确保文件完整性。

    开发前端项目有时需要把前端打包成 zip 文件用邮件发给别人, 为了保证完整性我会在文件名尾拼上这个 zip 包的 md5, 接收文件的人收到后也对 zip 包进行 md5 计算,两个 md5 做对比,如果一致证明文件完整,不一致则表示传输过程有丢包,文件不可用

    生成的 zip 文件

    #算法
    上次更新: 2023/04/05, 09:41:10
    算法图解阅读笔记
    JS实现常见排序

    ← 算法图解阅读笔记 JS实现常见排序→

    最近更新
    01
    JavaScript-test
    07-20
    02
    二维码的原理
    07-20
    03
    利用ChatGPT优化代码
    07-20
    更多文章>
    Theme by Vdoing | Copyright © 2021-2023 XingYun | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式