用户手机号加密入库,两条以 138 开头的号码密文前 16 字节完全相同。运维对比了两列,发现相同的号码密文也相同,一眼能看出哪些用户号码重复。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key, iv = AESGCM.generate_key(256), os.urandom(12)
ct = AESGCM(key).encrypt(iv, phone.encode(), None)

ECB 把明文按块独立加密,相同的明文块得到相同的密文块,块与块之间没有关联。数据里重复的片段在密文里也重复,模式和结构全暴露了。它没有 IV,谈不上随机性。这一点先确认清楚,后面就不用反复试。

碰到「AES ECB 模式」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。

具体做法是,换成 GCM 或 CBC 这类带 IV 的模式 GCM 还能顺带校验完整性;每次加密生成新的随机 IV 和密文一起存;IV 不要复用 也不要写死在配置里;历史数据解密后用新模式重新加密。

改完照着核一遍,同一号码加密两次密文不同 库里看不到成片相同的十六字节前缀。

作者 9823189