🧰 UtlKit

HMAC 生成器怎么用: 从文本或十六进制密钥算出 SHA-256, SHA-384 和 SHA-512 签名, 在浏览器

一条消息和一个密钥, 按 UTF-8 文本或原始十六进制读取, 用 SHA-256, SHA-384 或 SHA-512 签成十六进制或 Base64 摘要, 全部在浏览器内经 WebCrypto 计算.

HMAC 生成器用一条消息和一个密钥算出带密钥的摘要. 整个计算是一次浏览器内的 WebCrypto 调用: 消息和密钥都留在页面上, 不发给任何服务器, 结果是确定性的字符串, 可以粘进请求头, 查询参数或测试向量. 从HMAC 生成器开始, 消息输入 The quick brown fox jumps over the lazy dog, 密钥输入 key, 保持 SHA-256 和 Hex 选中, 按生成: 摘要打印 f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8.

四个控件

四个输入决定摘要: 消息框, 带 Text/Hex 切换的密钥框, 算法选择和输出格式选择. 消息是多行文本域: 换行符是消息的一部分, 参与签名, 所以同样的词分两行签和用空格连成一行签出的值不同, 你好 的 UTF-8 字节在密钥 key 下签出 309b75c0cbbfb27bb35b8d7b8f4adb4b9399cd54339ab5faeb8798e1b9f7f00c. 密钥是单行框, 切换按钮决定这个字符串如何被读. 算法选择提供 SHA-256, SHA-384 和 SHA-512, 格式选择提供 Hex 和 Base64. 生成是一个显式按钮: 按之前不计算任何东西, 摘要出现在一个只读框里, 旁边是复制按钮.

文本密钥和十六进制密钥

Text 模式下密钥按所敲的 UTF-8 字节读取: 每个字符都是密钥的一部分, 包括尾随空格, 所以密钥 key 把 abc 签成 9c196e32dc0175f86f4b1cb89289d6619de6bee699e4c378e68309ed97a1a6ab, 而带一个尾随空格的 key 把同样的 abc 签成 0324ef70f9e605e123731b458dcdce99cf5f8d23572f604fbdabf371aedb0f68. Hex 模式下字符串先去掉所有空白, 再按原始字节对读取, 所以 616263 是三个字节 0x61, 0x62, 0x63, 不是文本 616263 的六个字符: 消息 msg 下, 十六进制密钥 616263 签出 eb14f17c9f056479f147adcf8020d27914f1e5971f049e75bf21a669cbd747e2, 而文本密钥 616263 签出 49962d2f0cde29c6a4848f8ea64575424ad42d3d108452127c0512cb88444a41. 十六进制字符串必须至少两个字符, 偶数长度, 且全是十六进制数字; 6162635 在任何加密运行之前就过不了检查, 奇数长度和 a 到 f 之外的字母也一样.

三个算法

摘要长度由算法固定: SHA-256 打印 32 字节, 即 64 个十六进制字符, 或 44 个 Base64 字符带一个 = 填充; SHA-384 打印 48 字节, 96 个十六进制字符, 或 64 个 Base64 字符无填充; SHA-512 打印 64 字节, 128 个十六进制字符, 或 88 个 Base64 字符带双填充. 三者是同一个带密钥构造套在三个哈希函数上, 所以切换选择改变的是长度和值, 不是输入的形状. 本工具能复现 RFC 4231 测试向量: 十六进制密钥 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b 配消息 Hi There, SHA-256 打印 b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7, SHA-512 打印 87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854; 文本密钥 Jefe 配消息 what do ya want for breakfast?, SHA-256 打印 47f69d8f80f0a6326746beec23a9040fd533642b5ba38a99287670639d8b862a.

Hex 和 Base64

Hex 按字节小写打印摘要, 每字节两个字符; Base64 打印同样的字节, 带标准填充. 两种写法携带的是同样的 32 字节: 密钥 key 下的 fox 消息, Hex 是 f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8, Base64 是 97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg=, 结尾的 = 是填充, 不是被签的字符. Jefe 消息在 SHA-256 下打印 R/adj4DwpjJnRr7sI6kED9UzZCtbo4qZKHZwY52Lhio=, 在 SHA-384 下打印 MxTAcsyrQOuSUFsKlh1Gv2UuDowpCJfZzsFDvCo65FGJ15G5QCeCSey3RFF3dIlG, 48 字节正好填满 Base64 分组, 没有填充; 在 SHA-512 下打印 af7nmi5sP0zyOeCqttVBl2h4BIXw5B/8dZckor99FGR+CncEsWts5Zi2pWU1HIhhnQ3+0nKMj8+Ja0GvkB1UCA==, 64 字节在最后一组剩一个字节, 用双 = 填充. 复制按钮把打印的字符串放进剪贴板, 并显示 已复制 两秒.

