NodeJs-Web Crypto API

 后端   小卒子   2024-09-11 09:28   199
  nodejs

Node.js 中的 Web Crypto API 模块提供了现代的密码学功能,允许开发者使用加密、解密、签名、验证、哈希等功能。该模块基于 Web Cryptography API 标准,因此提供的 API 与浏览器环境中的类似,具有一致的使用体验。

模块引入

在 Node.js 中,你可以通过 crypto.webcrypto 来访问 Web Crypto API。使用示例如下:

const { webcrypto } = require('crypto');

主要属性和方法

Node.js 的 Web Crypto API 模块包括以下几个主要部分:

  1. SubtleCrypto
  2. CryptoKey
  3. Key Algorithm
  4. Supported Algorithms
  5. 随机数生成 (getRandomValues)
  6. Web Crypto API 的实际使用示例

1. SubtleCrypto

SubtleCrypto 对象是 Web Crypto API 的核心部分,提供了加密、解密、签名、验证、哈希、密钥生成和导入/导出的功能。

可以通过 crypto.webcrypto.subtle 来访问:

const subtle = webcrypto.subtle;

常用方法:

  • encrypt(): 使用指定的加密算法对数据进行加密。
  • decrypt(): 使用指定的加密算法对密文进行解密。
  • sign(): 使用密钥对数据进行签名。
  • verify(): 验证签名的有效性。
  • digest(): 计算数据的哈希值。
  • generateKey(): 生成加密密钥。
  • deriveKey(): 从基础密钥派生新的密钥。
  • deriveBits(): 从基础密钥派生位数据。
  • importKey(): 导入现有密钥材料,生成 CryptoKey 对象。
  • exportKey(): 导出密钥材料。
  • wrapKey(): 使用密钥对另一个密钥进行加密。
  • unwrapKey(): 解密加密的密钥。

2. CryptoKey

CryptoKey 对象代表了在 Web Crypto API 中使用的密钥。所有加密操作都依赖于这些密钥对象。CryptoKey 可以是对称密钥或非对称密钥对的组成部分(如 RSA 密钥对中的公钥或私钥)。

CryptoKey 的常用属性:

  • type: 指示密钥是对称密钥 (secret) 还是非对称密钥对中的公钥 (public) 或私钥 (private)。
  • extractable: 指示密钥是否可以导出。
  • algorithm: 密钥的算法。
  • usages: 密钥的用途,可以是 encrypt, decrypt, sign, verify, deriveKey, deriveBits, wrapKey, unwrapKey 等。

示例:

// 生成 AES-GCM 对称密钥
subtle.generateKey(
  {
    name: "AES-GCM",
    length: 256,
  },
  true,  // 密钥是否可导出
  ["encrypt", "decrypt"]
).then(key => {
  console.log(key);
});

3. Key Algorithm

KeyAlgorithm 对象定义了 CryptoKey 使用的加密算法,具体包括以下几种:

  • AES-GCM: 一种支持认证的对称加密算法。
  • AES-CBC: 对称加密算法。
  • HMAC: 一种基于密钥的哈希消息认证码。
  • RSA-OAEP: 使用 Optimal Asymmetric Encryption Padding 的非对称加密算法。
  • RSA-PSS: 基于 Probabilistic Signature Scheme 的非对称签名算法。
  • ECDSA: 基于椭圆曲线的数字签名算法。
  • ECDH: 基于椭圆曲线的密钥协商算法。

不同算法有各自的参数设置,具体取决于算法的类型。


4. Supported Algorithms

Node.js Web Crypto API 支持的主要算法如下:

  • 对称加密算法

    • AES-GCM
    • AES-CBC
    • AES-CTR
    • AES-KW(密钥包裹算法)
  • 非对称加密算法

    • RSA-OAEP
    • RSA-PSS(签名验证)
  • 密钥协商算法

    • ECDH
  • 哈希算法

    • SHA-1
    • SHA-256
    • SHA-384
    • SHA-512
  • 消息认证码

    • HMAC

5. getRandomValues()

getRandomValues() 是一种用于生成随机数的安全方法。它可以生成加密强度的随机数,适用于生成密钥材料或其他密码学相关的数据。

使用示例:

const array = new Uint8Array(16);
webcrypto.getRandomValues(array);
console.log(array);

在此示例中,getRandomValues 会生成一个长度为 16 的随机字节数组。


6. 实际使用示例

1. 数据加密和解密

以下是如何使用 AES-GCM 对称加密算法来加密和解密数据的示例:

async function encryptData(data, key) {
  const iv = webcrypto.getRandomValues(new Uint8Array(12));  // 初始化向量
  const encrypted = await subtle.encrypt(
    {
      name: "AES-GCM",
      iv: iv,
    },
    key,
    data
  );
  return { encrypted, iv };
}

async function decryptData(encrypted, key, iv) {
  const decrypted = await subtle.decrypt(
    {
      name: "AES-GCM",
      iv: iv,
    },
    key,
    encrypted
  );
  return decrypted;
}

(async () => {
  const key = await subtle.generateKey(
    {
      name: "AES-GCM",
      length: 256,
    },
    true,
    ["encrypt", "decrypt"]
  );

  const data = new TextEncoder().encode("Hello World");
  const { encrypted, iv } = await encryptData(data, key);

  const decrypted = await decryptData(encrypted, key, iv);
  console.log(new TextDecoder().decode(decrypted));
})();

2. 哈希数据

下面是使用 SHA-256 算法对数据进行哈希的示例:

async function hashData(data) {
  const hash = await subtle.digest("SHA-256", data);
  return hash;
}

(async () => {
  const data = new TextEncoder().encode("Hello World");
  const hash = await hashData(data);

  console.log(Buffer.from(hash).toString('hex'));
})();

3. 生成和验证数字签名

async function generateKeyPair() {
  return await subtle.generateKey(
    {
      name: "ECDSA",
      namedCurve: "P-256", // 可选 "P-384", "P-521"
    },
    true,
    ["sign", "verify"]
  );
}

async function signData(data, privateKey) {
  return await subtle.sign(
    {
      name: "ECDSA",
      hash: "SHA-256",
    },
    privateKey,
    data
  );
}

async function verifySignature(data, signature, publicKey) {
  return await subtle.verify(
    {
      name: "ECDSA",
      hash: "SHA-256",
    },
    publicKey,
    signature,
    data
  );
}

(async () => {
  const { publicKey, privateKey } = await generateKeyPair();

  const data = new TextEncoder().encode("Hello World");
  const signature = await signData(data, privateKey);

  const isValid = await verifySignature(data, signature, publicKey);
  console.log("Signature valid:", isValid);
})();

总结

Node.js 的 Web Crypto API 模块提供了强大的现代密码学支持,包括对称加密、非对称加密、哈希、签名验证、密钥派生等功能。通过 SubtleCrypto API,开发者能够实现安全的数据加密、解密、哈希和签名功能,同时保持与浏览器端 API 的一致性。这为构建安全应用程序和实现跨平台的密码学操作提供了便捷的解决方案。