前端加解密之 Crypto

时间:2024-11-19

之前写过 NodeJS 加解密之 crypto 模块,前端一般很少用这个功能,就我见过的业务来讲基本上没人用,了解了下前端浏览器支持的 Crypto 和 Node.js 模块支持的 Crypto API 还不太一样。

前端的 Crypto API 挂在浏览器的当前上下文,直接通过 crypto 就能访问。

image.png

包含一个属性两个方法:

方法属性CryptoRandomSourcesubtleCrypto.getRandomValuesrandomUUID

randomUUID 生成 v4 的 UUID 是很有用的 API,关于加解密的全部都在 subtle 属性上,使用 subtle 一定要注意下面提示的两点。

此功能:

  1. 仅在安全上下文(HTTPS)中可用

  2. 在某些或所有支持的浏览器中可用。

加密方式

前端浏览器的 Crypto 技术提供了以下常用加密方式:

1. 对称加密和解密

对称加密是一种加密方式,使用同一个密钥进行加密和解密。Web Crypto API 提供了多种对称加密算法,如 AES、DES 和 3DES 等,可以通过这些算法来加密和解密数据。

实现过程中用到的 Web API 参考:

所有 API 中最重要的是 SubtleCrypto.generateKey() API,SubtleCrypto.generateKey() 是 Web Cryptography API 中的一个方法,用于生成密钥。

该方法有三个参数:

下面演示对称加密和解密的过程:

async function encryptSymmetricKey(key, iv, data) {   const ciphertext = await window.crypto.subtle.encrypt(     {       name: "AES-GCM",       iv,     },     key,     data   );   return ciphertext; } async function decryptSymmetricKey(key, iv, ciphertext) {   const plaintext = await window.crypto.subtle.decrypt(     {       name: "AES-GCM",       iv,     },     key,     ciphertext   );   const decoder = new TextDecoder();   return decoder.decode(plaintext); } async function symmetricEncryptionDecryption() {   const text = "Shavahn";   // 生成一个随机的对称加密密钥   const key = await window.crypto.subtle.generateKey(     {       name: "AES-GCM",       length: 256,     },     true,     ["encrypt", "decrypt"]   );   // 将文本编码为 ArrayBuffer   const encoder = new TextEncoder();   const data = encoder.encode(text);   // 加密文本   const iv = window.crypto.getRandomValues(new Uint8Array(12));   const ciphertext = await encryptSymmetricKey(key, iv, data);   // 将加密后的文本解密   const decryptedText = await decryptSymmetricKey(key, iv, ciphertext);   console.log("原始文本:", text);   console.log("加密后的文本:", new Uint8Array(ciphertext));   console.log("解密后的文本:", decryptedText); } symmetricEncryptionDecryption();



  1. async function encryptSymmetricKey(key, iv, data):这是一个异步函数,用于加密传入的数据。它使用传入的对称密钥和初始化向量 iv,以及 AES-GCM 加密算法对数据进行加密,并返回加密后的结果 ciphertext。

  2. async function decryptSymmetricKey(key, iv, ciphertext):这是一个异步函数,用于解密传入的密文。它使用传入的对称密钥和初始化向量 iv,以及 AES-GCM 加密算法对密文进行解密,并将解密后的结果以字符串形式返回。

  3. async function symmetricEncryptionDecryption():这是一个异步函数,它执行了整个加密和解密的过程。它首先生成一个随机的 AES-GCM 对称密钥,并将要加密的文本编码为 ArrayBuffer。然后,它生成一个随机的 12 字节初始化向量 iv,并使用 encryptSymmetricKey 函数对文本进行加密。最后,它使用 decryptSymmetricKey 函数对密文进行解密,并输出原始文本、加密后的文本和解密后的文本。

  4. window.crypto.subtle:这是 Web Crypto API 提供的加密和解密函数的命名空间。它提供了一组对称和非对称加密算法,包括 AES-GCM、RSA-OAEP 等。

  5. TextEncoderTextDecoder:这两个对象用于将文本字符串编码为 ArrayBuffer 和将 ArrayBuffer 解码为文本字符串。在这个例子中,我们使用它们将文本字符串编码为 ArrayBuffer,以便进行加密,并将解密后的 ArrayBuffer 解码为文本字符串。

2. 非对称加密和解密

非对称加密是一种加密方式,使用一对公钥和私钥进行加密和解密。Web Crypto API 提供了多种非对称加密算法,如 RSA 和 ECDSA 等,可以通过这些算法来加密和解密数据。


2. 非对称加密和解密


async function encryptAsymmetricKey(publicKey, data) {   const encodedData = new TextEncoder().encode(data);   const encryptedData = await window.crypto.subtle.encrypt(     {       name: "RSA-OAEP",     },     publicKey,     encodedData   );   return encryptedData; } async function decryptAsymmetricKey(privateKey, encryptedData) {   const decryptedData = await window.crypto.subtle.decrypt(     {       name: "RSA-OAEP",     },     privateKey,     encryptedData   );   return new TextDecoder().decode(decryptedData); } async function asymmetricEncryptionDecryption() {   const text = "Shavahn";   // 生成一对非对称加密密钥   const keyPair = await window.crypto.subtle.generateKey(     {       name: "RSA-OAEP",       modulusLength: 2048,       publicExponent: new Uint8Array([1, 0, 1]),       hash: { name: "SHA-256" },     },     true,     ["encrypt", "decrypt"]   );   // 加密文本   const encryptedData = await encryptAsymmetricKey(keyPair.publicKey, text);   // 将加密后的文本解密   const decryptedText = await decryptAsymmetricKey(     keyPair.privateKey,     encryptedData   );   console.log("原始文本:", text);   console.log("加密后的文本:", new Uint8Array(encryptedData));   console.log("解密后的文本:", decryptedText); } asymmetricEncryptionDecryption();




数字签名是一种用于验证数据完整性和身份认证的技术,Web Crypto API 提供了多种数字签名算法,如 RSA 和 ECDSA 等,可以通过这些算法来对数据进行签名和验证。


async function signMessage(privateKey, message) {   const encoder = new TextEncoder();   const data = encoder.encode(message);   const signature = await window.crypto.subtle.sign(     {       name: "ECDSA",       hash: { name: "SHA-256" },     },     privateKey,     data   );   return signature; } async function verifySignature(publicKey, message, signature) {   const encoder = new TextEncoder();   const data = encoder.encode(message);   const isVerified = await window.crypto.subtle.verify(     {       name: "ECDSA",       hash: { name: "SHA-256" },     },     publicKey,     signature,     data   );   return isVerified; } async function signatureAndVerification() {   const message = "hello world";   // 生成椭圆曲线密钥对   const keyPair = await window.crypto.subtle.generateKey(     {       name: "ECDSA",       namedCurve: "P-256",     },     true,     ["sign", "verify"]   );   // 对消息进行数字签名   const signature = await signMessage(keyPair.privateKey, message);   // 验证数字签名   const isVerified = await verifySignature(keyPair.publicKey, message, signature);   console.log("原始消息:", message);   console.log("数字签名:", new Uint8Array(signature));   console.log("验证结果:", isVerified); } signatureAndVerification();




如何把密钥发给后端

前端通过 window.crypto.subtle.generateKey 生成的公钥可以通过以下步骤发送给后端:

  1. 从生成的密钥对中获取公钥,使用 exportKey 方法将其导出成 ArrayBuffer 格式。


const keyPair = await window.crypto.subtle.generateKey(   { name: "RSA-OAEP", modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: "SHA-256" },   true,   ["encrypt", "decrypt"] ); const publicKey = await window.crypto.subtle.exportKey(   "spki",   keyPair.publicKey );




  1. 将导出的 ArrayBuffer 转换为 Base64 编码的字符串格式,以便可以通过 HTTP 请求发送给后端。


const publicKeyBase64 = btoa(String.fromCharCode.apply(null, new Uint8Array(publicKey)));



  1. 将 Base64 编码的字符串作为请求参数发送到后端,后端可以将其解码并使用相应的加密算法进行加密操作。

  2. // 发送公钥给后端 fetch('/api/sendPublicKey', {  method: 'POST',  headers: {    'Content-Type': 'application/json',  },  body: JSON.stringify({ publicKey: publicKeyBase64 }), })


上面就是简单的一种演示,只要用 exportKey 拿到 Key,你想怎么发送就怎么发送。

摘要算法

async function generateHMAC(key, data) {  const encoder = new TextEncoder();  const encodedKey = encoder.encode(key);  const encodedData = encoder.encode(data);  const cryptoKey = await window.crypto.subtle.importKey(    "raw",    encodedKey,    {      name: "HMAC",      hash: "SHA-256"    },    false,    ["sign"]  );  const signature = await window.crypto.subtle.sign(    {      name: "HMAC",      hash: "SHA-256"    },    cryptoKey,    encodedData  );  return signature; } async function verifyHMAC(key, data, signature) {  const encoder = new TextEncoder();  const encodedKey = encoder.encode(key);  const encodedData = encoder.encode(data);  const cryptoKey = await window.crypto.subtle.importKey(    "raw",    encodedKey,    {      name: "HMAC",      hash: "SHA-256"    },    false,    ["verify"]  );  const result = await window.crypto.subtle.verify(    {      name: "HMAC",      hash: "SHA-256"    },    cryptoKey,    signature,    encodedData  );  return result; } async function hmacExample() {  const key = "my secret key";  const data = "Shavahn";    const signature = await generateHMAC(key, data);  console.log("HMAC 签名:", new Uint8Array(signature));  const isValid = await verifyHMAC(key, data, signature);  console.log("HMAC 签名是否有效:", isValid); } hmacExample();



主要用途

前端浏览器的 Crypto 技术可以用于以下主要用途:

1. 安全的数据传输

通过使用前端浏览器的 Crypto 技术,开发者可以对数据进行加密和解密,从而确保数据在传输过程中的安全性。例如,在使用 HTTPS 协议时,可以使用浏览器内置的加密算法对传输的数据进行加密,以保证数据的机密性和完整性。

2. 数字签名验证

通过使用前端浏览器的 Crypto 技术,可以对数据进行数字签名和验证,从而确保数据的完整性和真实性。例如,在电子商务中,可以使用数字签名技术对交易数据进行签名和验证,以保证交易数据的真实性和完整性。

3. 认证和授权

通过使用前端浏览器的 Crypto 技术,可以对用户进行认证和授权。例如,在使用 OAuth2 认证时,可以使用前端浏览器的 Crypto 技术生成安全的随机数,以保证授权码的安全性。

总结

前端浏览器的 Crypto 技术是实现安全的前端应用程序的关键技术之一。Web Crypto API 提供了多种密码学算法和函数,使得前端开发人员可以在浏览器中实现安全的数据传输、数字签名和验证等功能,同时确保数据的安全性和完整性。使用前端浏览器的 Crypto 技术可以使开发人员更轻松地实现密码学相关的功能,同时提高应用程序的安全性和保护用户数据的隐私。因此,开发人员应该了解和熟悉前端浏览器的 Crypto 技术,并在必要时使用它来保证应用程序的安全性。


免责声明:服务用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯本网站及相关权利人的合法权利。
IPv4 © 2005-2025 库目书 版权所有 | kumushu.com .All Rights Reserved
黑ICP备2022003236号-1