JS 开发密码学速览

  • 胡键
  • 更新于 2022-05-01 12:50
  • 阅读 2528

面向 JS 开发者的密码学要点速览。

原文链接

加密 API 选用原则

  • 优先语言标准库。
  • 优先知名且经过审计的库。
  • 选用第三方库时,先摸清背景。

基础

  • 编码:使用 Buffer 完成各类编码格式转换。
  • 随机数
    • 各类加密技术的基础。
    • 真随机数获取极其困难,常用加密专用伪随机数。
    • 不要使用 Math.random !!
    • 使用 crypto 模块中的 random 函数,如 crypto.randomBytes
  • Hash
    • 单向。
    • 输出为定长字符串。
    • 相同输入,输出相同。
    • 不同输入,输出不同。
    • 典型应用
    • 数据完整性验证
    • 口令哈希
    • 派生密钥
  • 密钥
    • 派生密钥:由主密钥生成的密钥。
    • 密钥封装:加密并导出密钥。
    • 解封密钥:解密并导入密钥。
  • 认证加密:加密且防篡改
  • 对称加密
    • 加解密使用相同密钥
    • 速度快
    • 可操作大数据块
    • 密钥交换是难题
  • 非对称加密
    • 公钥 + 私钥
    • 加密:公钥加密,私钥解密
    • 签名:私钥加密,公钥解密
    • 速度慢
    • 不适合大数据块
    • 典型应用
    • 密钥交换
    • 数字证书
    • 数字签名
  • 混合加密
    • 以上两种组合
    • 非对称加密交换密钥
    • 对称加密操作数据

Hash

  • 不推荐的算法
    • MD5
    • SHA-1
    • PBKDF2
    • bcrypt
  • 消息摘要:SHA-256 及其它同族
    • crypto.createHash('sha256')
    • 对于大数据采用流模式
    • 不要用于敏感数据,如口令。
  • 消息认证码(HMAC)
    • 结合哈希和密钥(密钥需双方事先协商)
    • crypto.createHmac('sha256', 'secret')
  • 口令哈希和 KDF(Key Derivation Function)
    • 特点:
    • 自带 salt
    • 有意用慢算法抵消硬件升级带来的计算速度提升
    • argon2(优先)
    • argon2i,抗 side-channel 攻击
    • argon2d,抗 GPU 攻击
    • argon2id(优先),以上组合
    • https://www.npmjs.com/package/argon2
    • scrypt
    • crypto.scrypt

对称加密

  • 不推荐的算法
    • DES
    • AES-ECB
  • AES
    • 典型模式:
    • AES-CBC,不需要认证时
      • crypto.createCipheriv('aes-256-cbc', ...)
      • crypto.createDecipheriv('aes-256-cbc', ...)
    • AES-GCM,需要认证时
      • crypto.createCipheriv('aes-256-gcm', ...)
      • crypto.createDecipheriv('aes-256-gcm', ...)
    • 对于大数据采用流模式
  • ChaCha20-Poly1305
    • ChaCha20 加密 + Poly1305 哈希
    • 等同于 AES-GCM
    • 适用于无 AES 硬件加速支持的环境
    • crypto.createCipheriv('chacha20-poly1305', ...)
    • crypto.createDecipheriv('chacha20-poly1305', ...)

非对称加密

  • ASN.1 数据结构
  • 键编码格式:PEM 格式
    • 公钥:SPKI
    • // 导入
      crypto.createPrivateKey(fs.readFileSync("public.pem"));
    • 私钥:
    • PKCS #1(旧,RSA only)
    • PKCS #8(新,面向多种算法)
    • //导入
      crypto.createPrivateKey(fs.readFileSync("private.pem"));
    • 导出:crypto.KeyObject.export(option)
  • RSA
    • key
    • crypto.generateKeyPair('rsa', ...)
    • 加解密
    • padding:加密前给明文加入随机数据以提高 RSA 的抗攻击能力。
      • 如无理由,总是使用。
      • crypto.constants.RSA_PKCS1_OAEP_PADDING(推荐)
      • crypto.constants.RSA_PKCS1_PADDING(不推荐)
    • crypto.publicEncrypt(
      {
        key: publicKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        oaepHash: "sha256",
      },
      plaintext
      );
    • crypto.privateDecrypt(
      {
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
        oaepHash: "sha256",
      },
      message
      );
    • 数字签名
    • padding:
      • crypto.constants.RSA_PKCS1_PADDING(缺省)
      • crypto.constants.RSA_PKCS1_PSS_PADDING(新版本,推荐)
    • crypto.sign("sha256", message, {
      key: privateKey,
      padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
      });
    • crypto.verify(
      "sha256",
      message,
      {
        key: publicKey,
        padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
      },
      signature
      );
  • 椭圆曲线
    • 与 RSA 同等的安全性
    • 密钥更短、更快、消耗资源更少
    • 常用曲线
    • P-256:secp256r1 / prime256v1,NIST 标准
    • Curve25519
      • 密钥交换时,X25519
      • 数字签名时,Ed25519
    • secp256k1,比特币采用
    • 典型应用
    • 密钥交换(ECDH)
    • 数字签名
    • key
    • crypto.generateKeyPair('ec', ...)
    • ECDH
    • 不同于 RSA(一方用另一方的公钥加密密钥之后,发给对方解密即可)。
    • DH 协议
      • Alice 和 Bob 各生成一个密钥对
      • 两者交换对方的公钥
      • 结合自身的私钥生成公共密钥,即:
      • shareSecret(A 公钥, B 私钥) = shareSecret(B 公钥, A 私钥)
    • crypto.diffieHellman({对方公钥,自己私钥})
    • 公共密钥的一个参考实现:
      • crypto.diffieHellman 得到 shareSecret
      • 生成随机 salt
      • sha256(shareSecret, salt) 为公共密钥,注:salt 记得随密文传给对方。
    • 数字签名
    • ECDSA(使用 prime256v1)
      • crypto.sign('sha256', message, privateKey)
      • crypto.verify('sha256', message, publicKey, signature)
    • EdDSA(使用 Ed25519),因其已经内置数字签名算法,故无需外部配置 hash 函数。
      • crypto.sign(null, message, privateKey)
      • crypto.verify(null, message, publicKey, signature)

Web Crypto

  • 应用于浏览器环境
  • 编码
    • ArrayBuffer
    • atobbtoa
    • TextEncoder
  • 随机数:
    • Window.crypto.getRandomValues
    • Window.crypto.randomUUID
  • 密钥
    • window.crypto.subtle.generateKey(algorithm, extractable, usages)
    • window.crypto.subtle.importKey(format, data, algorithm, extractable, usages)
    • window.crypto.subtle.exportKey(format, key)
    • window.crypto.subtle.wrapKey
    • window.crypto.subtle.unwrapKey
    • window.crypto.subtle.deriveKey
  • 哈希
  • 加解密(同时适用于对称和非对称)
    • crypto.subtle.encrypt(algorithm, key, data)
    • crypto.subtle.decrypt(algorithm, key, data)
  • 数字签名
    • window.crypto.subtle.sign
    • window.crypto.subtle.verify

参考

点赞 1
收藏 2
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

1 条评论

请先 登录 后评论
胡键
胡键
CSM / 架构师 / 创业者,先后就职于中兴和 SAP,现专注于工业物联网、机器学习和区块链。同时,作为机器学习和区块链技术活动的组织者和分享者活跃于本地社区。