Hash 算法

  • hash 算法是不可逆的摘要算法,非加密的,实现的是将任意长度的数据转换为固定长度的哈希值吧,具备雪崩效应讷,也就说微小的变化就会引发大幅的变化,核心的价值是用来校验数据的完整性以及防止被串篡改的实现吧

  • 算法拓展

    • 基础的hash算法:MD5 算法,SHA1算法,SHA256/SHA512 算法的实现吧

    • 增强:HMAC 的带有密钥的Hash 算法,防止数据被篡改吧,加盐(salt),慢哈希的实现(bctypt/argon2/scrypt),故意的设计慢,防止暴力破解密码吧

  • 设计拓展

    • 加盐的规则是:盐值必须是唯一的,随机的,避免彩虹表的工具吧

    • 哈希迭代:多次哈希(PBKDF2)提升被破解的成本吧

  • 设计哲学:

    • 禁止适用已经被破解的加密算法吧,优先适用 bcrtpt/argon2 进行密码的加密实现,以及SHA256进行文件的校验实现吧

    • 密码的存储存储我们的 哈希值,不存明文/盐值(nodejs 中会把盐值注入到hash结果中讷)

    • HMAC的密钥需要和业务数据进行分开存储讷

  • 适用场景

    • 密码存储的加密设置

    • 文件完整性的校验

    • 数据防篡改设计

    • 唯一标识的设计

Base64 编码

  • Base64 是可逆的编码方式(非加密),将二进制数据转换为 ASCII 字符集的字符串,解决二进制数据在文本协议(如 HTTP/JSON)中传输的兼容性问题

  • Base64 仅用于 “编码传输”,绝不用于加密(可逆且无密钥,毫无安全性);

  • URL/Cookie 中传输 Base64 必须用 “URL 安全版”,否则+//会被 URL 解析为特殊字符;

  • Base64 编码后数据体积会增加约 33%,大文件优先用二进制传输而非 Base64。

  • JSON 接口传输二进制数据(如小图片、音频片段);

  • Cookie/URL 携带少量二进制数据(需 URL 安全 Base64);

  • 邮件附件、MIME 协议编码(标准 Base64);

  • 前端本地存储二进制数据(如 localStorage 仅支持字符串)。

URL 编码

  • 传递 URL 参数值必须用 encodeURIComponent(100% 编码),而非 encodeURI;

  • 后端接收参数时需显式指定解码编码为 UTF-8;

  • 拼接 URL 时,仅对 “参数值” 编码,不要对整个 URL 反复编码。

  • URL 参数传递(如?keyword=Node.js 教程?keyword=Node.js%20%E6%95%99%E7%A8%8B);

  • 处理含特殊字符的 URL 路径 / 参数(如空格、中文、&、=);

  • 前端向后端传递非 ASCII 字符(如用户名、搜索关键词)。

对称加密

  • 加密和解密使用同一密钥,算法速度快,核心问题是 “密钥安全传输 / 存储”。

  • 推荐:AES(AES-128/AES-256)+ GCM 模式(带认证,防篡改);

  • 禁用:DES(密钥短)、3DES(效率低)、ECB 模式(无 IV,相同明文生成相同密文);

  • 密钥派生:通过 PBKDF2/scrypt 从用户密码生成固定长度密钥(避免弱密钥);

  • 密钥轮换:定期更换密钥,降低密钥泄露风险;

  • AEAD(认证加密)模式(GCM/CCM),同时保证机密性和完整性。

  • 优先选 AES-256-GCM(安全 + 高效 + 带认证),IV 必须随机且与密文一起传输;

  • 密钥长度符合算法要求(AES-256 需 32 字节),不要硬编码密钥(用环境变量 / 密钥管理服务);

  • 大文件加密:分片加密(避免一次性加载到内存)。

  • 本地敏感数据加密(如配置文件中的数据库密码);

  • 服务间内部通信加密(如微服务数据传输);

  • 大文件加密(速度快,适合批量数据);

  • 临时数据加密(如缓存中的敏感信息)。