确定性和输入检查

同样的消息, 密钥和算法永远打印同样的摘要: 没有盐, 没有时间戳, 没有随机性, 这正是 HMAC 能被用作测试向量, 以及被两个系统用作共享校验的原因. 两个输入在任何加密运行之前被拒: 空消息或纯空白消息触发 请输入消息 错误, 空密钥或纯空白密钥触发 请输入密钥 错误; 过不了十六进制检查的密钥触发 无效十六进制 错误, 三种情况框里都保留内容以便修正. 密钥长度除此之外不受限: 单字节密钥把 abc 签成 df55998f9fc33d78ac99d1d8ebc2b6e16aa076c4189946942a82b55d5dee8dc7, 100 字节密钥把同样的 abc 签成 30f0f7f4a3d31b9750666b038c048550020795dd2743759bf83bcf5e0f125b36, 因为 HMAC 构造先把过长的密钥哈希到哈希尺寸. 还剩一个平台角: WebCrypto subtle API 只存在于安全上下文, 所以在纯 http 页面上, 按钮会显示失败错误而不是计算.

它不是什么

HMAC 生成器不是普通哈希工具: 要对消息本身不带任何密钥的摘要, 哈希生成器对文本跑 MD5, SHA-1 和 SHA-2 族. 它也不是 JWT 工具: 要读取, 拆分并 Base64 解码一个令牌而不是签一个, JWT 解码器做那件事. 它也不加密: 摘要是签名, 不是秘密容器, 加密方向见AES 指南. 它也不在四个输入之外保存任何状态: 没有历史, 没有存储的密钥, 没有上一个摘要的记忆, 关掉页面就丢掉消息和密钥.

相关工具

常见问题

HMAC 生成器会把消息或密钥发给服务器吗?

不会. 摘要由页面上的浏览器 WebCrypto API 从两个框和两个选择算出. 消息字节, 密钥字节和结果都留在页面里, 按生成不发任何网络请求, 唯一离开页面的东西是你自己复制的打印摘要.

为什么同样的词给出不同的摘要?

因为密钥模式对字符串的读法不同. 文本密钥 616263 是六个 UTF-8 字符, 把消息 msg 签成 49962d2f0cde29c6a4848f8ea64575424ad42d3d108452127c0512cb88444a41, 而十六进制密钥 616263 是三个原始字节, 把同样的消息签成 eb14f17c9f056479f147adcf8020d27914f1e5971f049e75bf21a669cbd747e2. 空白在文本模式下同样起作用: 带一个尾随空格的密钥把 abc 签成 0324ef70f9e605e123731b458dcdce99cf5f8d23572f604fbdabf371aedb0f68, 和没有空格的那个密钥不同.

为什么十六进制密钥 6162635 被拒绝?

十六进制检查在任何加密运行之前执行: 去掉空白后, 字符串必须至少两个字符, 偶数长度, 且每个字符都是十六进制数字. 6162635 有七个字符, 奇数长度, 所以触发无效十六进制错误; 带 a 到 f 之外字母的字符串, 或单个字符, 过不了同一个检查. 错误不清空这个框.

按两次生成会打印两个不同的摘要吗?

不会. HMAC 是确定性的: 同样的消息, 密钥, 算法和格式永远打印同样的字符串, 因为构造里没有盐, 没有时间戳, 没有随机数. 这正是两个共享密钥的系统能互相校验的原因, 也是打印的值能被粘成测试向量的原因.

SHA-256, SHA-384 和 SHA-512 该选哪个?

算法是与校验方之间的约定: 选对方或规范期望的那个, 因为用错误的哈希去验证的签名不会匹配. 三者区别在输出长度, 32, 48, 64 字节, 以及带密钥构造内部的哈希函数. 自由选时, SHA-256 是最常见的默认, SHA-512 给最长的摘要.

相关文章