JavaScript

JavaScript 知识量:26 - 101 - 483

19.10 加密解密><

Web Cryptography API- 19.10.1 -

Web Cryptography API 是 W3C 在 2016 年提出的一个 API 规范,它为 Web 开发者提供了一套丰富的密码学工具,使得开发者可以在浏览器环境中安全地进行加密和解密操作。

Web Cryptography API 支持以下几种主要的密码学方法:

  • 散列(Hashing):对数据进行单向转换,得到固定长度的摘要。常见的散列函数包括 SHA-256 和 SHA-512。

  • 签名生成和验证:通过私钥生成消息的数字签名,然后使用公钥验证该签名。这可以用来验证消息的来源和完整性。

  • 加密和解密:使用密钥对数据进行加密,然后使用同一密钥(对称加密)或另一密钥(非对称加密)对数据进行解密。

Web Cryptography API 提供了这些功能的高级接口,使得开发者可以在不需要深入理解密码学细节的情况下使用它们。这对于需要处理敏感数据或在网络上传输数据的 Web 应用来说是非常重要的。

此外,Web Cryptography API 还强调了错误处理和安全实践的重要性。例如,它要求开发者在处理加密密钥时应该使用安全的存储机制,并且在处理敏感数据时应该使用安全的传输机制。

生成随机数- 19.10.2 -

Web Cryptography API 中的 CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) 是一种高度安全的随机数生成器,它为开发者提供了一种生成可用于安全加密和其他密码学应用的随机值的方法。

crypto.getRandomValues() 是一个将加密强随机数生成器暴露给JavaScript的全局函数。这个函数接收一个类型化数组(例如 Uint8Array,Uint16Array,Uint32Array,等等)作为参数,并将加密强随机数填充到这个数组中。

与 Math.random() 相比,crypto.getRandomValues() 生成的随机数更安全。Math.random() 生成的随机数实际上是伪随机数,有潜在的安全风险。而 crypto.getRandomValues() 生成的随机数是真正的加密强随机数,它们来自系统底层的熵源(通常是一个安全的随机数生成器),因此更适用于需要高度安全性的密码学应用。

在使用 crypto.getRandomValues() 时,需要注意的一点是,应该始终确保类型化数组的长度足够大,以容纳想要生成的随机数的数量。这是因为一旦数组被填满,就不能再向它添加更多的随机数了。

以下是一个使用 Web Cryptography API 的 CSPRNG 生成随机数的示例:

// 创建一个长度为16的 Uint8Array数组,并将其作为参数传递给 getRandomValues 方法  
let buffer = new Uint8Array(16);  
window.crypto.getRandomValues(buffer);  
  
// 打印生成的随机数  
console.log(buffer);

在这个示例中,首先创建了一个长度为16的 Uint8Array 数组,并将其作为参数传递给 getRandomValues 方法。这个方法会将加密强随机数填充到数组中。然后,打印生成的随机数。由于 getRandomValues 方法返回的是加密强随机数,因此生成的随机数比使用 Math.random() 生成的伪随机数更安全,更适合用于需要高度安全的密码学应用。

使用SubtleCrypto对象- 19.10.3 -

SubtleCrypto 是一个通用的加密 API,它提供了许多底层加密功能,包括签名生成和验证、加密和解密、数据摘要生成等。

SubtleCrypto 对象提供了一系列方法,可以用于实现各种密码学操作。例如,sign() 和 verify() 方法用于创建和验证数字签名;encrypt() 和 decrypt() 方法用于加密和解密数据;digest() 方法用于生成数据的摘要;generateKey() 和 deriveKey() 方法用于生成和派生密钥;deriveBits() 方法用于派生伪随机字节;importKey() 和 exportKey() 方法用于导入和导出密钥;wrapKey() 方法用于在不安全的环境中使用包裹对称密钥。

SubtleCrypto 对象的使用非常灵活,可以根据不同的需求选择不同的方法和参数来实现密码学操作。同时,它还提供了错误处理和安全实践的支持,以确保开发者能够正确地使用密码学方法而不会出现安全漏洞。

以下是一个使用 Web Cryptography API 的 SubtleCrypto 对象进行 RSA 加密和解密的示例:

首先,需要使用 SubtleCrypto 对象的 generateKey 方法生成一个 RSA 密钥对:

window.crypto.subtle.generateKey(  
  {  
    name: "RSA-OAEP",  
    modulusLength: 2048, //can be 1024, 2048, or 4096  
    publicExponent: new Uint8Array([0x01, 0x00, 0x01]),  
    hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"  
  },  
  true, //whether the key is extractable (i.e. can be used in exportKey)  
  ["encrypt", "decrypt"] //can be any combination of "encrypt" and "decrypt"  
)  
.then(function(key){  
  //returns a keypair object  
  console.log(key);  
})  
.catch(function(err){  
  console.error(err);  
});

然后,可以使用 SubtleCrypto 对象的 encrypt 方法对数据进行加密:

window.crypto.subtle.encrypt(  
  {  
    name: "RSA-OAEP",  
  },  
  key, //from generateKey or importKey above  
  new TextEncoder().encode("Hello, World!") //ArrayBuffer of data you want to encrypt  
)  
.then(function(encrypted){  
  //returns an ArrayBuffer containing the encrypted data  
  console.log(new Uint8Array(encrypted));  
})  
.catch(function(err){  
  console.error(err);  
});

最后,可以使用 SubtleCrypto 对象的 decrypt 方法对数据进行解密:

window.crypto.subtle.decrypt(  
  {  
    name: "RSA-OAEP",  
  },  
  key, //from generateKey or importKey above  
  encrypted //ArrayBuffer of encrypted data  
)  
.then(function(decrypted){  
  //returns an ArrayBuffer containing the decrypted data  
  console.log(new TextDecoder().decode(decrypted));  
})  
.catch(function(err){  
  console.error(err);  
});