开发者工具 · SHA 哈希计算器
SHA-256 逐步:填充、消息调度和 64 回合
· 工作原理
sha-256 密码学 浏览器 API JavaScript
SHA-256 填充您的输入,将其分成 512 位块,并通过 64 轮混合运行每个块。这篇文章用简单的语言解释了每个阶段,不需要密码学背景。
你的字节实际上发生了什么——大多数开发人员从未打开过的黑匣子
SHA-256 是一种确定性算法,可将任何输入转换为 256 位(32 字节)指纹。从外面看起来像一个黑匣子,实际上是一系列明确定义的步骤。了解这些步骤可以消除神秘感,让您验证正确性、跟踪错误并了解输出为何如此。算法的每一个部分都是公开的;力量来自于设计,而不是来自于保密。
该算法在 512 位块上运行。如果您的输入较短,则会被填充。如果它更长,它会被分成多个块,每个块按顺序处理,每个块的输出输入到下一个块。处理完所有块后,您将获得八个 32 位数字,它们连接在一起形成最终的 256 位摘要。
填充 — 附加 1 位、零和 64 位消息长度以达到 512 位的倍数
填充步骤是确定性和形式化的。在实际输入之后,附加一个 1 位(实际上,如果您的输入在字节边界上结束,则附加字节 0x80)。然后附加零位,直到 64 位少于 512 位的倍数。最后,附加输入长度的 64 位大端编码(以位为单位)。此填充确保每条消息都是 512 位的倍数,并对原始长度进行编码,因此不同长度的相同输入不能产生相同的摘要。
对于输入 abc(3 字节 = 24 位),填充消息为 512 位(一个块):三个字节 61 62 63,后跟 0x80,后跟零,后跟24 的 64 位编码(在 64 位大端字段中为 0x00...0x18)。该消息现在正好填充一个 512 位块。对于空字符串,填充会附加 0x80,后跟零,最后是 0x00...0x00(表示输入的 0 位)。对于较长的输入(例如 100 字节文件),填充会将最后一个块填充到 512 位,并指示原始长度的 800 位。
初始值和常量由算法固定;它们的历史推导是在存储库证据之外
该算法以八个 32 位工作变量开始,初始化为前八个素数平方根的小数部分的前 32 位。这些是硬编码常量,在任何参考实现和加密库的源代码中都可见。它们的存在是因为使用数学中的固定常数可以避免对隐藏后门的怀疑。 ToolAcre 工具使用浏览器的 Web Crypto 实现,该实现应用了这些相同的常量。
该算法还使用 64 舍入常量,这些常量源自前 64 素数的立方根的小数部分的前 32 位。这些也是固定的和公开的。这些常数充当附加的混合材料;改变它们会破坏算法并产生不同的摘要。
消息调度 — 通过移位和轮换将 16 字扩展为 64
消息调度通过特定公式将 16 字(512 位)扩展为 64 字(2048 位)。对于 0-15 轮,单词直接来自输入块。对于 16-63 轮,每个新单词是通过采用两个较早的单词(在特定偏移处)、应用旋转和移位、在另一个单词中进行异或并存储结果来计算的。该公式在一个区块的上下文中是确定性且可逆的,但扩展将输入的影响分散到所有 64 轮中。
扩展公式使用右旋转(一种循环位移位,其中从一端掉落的位重新出现在另一端)和右移操作。旋转保留所有位但改变它们的位置;右移会丢弃位。旋转、移位和异或运算的组合确保输入的每一位都会影响调度中的多个字。
一轮 — Ch、Maj 和 Sigma 函数被描述为位混合操作,以及八个工作变量如何更新
每一轮 64 处理消息调度的一个字并更新八个工作变量。核心函数涉及六个操作:基于控制变量选择位的条件混合(通常称为 Ch,表示“选择”)、选择三个变量中最常见值的多数函数 (Maj)、旋转和移位工作变量的两个特殊混合函数(Sigma_0 和 Sigma_1)以及对 2^32 取模的加法。所有算术都是在 32 位字上完成的,因此溢出会回绕。
“选择”函数采用三个 32 位输入,并且对于每个位位置,如果控制位为 1,则从第一个输入中选择位;如果控制位为 0,则从第二个输入中选择位。多数函数查看三个输入,并针对每个位位置输出这三个输入中最常出现的位值。这些是非线性操作,它们打破了线性并确保微小的输入变化在状态中不可预测地传播。
链接块并生成输出 - 将每个块的结果添加到运行状态中
每轮都会更新所有八个工作变量,方法是旋转它们并合并根据当前轮常量、消息调度字和先前状态计算出的新值。前七个工作变量发生变化:第 8 个变为第 1 个,第 1 个变为第 2 个,依此类推。新的第八个值是使用混合函数根据旧变量计算得出的。经过 64 轮后,您将获得八个新的 32 位值。这些被添加(模 2^32)到初始常量,产生该块的最终哈希状态。
对于多块消息,一个块中的八个值将成为下一个块的初始状态。该链确保输入中任何位置的更改都会影响所有后续块。当到达最后一个块时,输入的每一位都会影响最终的输出。
工作示例以及未涵盖的内容 - 跟踪短消息的填充和块计数;安全证明超出范围
对于输入 abc,消息在填充后适合一个 512 位块。填充添加了 424 位,总共 512 位。消息调度将其扩展为 64 个字。每一轮消耗一个字并通过混合函数更新八个工作变量。经过 64 轮后,状态与初始常量进行异或,生成最终摘要 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad。
这是一个已发布的测试向量:对相同输入进行相同的计算始终会产生相同的输出。 ToolAcre 工具通过浏览器的 Web Crypto 实现执行此精确计算。您可以通过对 abc 进行散列并将结果与已知向量进行比较来验证它。任何正确实现 Web Crypto 的浏览器都会产生相同的输出;该算法不允许任何捷径或替代路径。
要点:Web Crypto 执行确定性 SHA-256 混合而不暴露秘密
该算法是公开的,并且每一步都是确定性的。混合函数(Ch、Maj、Sigma_0、Sigma_1)被选择为非线性的,这意味着更改一个输入位不会按预期改变一个输出位。将 16 消息字扩展到 64 确保整个输入影响整个计算。 64 轮次和状态链接意味着输出对输入的每一位都很敏感,并且存储库使用结果输出作为确定性摘要。抗碰撞性是一种有限制的安全属性,而不是保证重复输出在数学上是不可能的。
密码证明超出了本文的范围。关键是您现在知道该算法实际上是做什么的。它不是魔法,也不是黑匣子。如果您想验证 ToolAcre 是否正确进行哈希处理,请通过这些步骤跟踪您自己的输入,或使用其他语言的参考实现并比较结果。浏览器的实现和任何正确的引用都会为相同的输入生成相同的摘要。