scrypt 是什么
scrypt 是 RFC 7914 定义的内存硬密钥派生函数。与主要消耗 CPU 的 PBKDF2 不同,它通过参数 N(迭代次数)、r(块大小)、p(并行度)同时抬高内存与计算成本,内存需求约为 128 × N × r 字节。这样显卡与专用电路的并行优势被大幅削弱,因此它被广泛用于口令存储与文件加密,也是 Argon2 之外的另一个内存硬选择。
基本信息
| 标准 | RFC 7914 |
|---|---|
| 参数 | N=2^17、r=8、p=1(OWASP 建议下限) |
| 内存开销 | 约 128 × N × r 字节;上述参数约 128 MiB |
| 输出 | dklen 通常取 32 字节 |
| 约束 | N 必须是 2 的幂 |
| 定位 | 内存硬 KDF,抑制 GPU 与 ASIC 的并行优势 |
典型使用场景
- 口令存储:作为 bcrypt 之外的备选,抬高暴力破解成本
- 文件与磁盘加密:从口令派生出实际的加密密钥
- 资源受限设备:用较小的 N 在移动端与嵌入式上取得平衡
- 容器化部署:按内存限额调整参数,避免派生过程被终止
- 选型评估:已有 scrypt 支持且不便换库时优先沿用并调参
Python 示例
Python 示例
import hashlib, os
salt = os.urandom(16) # 每个口令一份独立随机盐
key = hashlib.scrypt(b'password', salt=salt, n=2**17, r=8, p=1, dklen=32)
# 校验时需要同时保存 N/r/p、盐与输出,缺任何一项都无法复现
# 部署前做基准测试:单次派生的耗时与峰值内存是参数是否合适的直接证据参数读法
| 参数 | 作用 | 调整建议 |
|---|---|---|
| N | 迭代次数,必须为 2 的幂 | 提高它最能增加攻击成本 |
| r | 块大小,与 N 共同决定内存 | 一般固定为 8 |
| p | 并行度,影响 CPU 时间 | 保持较小值,主要靠内存约束 |
| dklen | 输出密钥长度 | 按后续算法需求,通常 32 字节 |
| salt | 随机盐 | 至少 16 字节,每个口令独立 |
N 提升内存与时间成本,部署前按目标设备(尤其移动端与容器内存限额)做基准测试再定参数。
容器与函数计算环境要特别注意:N=2^17、r=8 时约需 128 MiB 内存,若未同步调大内存限制,派生过程会被直接终止。
输出格式由使用方定义:scrypt 只返回密钥字节,参数、盐与算法标识的编码需要自行设计并写进文档,否则将来无法校验或迁移。