// 编码 const base64Str = window.btoa('Hello World!'); console.log(base64Str); // SGVsbG8gV29ybGQh // 解码 const str = window.atob(base64Str); console.log(str); // Hello World!当然,我们也可以使用base64插件。
pnpm install --save js-base64 <script setup lang="ts"> import { Base64 } from 'js-base64'; // 堆代码 duidaima.com // 编码 const encode = Base64.encode('Hello World!'); console.log(encode); // 解码 const decode = Base64.decode(encode); console.log(decode); </script>二.哈希算法
import CryptoJS from "crypto-js"; // MD5 const hash = CryptoJS.MD5('Message'); // SHA-1 const hash = CryptoJS.SHA1('Message'); // SHA-256 const hash = CryptoJS.SHA256('Message'); // SHA-512 const hash = CryptoJS.SHA512('Message');三.对称加密(AES/DES)
ECB是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。CBC是一种循环模式,前一个分组的密文和当前分组的明文异或或操作后再加密,这样做的目的是增强破解难度。
参数Mode为DES/AES的工作方式。参数padding为填充模式,如果加密后密文长度如果达不到指定整数倍(8个字节、16个字节),填充对应字符,padding的赋值固定为CryptoJS.pad.Pkcs7即可。
import CryptoJS from "crypto-js"; //秘钥 const secretKey = CryptoJS.enc.Utf8.parse("12345678ABCDEFGH"); //16位 // iv偏移量 const iv = CryptoJS.enc.Utf8.parse("ABCDEFGH12345678"); // 需要加密的参数,数据类型为bytes const secretMessage = "Hello World!"; // 加密 const encrypt = CryptoJS.AES.encrypt(secretMessage, secretKey, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).tostring(); console.log(encrypt); //解密 const decrypt = CryptoJS.AES.decrypt(encrypt, secretKey, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8); console.log(decrypt);
npm install jsencrypt import JSEncrypt from 'jsencrypt' // RSA加密 // 创建加密对象实例 const encryptor = new JSEncrypt(); //之前ssl生成的公钥,复制的时候要小心不要有空格 const pubKey = '-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1QQRl0HlrVv6kGqhgonD6A9SU6ZJpnEN+Q0blT/ue6Ndt97WRfxtSAs0QoquTreaDtfC4RRX4o+CU6BTuHLUm+eSvxZS9TzbwoYZq7ObbQAZAY+SYDgAA5PHf1wNN20dGMFFgVS/y0ZWvv1UNa2laEz0I8Vmr5ZlzIn88GkmSiQIDAQAB-----END PUBLIC KEY-----'; //设置公钥 encryptor.setPublicKey(pubKey); // 对内容进行加密 const encrypted = encryptor.encrypt('要加密的内容') // RSA解密 //创建解密对象实例 const decrypt = new JSEncrypt(); //之前ssl生成的秘钥 const priKey = '-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQC1QQRl0HlrVv6kGqhgonD6A9SU6ZJpnEN+Q0blT/ue6Ndt97WRfxtSAs0QoquTreaDtfC4RRX4o+CU6BTuHLUm+eSvxZS9TzbwoYZq7ObbQAZAY+SYDgAA5PHf1wNN20dGMFFgVS/y0ZWvv1UNa2laEz0I8Vmr5ZlzIn88GkmSiQIDAQABAoGBAKYDKP4AFlXkVlMEP5hS8FtuSrUhwgKNJ5xsDnFV8sc3yKlmKp1a6DETc7N66t/Wdb3JVPPSAy+7GaYJc7IsBRZgVqhrjiYiTO3ZvJv3nwAT5snCoZrDqlFzNhR8zvUiyAfGD1pExBKLZKNH826dpfoKD2fYlBVOjz6i6dTKBvCJAkEA/GtL6q1JgGhGLOUenFveqOHJKUydBAk/3jLZksQqIaVxoB+jRQNOZjeSO9er0fxgI2kh0NnfXEvH+v326WxjBwJBALfTRar040v71GJq1m8eFxADIiPDNh5JD2yb71FtYzH9J5/d8SUHI/CUFoROOhxr3DpagmrnTn28H0088vubKe8CQDKMOhOwx/tS5lqvN0YQj7I6JNKEaR0ZzRRuEmv1pIpAW1S5gTScyOJnVn1tXxcZ9xagQwlT2ArfkhiNKxjrf5kCQAwBSDN5+r4jnCMxRv/Kv0bUbY5YWVhw/QjixiZTNn81QTk3jWAVr0su4KmTUkg44xEMiCfjI0Ui3Ah3SocUAxECQAmHCjy8WPjhJN8y0MXSX05OyPTtysrdFzm1pwZNm/tWnhW7GvYQpvE/iAcNrNNb5k17fCImJLH5gbdvJJmCWRk=-----END RSA PRIVATE KEY----'; //设置秘钥 decrypt.setPrivateKey(priKey); //解密之前拿公钥加密的内容 const uncrypted = decrypt.decrypt(encrypted)RSA加解密可以应用在用户注册或登录的时候,用公钥对密码进行加密,再去传给后台,后台用私钥对加密的内容进行解密,然后进行密码校验或者保存到数据库。
pnpm install js-sha256 import { sha256 } from 'js-sha256' import { sha256 } from 'js-sha256'; const generateSalt = () => { const randomBytes = new Uint8Array(16); crypto.getRandomValues(randomBytes); return Array.from(randomBytes, (byte) => byte.toString(16).padStart(2, '0') ).join(''); }; // 盐值 const salt = generateSalt(); // 假如一个密码 const password = 'admin123456'; // 盐值和密码进行组合 const saltedPassword = salt + password; // 哈希计算 const hash = sha256(saltedPassword); console.log(hash);六.Web Cryptography API
// fix safari crypto namespace if (window.crypto && !window.crypto.subtle && window.crypto.webkitSubtle) { window.crypto.subtle = window.crypto.webkitSubtle; } /** * Detect Web Cryptography API * @return {Boolean} true, if success */ function isWebCryptoAPISupported() { return 'crypto' in window && 'subtle' in window.crypto; }getRandomValues 同步方法,获取随机数,因为性能要求,这是一个伪随机数生成器(PRNG)。浏览器也通过添加系统级别的种子来提高熵(不确定性的量度),来满足密码学使用要求。
const size = 10; const array = new Uint8Array(size); window.crypto.getRandomValues(array); // print values to console for (let i=0; i!==array.length; ++i) { console.log(array[i]); }SubtleCrypto接口:
// 生成公钥和私钥 const keyPair = await window.crypto.subtle.generateKey( { name: "RSA-OAEP", // 使用RSA-OAEP算法 modulusLength: 2048, // 密钥长度为2048位 publicExponent: new Uint8Array([1, 0, 1]), // 公共指数为65537 hash: "SHA-256" // 哈希算法为SHA-256 }, true, // 生成可导出的密钥对 ["encrypt", "decrypt"] // 可用于加密和解密操作 ); keyPair.then(function(result) { // 处理生成的密钥对 console.log(result.publicKey); // 打印公钥 console.log(result.privateKey); // 打印私钥 }).catch(function(error) { // 处理错误 console.error(error); }); // 加密 async function encryptByRSA(message, publicKey) { // 将消息编码为Uint8Array格式 const encodedMessage = new TextEncoder().encode(message); // 使用Web Crypto API的encrypt()方法对消息进行加密 const encrypted = await window.crypto.subtle.encrypt( { name: "RSA-OAEP" // 加密算法为RSA-OAEP }, publicKey, // 使用传入的公钥进行加密 encodedMessage // 要加密的消息 ); // 将加密后的数据转换为Base64编码的字符串 return window.btoa(String.fromCharCode(...new Uint8Array(encrypted))); } // 解密 使用RSA私钥对密文进行解密 async function decryptByRSA(ciphertext, privateKey) { // 将Base64编码的密文解码为Uint8Array格式 const decodedCiphertext = Uint8Array.from( atob(ciphertext), c => c.charCodeAt(0) ); // 使用Web Crypto API的decrypt()方法对密文进行解密 const decrypted = await window.crypto.subtle.decrypt( { name: "RSA-OAEP" // 解密算法为RSA-OAEP }, privateKey, // 使用传入的私钥进行解密 decodedCiphertext // 要解密的密文 ); // 将解密后的数据转换为字符串 return new TextDecoder().decode(decrypted); }