8

JS 开发密码学速览

 2 years ago
source link: https://blog.dteam.top/posts/2022-05/quick-cryptography-for-js-devs.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

加密 API 选用原则

  • 优先语言标准库。
  • 优先知名且经过审计的库。
  • 选用第三方库时,先摸清背景。
  • 编码:使用 Buffer 完成各类编码格式转换。
  • 随机数
    • 各类加密技术的基础。
    • 真随机数获取极其困难,常用加密专用伪随机数。
    • 不要使用 Math.random !!
    • 使用 crypto 模块中的 random 函数,如 crypto.randomBytes
  • Hash
    • 输出为定长字符串。
    • 相同输入,输出相同。
    • 不同输入,输出不同。
    • 典型应用
      • 数据完整性验证
  • 密钥
    • 派生密钥:由主密钥生成的密钥。
    • 密钥封装:加密并导出密钥。
    • 解封密钥:解密并导入密钥。
  • 认证加密:加密且防篡改
  • 对称加密
    • 加解密使用相同密钥
    • 可操作大数据块
    • 密钥交换是难题
  • 非对称加密
    • 公钥 + 私钥
      • 加密:公钥加密,私钥解密
      • 签名:私钥加密,公钥解密
    • 不适合大数据块
  • 混合加密
    • 以上两种组合
      • 非对称加密交换密钥
      • 对称加密操作数据
  • 不推荐的算法
    • SHA-1
    • PBKDF2
    • bcrypt
  • 消息摘要:SHA-256 及其它同族
    • crypto.createHash('sha256')
    • 对于大数据采用流模式
    • 不要用于敏感数据,如口令。
  • 消息认证码(HMAC)
    • 结合哈希和密钥(密钥需双方事先协商)
    • crypto.createHmac('sha256', 'secret')
  • 口令哈希和 KDF(Key Derivation Function)
    • 特点:
      • 自带 salt
      • 有意用慢算法抵消硬件升级带来的计算速度提升
    • argon2(优先)
    • scrypt
      • crypto.scrypt
  • 不推荐的算法
    • 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
  • 哈希
    • SHA-256:window.crypto.subtle.digest('SHA-256', ...)
    • HMAC: window.crypto.subtle.sign("HMAC", key, encoded)
    • 口令哈希:https://www.npmjs.com/package/hash-wasm
  • 加解密(同时适用于对称和非对称)
    • crypto.subtle.encrypt(algorithm, key, data)
    • crypto.subtle.decrypt(algorithm, key, data)
  • 数字签名
    • window.crypto.subtle.sign
    • window.crypto.subtle.verify

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK