Daily Tech Briefing
AI 科技速览
每天 5 分钟内学习 AI。获取最新的人工智能新闻,理解其重要性,并学习如何将其应用于您的工作。
Dev.to AI · 2026/8/1 09:00:32
Nobody Writes Bad Crypto. They Write Correct Crypto at Four Layers.
AI 中文解读
这篇文章揭露了一个反直觉的现象:程序员很少写出“明显错误”的加密代码,真正的漏洞往往藏在看起来完全正确的外表下。作者把密码学问题拆成四个隐蔽层次:第一层是用错工具类型,比如该用加密哈希却用了普通随机数;第二层是选错加密模式,AES加密算法看着高级,但用了ECB模式就像给图片盖了层透明纸,加密后还能看出原图;第三层是参数错误,比如用固定不变的初始化向量,或者用了过时的填充方式,这些细节往往是一行常量,很难引起注意;第四层更隐蔽,连加密本身都是对的,却在后续代码里把密钥打印出来,或者用不安全的比较方式泄露了信息。
最反直觉的是,越重视安全、越有经验的团队,反而越容易栽在三四层。因为他们花大力气升级了算法,却以为高枕无忧,不再检查更深的漏洞。对普通人来说,这意味着即便你的密码学技术再先进,真正决定安全的是整个系统的每个环节。未来,企业做安全审计时,不能只盯着“用了什么算法”,还得专门排查参数和使用逻辑,才能避免“金库大门焊死了,窗户却开着”的尴尬。
<p>The code review comment I have written most often, and regretted most often, is<br>
"use a stronger algorithm."</p>
<p>It is regrettable because it is almost never the actual defect. It is the defect I can see<br>
from where I am standing. The team swaps SHA-1 for SHA-256, everyone agrees the review was<br>
useful, and the thing that would have mattered stays where it was.</p>
<h2>
Four layers, each hiding the next
</h2>
<p>A crypto call has to be right four separate times, and being correct at one layer makes<br>
the next one invisible. AES looks like a decision you already made. It is four.</p>
<p><strong>Layer 1 — the primitive.</strong> {#layer-1} Right kind of thing? A hash where you needed a<br>
KDF. A cipher where you needed a MAC. <code>Math.random()</code> where you needed a CSPRNG. Everyone<br>
reviews this layer, because it is visible in the function name.</p>
<p><strong>Layer 2 — the mode.</strong> {#layer-2} Primitive right, mode wrong. AES in ECB encrypts<br>
identical blocks to identical ciphertext — which is why the famous penguin is still<br>
legible after "encryption." Nothing about <code>aes-256-ecb</code> reads as wrong at a glance; it<br>
contains <code>aes</code> and <code>256</code>, and both are reassuring.</p>
<p><strong>Layer 3 — the parameters.</strong> {#layer-3} Right primitive, right mode, wrong inputs. A<br>
static IV. An iteration count set in 2015 and never revisited. RSA where someone passed<br>
<code>RSA_PKCS1_PADDING</code> explicitly — Node defaults to OAEP, so this one takes a deliberate<br>
argument to get wrong, which is exactly why it survives review. Each is a single value,<br>
usually a constant, and constants do not attract attention.</p>
<p><strong>Layer 4 — the usage.</strong> {#layer-4} Everything above correct, and the surrounding code<br>
gives it away. Comparing an HMAC with <code>===</code> and leaking the answer through timing.<br>
Deriving a key correctly, then logging it. This layer is not crypto code at all, which is<br>
why crypto review misses it.</p>
<h2>
Why layers beat a rule list
</h2>
<p>A rule list tells you what to grep for. The layer tells you where your team is, and<br>
therefore what you are <em>not</em> going to catch.</p>
<p>My working hypothesis — and it is a hypothesis, not something I have measured — is that<br>
failures cluster by how much crypto attention a team has already had. Never thought about<br>
it: layer 1. Just audited: layer 2, because the audit said "upgrade the primitives" and it<br>
did exactly that. Careful for years: layers 3 and 4.</p>
<p>If that holds, the uncomfortable corollary is that layer 3 and 4 defects live longest<br>
<em>because</em> the code passes every review asking "are we using strong algorithms." The<br>
maturity that fixes the first two layers is the same maturity that stops looking further<br>
down. That is the measurement I most want from this taxonomy.</p>
<h2>
Detection: the easy layers are the trap
</h2>
<p>Layers 1 and 2 live in a single call expression. <code>createHash("sha1")</code> and <code>aes-256-ecb</code><br>
are string literals; matching them is syntactic and any linter does it well.</p>
<p>Layers 3 and 4 are not. Whether an IV is static depends on where it came from — a<br>
data-flow question, the difference between<br>
<a href="https://ofriperetz.dev/go/taint-vs-heuristic-detection?utm_source=devto&from=crypto-misuse-taxonomy" rel="noopener noreferrer">matching a pattern and following a value</a>.<br>
Whether a comparison is timing-unsafe depends on whether the value is a secret, which no<br>
analyzer knows from the expression alone.</p>
<p>So tool coverage is inversely correlated with how long a defect survives. The layers a<br>
tool covers cleanly are the ones your team already fixes. Read any claim that a tool<br>
"covers crypto" as "covers layers 1 and 2" until shown otherwise — and checking that needs<br>
<a href="https://ofriperetz.dev/go/ground-trut
分享
阅读原文 ↗