SHA-256 是一种定义明确的算法,用来计算数据的指纹,也就是哈希。相同的输入总会得到相同的结果,长度为 256 位,即 32 字节,通常写成 64 个十六进制字符。比特币用它关联和验证数据,也用它进行挖矿。不过,这个指纹并不是原始内容的加密副本。
假设有人给你一个文件,同时提供它的哈希。你可以自行计算,检查下载的数据是否与这个指纹相符。哪怕输入只发生很小的变化,也极有可能使整个结果发生变化。但指纹本身不能说明文件是谁制作的,也不能证明它安全。如果攻击者同时替换文件和它的哈希,两者仍然会匹配。因此,用于比较的参考值来自哪里、是否可信,同样重要。 [1] [5]
对三个 ASCII 字节 abc 进行计算,不加引号,也不加换行符,结果是 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad。这不是随机生成的数字:任何正确的实现,对完全相同的字节都会算出这个结果。如果加上空格或换行符,输入就变了。此时哈希不同,并不意味着算法出错。处理文字时,字符编码也会影响结果。 [3]
加密的设计目标是让持有密钥的人恢复消息。SHA-256 没有这种密钥,也没有反向还原的步骤。但这并不妨碍别人猜测可能的输入:如果对方怀疑你哈希的是四位数字 PIN,就可以尝试全部 10,000 种组合,并逐一比较结果。很长的哈希不会给薄弱的秘密补上缺失的熵 (这里指输入的不可预测程度)。安全性还取决于攻击者实际需要尝试多少种可能。 [5] [7]
区块标识符、txid (交易标识符),以及 Merkle Tree (由相互关联的哈希组成的树) 中成对哈希的合并,都使用 SHA256(SHA256(data))。第二遍处理的是第一遍结果的 32 个原始字节,而不是它那 64 个字符的文本表示。最终输出仍是 256 位。这里的双重哈希是一条协议规则,并不说明单次 SHA-256 已被攻破。比特币还使用其他构造:例如 Taproot 会在输入中加入预先定义的标签,以区分哈希的不同用途。 [2] [4] [6]
矿工反复修改候选区块头中允许修改的字段,计算它的双重 SHA-256,寻找一个按数值解释时不超过规定 target (数值上限) 的结果。他们不是在解密消息,也不是在寻找别人的私钥。找到合格的区块头需要大量尝试,验证它却很快。区块头还引用前一个区块,因此修改旧区块会破坏后续的链接。Full Node (独立验证比特币规则的节点) 还要检查交易和其他规则:仅有一个符合要求的哈希,并不能让无效区块变成有效区块。 [4]
可能的消息数量多于 256 位指纹的数量,因此必然有不同输入得到同一个哈希,这叫碰撞。关键在于能否有目的地找到它。对于理想的 256 位哈希,通用方法寻找任意碰撞需要约 2^128 次尝试;为一个事先指定的指纹寻找输入,则需要约 2^256 次。两者是不同的问题。找到碰撞本身不会泄露比特币私钥。这些数字也不是整个钱包或协议安全性的保证。 [5]
SHA-256 是一个组件,并不是所有安全问题的完整答案。它被设计得很快,因此不适合单独用来存储人类选择的密码:攻击者也能快速尝试各种猜测。这个场景需要专门的密码派生方法,例如能够调节计算成本的算法。同样,自制一套“把某个东西哈希一下,就有了安全密钥”的办法,既不能解决初始随机性不足,也不能补救输入泄露。用户通常不必手工计算 SHA-256,但应理解核对过的指纹能证明什么、不能证明什么。 [8] [7]
SHA-256 属于 SHA-2 家族,NIST FIPS 180-4 描述了它的计算方法。计算前,算法对输入进行填充,其中包含输入长度的信息,然后按 512 位一组处理,每组经过 64 轮计算。这些内部块有 64 字节,并不是比特币区块。比特币区块头有 80 字节,完整区块还包含交易。名称中的 256 指的是输出指纹的长度,而不是区块或私钥的大小。 [1] [4]
要获得更完整的理解,请将本词条与以下词条结合阅读: Hash, Proof of Work, Block Header, 比特币地址, Merkle Tree, Bitcoin. 反向关联还来自: Hash, ASIC Miner, Hashrate, Nonce.