【问题标题】:MD5 Hash and Base64 encodingMD5 哈希和 Base64 编码
【发布时间】:2010-11-25 14:35:03
【问题描述】:

如果我有一个 32 个字符的字符串(一个 MD5 哈希)并且我使用 Base64 对其进行编码,那么编码字符串的最大长度是多少?

【问题讨论】:

  • 如果你有一个 32 个字符的 MD5 哈希字符串,那么它已经是十六进制编码的,不需要 base64 编码。
  • MD5 哈希不是十六进制的!它是 16 个字节 - 十六进制只是一种常规表示。
  • @GregS,你是正确的,MD5 哈希通常以十六进制形式表示,它是 Base64 的子集。但是转换为 Base64 是有目的的——Base64 需要更少的字符,因为它具有更大的字符集。如果您使用 Base64(22 个字符)而不是十六进制(32 个字符)表示法,当您以纯文本或字符编码方案保存时,它将为您节省磁盘空间。
  • @GregS 实际上,如果这是预期的格式,您确实需要对其进行编码,例如在 HTTP Content-MD5 标头中。
  • @Michael 实际上,在这种情况下,您必须先对其进行十六进制解码,然后再对其进行 base64 编码。 32 个字符的十六进制字符串的 base64 编码不正确。

标签: hash cryptography base64 md5 cryptographic-hash-function


【解决方案1】:

在 Base64 表示法中,MD5 值总是 22 个(有用的)字符。许多 Base64 算法在编码 MD5 散列时还会附加 2 个填充字符,使总数达到 24 个字符。填充没有添加有用的信息,可以丢弃。只有前 22 个字符很重要。

原因如下:

MD5 哈希是一个 128 位的值。 Base64 字符串中的每个字符包含 6 位信息,因为该字符有 64 个可能的值,需要 2 的 6 次方才能达到 64。每个字符包含 6 位信息,21 个字符有 126 位信息, 22 个字符包含 132 位信息。由于 128 位不能容纳 21 个字符,但可以容纳 22 个字符(有一点余地),因此 128 位值在 Base64 中将始终表示为 22 个字符。

关于填充的注释:

我在上面提到,许多 Base64 编码算法在对 MD5 值进行编码时会添加几个填充字符。这是因为 Base64 将 3 个字节的信息表示为 4 个字符。由于 MD5 有 16 个字节的信息,许多 Base64 编码算法会附加“==”来指定 16 个字节的输入比下一个 3 的倍数少 2 个字节,即 18 个字节。这两个等号不向字符串添加任何信息,并且可以在存储时丢弃。

【讨论】:

    【解决方案2】:

    MD5 128 位在 Base64 中表示为 22 个字符。在这种情况下还有 2 个填充字符 '='。

    怎么做?

    $ md5sum ./README.md 
    c6b5f48774aa0a87a82a276ff86be507  ./README.md
    $ md5sum ./README.md | base64
    YzZiNWY0ODc3NGFhMGE4N2E4MmEyNzZmZjg2YmU1MDcgIC4vUkVBRE1FLm1kCg==
    

    在这种情况下,Base64 编码的字符串不短于 MD5 哈希长度

    因为编码的是MD5哈希的存储形式。不是 MD5 哈希值本身。

    需要注意多少位用于存储一位MD5哈希。

    正确的方法:

    将哈希值转换为 1 十六进制转二进制

    2 将二进制转换为base64编码的字符串

    $ cat ./README.md |  openssl dgst -md5 
    c6b5f48774aa0a87a82a276ff86be507
    $ cat ./README.md |  openssl dgst -md5 -binary | openssl enc -base64
    xrX0h3SqCoeoKidv+GvlBw==
    

    $ md5sum ./LICENSE 
    e3fc50a88d0a364313df4b21ef20c29e  ./LICENSE
    $ cat ./LICENSE |  openssl dgst -md5 -binary | openssl enc -base64
    4/xQqI0KNkMT30sh7yDCng==
    $ (echo 0:; echo e3fc50a88d0a364313df4b21ef20c29e) | xxd -rp -l 16|base64
    4/xQqI0KNkMT30sh7yDCng==
    

    【讨论】:

      【解决方案3】:

      根据http://en.wikipedia.org/wiki/Base64

      "请注意,给定 n 字节的输入,输出将是 (n + 2 - ((n + 2) % 3)) / 3 * 4 字节长,收敛到 n * 4 / 3 或 1.33333n对于较大的 n。”

      所以,它将是 ((32 + 2 - (32 + 2) % 3)) / 3 * 4 = 34 - (34 % 3) / 3 * 4 = (34 - 1) / 3 * 4 = 33/3*4 = 44 个字符。

      您始终可以将其提取为原始二进制形式(128 位)并将其直接编码为 base 64,这意味着转换 16 字节而不是 32,在 base 64 编码时变为 24 字节。

      【讨论】:

      • 一个 md5 哈希是 128 位,可以编码为 24 个 base64 字符。
      • 感谢 Arantor!完美答案!
      • @GregS,抱歉,是的,我在考虑 160 位的 SHA1。
      • 在 base64 中编码十六进制编码的哈希输出确实没有意义 - 十六进制序列中的有效字符是 base64 序列中的子集。
      • @caf,但是解码十六进制然后在 Base64 中重新编码是有意义的......编码字符串的大小会更小
      猜你喜欢
      • 2020-02-14
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      相关资源
      最近更新 更多