非对称加密

  • 使用 “公钥 - 私钥对”:公钥加密→私钥解密,私钥签名→公钥验签;公钥可公开,私钥需严格保密,算法速度慢(仅适合小数据)。

  • RSA:常用(兼容好),但密钥长、速度慢;

  • ECC(椭圆曲线):如 secp256r1,密钥更短(256 位≈RSA 3072 位)、速度更快(推荐新系统用);

  • 数字签名:RSA-SHA256/ECDSA(接口验签、文件签名);

  • 密钥交换:ECDH(安全交换对称密钥,HTTPS 握手用);

  • 证书体系:X.509 证书(验证公钥归属,HTTPS、代码签名用);

  • JWT 签名:RS256(非对称签名,多服务认证)。

  • 非对称加密仅用于 “加密小数据”(如对称密钥),不加密大文件(速度慢);

  • 签名优先用 ECDSA(比 RSA 高效),验签逻辑需防重放攻击(加时间戳 /nonce);

  • 私钥必须离线存储(如硬件安全模块 HSM),禁止暴露到代码 / 日志中。

  • 密钥交换:HTTPS 握手(交换对称密钥)、端到端加密(如聊天软件);

  • 数字签名:接口验签(如开放平台 API)、文件 / 代码签名(防篡改);

  • 身份认证:SSH 登录、区块链交易签名、JWT 非对称认证;

  • 公钥加密:敏感小数据传输(如用户手机号、验证码)。

类别

典型算法

输出长度

安全等级

适用场景

Node.js 支持性

弱哈希(淘汰)

MD5、SHA1

128bit/160bit

极低

仅历史兼容(禁止新业务)

✅ 原生支持

强哈希(推荐)

SHA256/SHA512、Blake2b

256bit/512bit

文件校验、数据签名

✅ 原生支持

密码哈希(专用)

bcrypt、argon2、scrypt、PBKDF2

变长

极高

密码存储

bcrypt/argon2 需第三方库,scrypt/PBKDF2 原生支持

实现方式

Node.js(bcrypt/argon2)

Python/Java(传统方式)

核心差异

盐值存储方式

盐值嵌入最终哈希结果(无需单独存储)

盐值需单独存储(如数据库字段salt

Node.js 更简洁,减少存储成本

盐值拼接方式

底层自动处理(非简单前后拼接,是算法级融合)

手动拼接(如salt + passwordpassword + salt

Node.js 避免手动拼接的安全漏洞

哈希迭代 / 复杂度控制

内置 “成本因子”(如 bcrypt 的 rounds),自动控制哈希速度

需手动实现迭代(如 PBKDF2 的 iterations 参数)

Node.js 封装更易用

  • $2a$:bcrypt 版本标识;

  • $10$:成本因子(rounds=10,哈希迭代次数 = 2^10=1024 次);

  • $N9qo8uLOickgx2ZMRZoMye:随机盐值(22 位 Base64 编码,对应 16 字节原始盐);

  • $eIjZAgcfl7p92ldGxad68LJZdL17lhWy:加盐后的哈希值(31 位 Base64 编码)。

最佳实践

  • 哈希算法

    • 密码存储:优先 argon2 > bcrypt > PBKDF2(scrypt 需注意内存限制);

    • 数据摘要:SHA256/Blake2b(替代 MD5/SHA1);

    • 接口签名:HMAC-SHA256(带密钥,防篡改 + 防重放);

    • 盐值:必须随机(crypto.randomBytes),bcrypt/argon2 无需单独存储。

  • Base64 编码

    • 小二进制数据传输(<1MB):Base64 编码(如小图片、JWT);

    • URL/Cookie 中:URL 安全 Base64(替换 +/-,去掉 =);

    • 大文件:分片 Base64 或直接二进制传输。

  • URL 编码

    • URL 参数值:必须用 encodeURIComponent(100% 编码);

    • 整个 URL:用 encodeURI(保留分隔符);

    • Cookie/Header:URL 编码非 ASCII 字符,避免解析错误。