从哈希函数到块密码:Davies-Meyer结构与SHACAL实例解析

📅 2026/8/8 5:06:29
从哈希函数到块密码:Davies-Meyer结构与SHACAL实例解析
1. 从“散列”到“加密”一个被误解的密码学概念在密码学的世界里哈希函数和块密码是两大基石但它们解决的问题和实现方式截然不同。当“基于哈希函数的块密码”这个标题出现时很多人的第一反应可能是困惑哈希函数不是单向的、不可逆的吗怎么能用来构建可逆的块密码呢这听起来像是一个技术悖论。实际上这个标题指向的是一种特定且重要的密码学构造思路——利用哈希函数的设计理念和组件来构建一个安全的、可逆的加密算法。这并非天方夜谭而是密码学历史上一个经典的“借力打力”案例它完美诠释了如何将一种密码原语的核心强度转化为另一种原语的构建材料。简单来说这种思路的核心在于块密码需要一个强大的、混乱的、非线性的轮函数来对数据进行多轮混淆和扩散。而现代密码学哈希函数如SHA-256的内部压缩函数恰恰就是一个经过精心设计、能抵抗各种密码分析攻击的、高度非线性的复杂函数。那么一个很自然的想法就是能不能把这个现成的、强大的“轮函数”拿过来稍作修改和包装让它变成一个块密码的加密轮次呢答案是肯定的并且已经有成熟的设计模式比如著名的Davies-Meyer结构它本身就是许多哈希函数如MD5, SHA-1, SHA-2家族的核心构造模块而这个结构反过来又可以用于构建块密码。理解这个概念不仅能让你看清哈希函数和块密码之间深刻的联系更能让你掌握一种“降维”分析复杂密码系统的方法。当你下次看到一个陌生的加密算法时如果能识别出它内部可能采用了类似哈希函数组件的结构你对它的安全性和性能会有一个更直观的判断。本文将深入拆解这一技术路径从原理、经典构造到实际考量为你呈现一个完整的知识图谱。2. 基石解析哈希函数与块密码的本质差异与内在联系要理解“基于哈希函数构建块密码”首先必须厘清这两者的根本区别然后才能找到它们之间的桥梁。很多人容易混淆是因为它们都处理数据并输出固定长度的结果但目标和性质完全不同。2.1 哈希函数的单向性与抗碰撞性哈希函数更准确地说是密码学哈希函数其核心特性是单向性和抗碰撞性。你输入任意长度的数据消息它输出一个固定长度的“指纹”哈希值。这个过程是单向的从哈希值反推原始消息在计算上是不可行的。同时找到两个不同的消息产生相同哈希值即碰撞也应该是极其困难的。它的工作模式通常是迭代的将长消息分割成固定大小的块然后与一个内部状态称为链接变量一起送入一个压缩函数中进行处理。这个压缩函数是哈希函数的心脏它接收两个固定长度的输入一个消息块和一个中间状态输出一个新的固定长度的中间状态。经过多轮迭代最终的中间状态就是哈希值。哈希函数的设计目标不是可逆而是最大限度地制造混乱和扩散确保输入哪怕有一比特的改变输出也会发生雪崩效应变得面目全非。2.2 块密码的可逆性与混淆扩散块密码则不同。它是一个可逆的变换。它接收一个固定长度的明文块和一个密钥输出一个相同长度的密文块。并且存在一个解密函数使用相同的密钥对称密码可以将密文块恢复为明文块。块密码的核心是混淆和扩散。混淆指密文与密钥之间的关系尽可能复杂防止密钥被轻易推导扩散指明文或密钥中一位的改变会影响密文中许多位的变化。块密码通常通过多轮迭代实现。每一轮都包含一个轮函数轮函数接收当前的数据块和该轮的轮密钥对数据块进行代换和置换操作。一个安全的块密码其轮函数必须提供足够的非线性和扩散能力。2.3 联系的纽带压缩函数与轮函数现在关键的联系点出现了。哈希函数的压缩函数和块密码的轮函数在抽象层面上承担着相似的角色它们都是一个接收固定长度输入、产生固定长度输出的密码学原语并且都需要具备强大的非线性和扩散特性。哈希函数的压缩函数为了抵抗碰撞和原像攻击已经被设计得非常坚固。那么一个很直接的想法是能否将这个现成的、坚固的压缩函数当作一个块密码的轮函数来使用这个想法是可行的但需要解决一个核心矛盾哈希函数的压缩函数是单向的而块密码的轮函数需要是可逆的至少在使用相同密钥进行解密时。解决方案不是让压缩函数本身可逆而是通过一种巧妙的构造模式将整个加密过程设计成可逆的。这种模式通常会将密钥作为压缩函数的一部分输入并利用类似Feistel网络的结构或特定的操作顺序使得在知晓密钥的情况下能够逆向执行整个流程从而实现解密。接下来我们就深入最经典的构造模式。3. 核心构造模式Davies-Meyer与单向压缩函数的再利用在“基于哈希函数构建块密码”的诸多方案中Davies-Meyer (DM) 结构是最著名、最直接的一种。它清晰地展示了如何将一个单向的压缩函数转化为一个可逆的加密/解密过程。有趣的是DM结构本身也是构建Merkle-Damgård结构哈希函数如MD5, SHA-1, SHA-2的核心。这里我们讨论的是它的“反向”应用。3.1 Davies-Meyer结构的工作原理假设我们有一个现成的、单向的压缩函数记作Compress(State, MessageBlock)。它接收一个状态State和一个消息块MessageBlock输出一个新的状态。在哈希函数中State是之前的中间哈希值MessageBlock是当前要处理的数据块。现在我们要用这个Compress函数来构建一个块密码。我们将块密码的明文对应为压缩函数的状态State将块密码的密钥或由密钥派生出的轮密钥对应为压缩函数的消息块MessageBlock。那么一轮简单的加密可以定义为Ciphertext Compress(Plaintext, Key) ⊕ Plaintext这里引入了一个异或操作。加密过程是将明文和密钥一起送入压缩函数得到的结果再与原始的明文进行异或输出作为密文。为什么这样设计就能实现可逆的解密呢解密过程如下Plaintext Compress(Ciphertext ⊕ Key, Key) ⊕ (Ciphertext ⊕ Key)这个式子看起来复杂但原理是关键。注意在加密时Compress的输入是(Plaintext, Key)。在解密时我们无法直接逆向计算Compress但我们可以利用一个技巧我们构造一个输入使得Compress的输出能与密文运算后还原出明文。通过代入推导可以发现如果解密者知道密钥他可以通过计算Ciphertext ⊕ Key得到一个中间值然后将这个中间值同时作为Compress函数的State和MessageBlock输入具体形式可能因变种而异最后再与同一个中间值异或就能神奇地得到原始明文。注意上述是最简化的单轮DM描述。实际安全的块密码需要多轮迭代。每一轮都会使用一个由主密钥通过密钥调度算法生成的轮密钥来代替上面公式中的Key。并且为了增强安全性通常在每一轮前后还会增加固定的置换或加解密步骤。3.2 安全性讨论固定点与碰撞攻击的关联使用DM结构或其他类似结构基于哈希函数构建块密码时其安全性与底层压缩函数的安全性紧密绑定但威胁模型发生了变化。在哈希函数中攻击者的目标是找到碰撞或原像。在基于DM的块密码中攻击者的目标可能包括密钥恢复攻击在已知若干明文-密文对的情况下推导出密钥。区分攻击区分这个密码算法与一个理想的随机置换。一个著名的潜在问题是固定点攻击。如果一个攻击者能找到一个(Plaintext, Key)对使得Compress(Plaintext, Key) 0那么根据加密公式Ciphertext 0 ⊕ Plaintext Plaintext。这意味着明文和密文相同攻击者如果能为特定密钥找到这样一个固定点就获得了一个特殊的明文-密文对这可能降低算法的有效密钥空间或为其他攻击打开突破口。而寻找这样的固定点在某种程度上类似于为压缩函数寻找碰撞或原像。因此如果底层哈希函数的压缩函数被发现有严重的弱点如易于找到碰撞那么基于它构建的块密码的安全性也会大打折扣。这反过来也强调了使用经过充分密码学分析、强度足够的哈希函数如SHA-2、SHA-3的组件作为基础的重要性。4. 从理论到实例SHACAL与SHA-256的华丽转身理论需要实例来佐证。在密码学历史上确实存在将哈希函数标准直接“改造”为块密码的著名案例其中最典型的就是SHACAL家族密码。4.1 SHACAL-1与SHACAL-2的设计精髓SHACALSecure Hash Algorithm Cipher Algorithm是一组基于SHA哈希函数系列的块密码。其中最具代表性的是SHACAL-1基于SHA-1的压缩函数。SHACAL-2基于SHA-256和SHA-224的压缩函数。它们的设计思想非常直接将SHA的压缩函数几乎原封不动地用作块密码的加密轮函数。具体来说数据块SHA-256压缩函数处理一个256位的中间哈希值和512位的消息块。在SHACAL-2中这256位的中间哈希值就被当作明文/密文块块大小为256位而那512位的消息块则被当作轮密钥。加密过程将256位的明文块作为初始的“链接变量”将扩展后的密钥或其一部分作为“消息块”代入SHA-256压缩函数执行一轮计算输出结果作为新的中间状态。这个过程重复多轮例如SHACAL-2标准建议80轮与SHA-256的轮数一致。最终的状态就是密文块。密钥调度主密钥最长512位通过一个类似但可能简化的密钥扩展算法生成80个512位的轮密钥。这保证了每一轮都有新鲜的密钥材料注入。解密过程由于SHA压缩函数本身是单向的SHACAL的解密并非简单逆运算。它需要利用压缩函数内部操作的特性主要是位运算和模加运算从最后一轮开始逆向推导出上一轮的中间状态。这个过程是精心设计的确保在知道全部轮密钥的情况下是可行的但计算量通常比加密稍大。4.2 实战中的考量性能、密钥长度与标准化虽然SHACAL在概念上很优雅但在实际应用中需要权衡几个关键点性能SHA-256压缩函数设计时优先考虑的是抗碰撞性而非加解密速度。它包含大量复杂的位运算、逻辑函数和模加法。因此基于它构建的SHACAL-2其加解密速度通常低于那些为高效加密而专门设计的块密码如AES。在软件实现上这可能是一个劣势。块大小与密钥长度SHACAL-2提供256位的块大小和最长512位的密钥。256位的块大小比AES的128位更大在某些特定模式下如某些认证加密模式可能提供更好的安全性边界。超长的密钥长度512位远远超出了当前及可预见的未来计算能力的破解范围提供了“过度安全”。但这也意味着密钥管理开销更大。标准化与采纳度SHACAL曾提交给NESSIE欧洲密码学项目和CRYPTREC日本密码技术评估项目进行评估。虽然它被认为在算法设计上是安全的但最终未能像AES那样成为全球广泛采纳的标准。原因包括性能因素、AES的先发优势以及足够的成熟度。因此在大多数通用场景下AES仍是首选。SHACAL更可能出现在一些对基于哈希构造有特殊偏好、或需要与SHA-256硬件实现高度集成的 niche 场景中。从SHACAL这个例子我们可以学到一个技术上可行的方案要成为工业标准需要在天时、地利、性能、生态等多个维度都具有竞争力。5. 另一种路径海绵结构与可调密码除了基于传统Merkle-Damgård结构哈希函数如SHA-2的构造现代密码学特别是SHA-3Keccak的获胜带来了另一种强大的密码学结构——海绵结构。这种结构为“基于哈希函数的密码”提供了更统一、更灵活的视角。5.1 海绵结构一种通用的密码学原语工厂海绵结构本身不特指哈希函数。它是一个通用的框架可以实例化为哈希函数、消息认证码、流密码当然也包括块密码。其核心是一个固定大小的内部状态海绵以及一个被称为置换函数的核心组件。工作分为两个阶段“吸收”和“挤压”。在吸收阶段输入数据被分块与内部状态进行混合在挤压阶段从内部状态中提取输出块。整个过程由置换函数驱动该函数在每一轮或每吸收/挤压一个数据块后对整个内部状态进行一个固定的、可逆的置换操作。Keccak-f置换函数是SHA-3的核心它是一个对1600位状态进行操作的复杂置换。它的设计目标之一就是高效和灵活性。5.2 从海绵结构到可调块密码基于海绵结构可以非常自然地构造一种称为可调块密码的模式。在这种模式下算法的内部状态被分为两部分一部分对外保密相当于密钥另一部分公开相当于“调整值”或“tweak”。明文/密文在吸收/挤压过程中与状态交互。核心的加密动力源就是那个强大的、固定的置换函数例如Keccak-f。你可以这样理解在这个构造中置换函数扮演了传统块密码中“轮函数”的角色。只不过这个“轮函数”不是基于密钥变化的而是固定的、公开的。安全性来自于初始状态中保密的密钥部分以及置换函数本身极强的扩散和混淆能力。这种构造的优势在于简洁与统一同一个核心置换Keccak-f可以用于哈希、认证加密、流密码和块密码简化了系统设计。可证明安全性在理想置换模型下海绵结构的安全性证明相对清晰。灵活性通过调整“tweak”可以很容易地从一个主密钥派生出大量不同的、关联性可控的“次密钥”适用于磁盘加密等需要大量不同密钥的场景。因此当我们谈论“基于哈希函数的块密码”时在现代语境下很可能指的就是这种基于SHA-3/Keccak海绵结构和置换函数的可调密码设计。这代表了比SHACAL更现代、更通用的一种设计哲学。6. 设计权衡与安全实践何时考虑如何选择了解了原理和实例后作为一个实践者你可能会问我到底该不该使用或者设计一个基于哈希函数的块密码这需要冷静的权衡。6.1 优势分析信任传递如果整个系统已经重度依赖并信任某个哈希函数例如SHA-256那么使用基于其构建的块密码可以在一定程度上简化系统的密码学信任基础。你不需要再引入一个全新的、需要单独评估的密码算法。实现一致性在硬件或深度优化的软件库中如果已有高效的SHA-256指令集或代码那么实现SHACAL-2的加密可能会共享大部分底层操作节省代码体积和开发成本。抗特定攻击由于设计根源不同基于哈希的密码可能对某些针对传统Feistel或SPN结构密码的专用攻击如某些线性或差分攻击的变种具有天然的抵抗力。大块与长密钥如SHACAL-2提供的256位块和512位密钥为需要极高安全边际的应用提供了选项。6.2 劣势与风险性能瓶颈这是最主要的顾虑。哈希函数为抗碰撞优化其操作如模加、复杂布尔函数通常比AES等专用加密算法的操作查表、字节置换在通用CPU上更慢。加解密吞吐量可能成为系统瓶颈。侧信道攻击风险哈希函数的实现可能并未像AES那样经过广泛的侧信道攻击如计时攻击、功耗分析防护设计和审查。直接将其实施为密码可能引入新的侧信道漏洞。缺乏广泛审查像AES这样的标准经历了全球密码学界近20年的高强度、公开的分析攻击。而基于哈希的密码如SHACAL所受到的审查强度和广度远不及前者。可能存在尚未被发现的设计弱点。生态支持弱在主流密码库如OpenSSL, libsodium中AES的支持是最高优先级的通常有硬件加速。而基于哈希的密码往往只有软件实现且优化程度不高缺乏标准的操作模式支持。6.3 实操建议与决策指南基于以上分析我的个人建议是对于绝大多数应用请坚持使用标准化的、广泛采用的块密码如AES。AES在性能、安全性证明、硬件支持、库生态、抗侧信道实现经验等方面拥有无与伦比的优势。它是经过时间考验的工业标准。仅在以下非常特定的场景中才考虑基于哈希函数的块密码极端受限的环境在一个已经内置了SHA-256硬件加速但没有任何对称加密硬件加速的极端嵌入式设备上为了节省门电路或代码空间使用SHACAL-2可能是合理的。但必须自行全面评估侧信道风险。密码学协议研究在设计需要与哈希函数进行某种形式“同态”操作或证明的先进密码协议时使用基于同一原语的密码可能简化安全证明。教育与实践为了深入理解哈希函数和块密码的构造原理亲手实现或分析一个类似SHACAL的算法是绝佳的学习方式。这能极大地加深你对密码学组件复用和模式设计的理解。如果你决定使用务必做到选择经过一定分析的算法如SHACAL-2而不是自己临时用某个哈希函数拼凑一个。进行严格的性能测试与AES等标准算法在目标平台上进行对比。关注侧信道防护确保实现是常数时间的并考虑必要的防护措施。明确记录决策原因在系统设计文档中清晰说明为何不采用AES而选择此方案。7. 深入轮函数剖析SHA-256压缩函数如何充当加密引擎要真正理解“基于哈希函数的块密码”如何工作我们需要钻进去看看SHA-256的压缩函数这个“引擎”的内部构造并理解它如何被“驾驶”来完成加密任务。这对于评估其安全性和性能至关重要。SHA-256压缩函数的核心是一个256位的中间状态8个32位字记作A, B, C, D, E, F, G, H和一个512位的输入消息块扩展为64个32位字记作W_t。每一轮共64轮的操作可以概括为以下步骤消息调度512位输入块被扩展成64个32位字W_t。这个扩展过程本身包含移位和异或等操作引入了额外的非线性。轮运算每一轮t进行如下计算T1 H Σ1(E) Ch(E, F, G) K_t W_t T2 Σ0(A) Maj(A, B, C) H G G F F E E D T1 D C C B B A A T1 T2其中Ch(E, F, G)是选择函数(E F) ^ (~E G)。Maj(A, B, C)是多数函数(A B) ^ (A C) ^ (B C)。Σ0,Σ1是循环右移和异或构成的函数。K_t是第t轮的常量。是模 2^32 加法。当这个压缩函数被用于SHACAL-2加密时中间状态A-H被初始化为明文。消息块W_t被替换为由主密钥扩展生成的轮密钥。执行完64轮运算后最终的中间状态A-H就是密文。可以看到每一轮中轮密钥W_t和轮常量K_t通过模加操作注入到状态中。Ch和Maj函数提供了关键的非线性。而Σ0、Σ1以及状态的移位传递B-C, C-D等提供了比特的扩散。整个结构是一个复杂的、高度非线性的状态更新函数。为什么解密是可能的仔细观察上述轮运算。除了模加法D T1和T1 T2其他操作赋值、位运算在已知所有轮密钥和轮常量的情况下都是可逆的。模加法的逆运算是模减法。因此从最后一轮的状态密文开始如果已知该轮的轮密钥W_t我们可以通过逆向计算进行相反的赋值顺序和模减法来恢复出前一轮的状态。如此逐轮逆向最终就能得到初始状态明文。这个过程要求解密者必须知道加密时使用的所有轮密钥这正是对称密码的要求。这种可逆性依赖于对压缩函数每一步的精确了解和控制。这也意味着如果你试图使用一个“黑盒”压缩函数只知其输入输出不知内部细节是无法构建出可解密的块密码的。你必须拥有其完整的算法描述。8. 超越加密构造模式与认证加密的启示“基于哈希函数的块密码”这一思想的价值不仅在于创造出一个新的加密算法更在于它启发了更广泛的密码学构造模式。这些模式将哈希函数或类似组件视为一种通用的密码学“乐高积木”。8.1 从块密码到哈希函数逆向思维我们讨论了用哈希函数造块密码。有趣的是反过来也是成立的并且更早被广泛应用用块密码来构造哈希函数。例如常见的Davies-Meyer、Miyaguchi-Preneel等结构就是用一个块密码如AES的加密函数作为压缩函数来构建哈希函数。这在AES成为标准后催生了如AES-based SHA-3候选算法等提案。这种双向可构造性深刻地揭示了密码学原语之间的内在统一性。一个强大的、具有良好混淆扩散性质的变换既可以作为保护数据机密性的工具加密也可以作为生成数据指纹的工具哈希关键在于如何使用它。8.2 海绵结构统一点的火花如前所述SHA-3的海绵结构将这种统一性推向了极致。在 sponge 构造中同一个核心置换Keccak-f可以实例化为哈希函数吸收消息后挤压出哈希值。消息认证码将密钥作为初始状态的一部分吸收。流密码在吸收密钥和初始向量后持续挤压出密钥流。可调块密码如前所述将密钥和调整值吸收进状态然后吸收/挤压明文/密文。这种“一个核心多种用途”的设计极大地简化了密码系统的架构。在一个资源受限的环境中你只需要实现和优化一个Keccak-f置换就能获得一套完整的密码学工具箱。这也是SHA-3算法家族在设计哲学上的重大进步。8.3 对认证加密设计的启发现代认证加密模式如AES-GCM通常组合使用一个块密码和一个哈希函数GHASH。而基于海绵结构的认证加密方案如Keccak团队提交的认证加密模式则能在一个统一的框架内用同一个置换同时完成加密和认证无需模式组合。这减少了设计复杂性和潜在的组合风险。“基于哈希函数的块密码”这一路径促使密码学家思考是否存在更本质的、更底层的密码学原语能否用更少的、更通用的组件来满足更多的安全需求海绵结构和可调密码正是这一思考下的杰出产物。它告诉我们未来的密码学标准可能不再是一堆孤立的算法一个加密、一个哈希、一个MAC而是一个或几个高度优化、可证明安全的通用引擎通过不同的调用模式来满足所有需求。因此学习和理解“基于哈希函数的块密码”不仅仅是掌握一个冷门的算法选项更是打开一扇窗去洞察密码学组件复用、模式设计和原语统一化的深层逻辑。它锻炼的是一种将复杂系统拆解为基本构件并思考构件之间如何转换和连接的能力这种能力对于深入理解任何密码协议和安全系统都至关重要。