基于RSA+AES的通讯加解密-前端部分-js代码

本文介绍了一种结合RSA和AES算法实现前后端安全通信的方法。前端生成随机AES密钥并使用RSA公钥加密,对数据进行AES加密后传递给后端。后端使用RSA私钥解密获取AES密钥,完成数据解密,并使用相同密钥加密返回的数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RSA+AES前后端通讯加解密-前端部分

  1. 流程:
  • 前端随机生成AES秘钥,使用RSA公钥对AES秘钥进行加密得到密钥
  • 前端使用AES秘钥对数据进行加密得到密文
  • 将这两者包装在一个对象里面传给后台
  • 后台使用RSA私钥解密密钥得到AES秘钥,使用AES秘钥对密文进行解密得到数据
  • 后台使用AES秘钥对数据进行加密返回给前端,前端使用AES秘钥解密
  1. 注意点:
  • 前后端的加解密流程要一致,要对照每一步进行操作
  • AES加密是对字符串进行加密,不能对对象进行加密,因此想要加密对象就要先转换成JSON字符(尝试过将对象直接加密,解密后得到的是一个空对象
  • RSA公私钥可以用工具随机生成,每一对公私钥都是对应的且唯一对应的
  • AES和RSA加密的方式都是可选的,要与后台确认好加解密采用的是同一种方法
  1. 加解密函数与随机生成AES秘钥的代码:
// 加密函数工具包 内有RSA加解密 AES加解密 指定位数字符串生成函数
import CryptoJS from "crypto-js";
import JSEncrypt from 'jsencrypt'

/** AES加密 */
// aesPassword是用于加密的16位随机字符串(秘钥) word是公钥
export const encryptAES=(aesPassword, word)=>{ 
    // 将随机字符串从UTF8编码解析出原始字符串??
    const key = CryptoJS.enc.Utf8.parse(aesPassword);
    // 将公钥从UTF8编码解析出原始字符串??
    const srcs = CryptoJS.enc.Utf8.parse(word);
    // 获得已使用AES加密的公钥
    const encrypted = CryptoJS.AES.encrypt(srcs, key, { mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
    // 将密文转化为字符串 并返回
    return encrypted.toString();// base64结果
    // return encrypted.ciphertext.toString()// 二进制结果
}

/** AES解密 */
// aesPassword是用于解密的字符串(秘钥) 与前文用于加密的字符串是同一个 word是密文 对方使用同样的秘钥加密过
export const decryptAES=(aesPassword, word)=>{ 
    // 将解密字符串转化为原始字符串??
    const key = CryptoJS.enc.Utf8.parse(aesPassword);
    // 首先将密文 用秘钥进行AES解密 获得明文 此信息即为目的数据
    const decrypt = CryptoJS.AES.decrypt(word, key, { mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
    // 将明文从原始字符串转化为UTF8编码格式 再转为为字符串并返回
    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();
}

/* 随机生成密钥 */
// len为目的秘钥长度
export const initKey=(len)=>{ 
    len = len || 32;
    let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz23456789~!@#$%^&*()_+}{":?><';    /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
    // maxPos是$chars的长度
    let  maxPos = $chars.length;
    let pwd = '';
    let i=0;
    for (i = 0; i < len; i++) { 
        // chartAt方法通过index从字符串中获取指定字符
        // 随机数*长度向下取整作为取字符的index
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

// RSA公钥加密
export const encryptRSA=(PUBLIC_KEY,word)=>{
    // new一个JSEncrypt对象
    const encrypt = new JSEncrypt();
    // 设置公钥 
    encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');
    // 公钥加密 并返回
    return encrypt.encrypt(word);
}

// RSA私钥解密
export const decryptRSA=(PRIVATE_KEY,word)=>{
    // new一个JSEncrypt对象
    const decrypt = new JSEncrypt();
    // 设置私钥
    decrypt.setPrivateKey('-----BEGIN RSA PRIVATE KEY-----'+PRIVATE_KEY+'-----END RSA PRIVATE KEY-----');
    // 私钥解密 并返回
    return decrypt.decrypt(word); 
}
### 前端 RSA AES 组合加密实现 为了实现在前端使用RSAAES组合加密,通常的做法是在客户端先利用随机生成的AES密钥对实际传输的数据进行加密。接着,再用接收方的公钥通过RSA算法对该AES密钥本身做一层额外保护。这种方式既发挥了AES加解密速度快的优势,又借助了RSA非对称加密的安全特性来安全传递会话密钥。 下面是一个基于JavaScript环境下的简单示例代码片段: #### 1. 准备工作 确保项目中有必要的库支持,比如`crypto-js`用于AES操作以及`jsrsasign`负责处理RSA部分。 ```html <script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/8.0.23/jsrsasign-all-min.js"></script> <script src="https://cdn.jsdelivr.net/npm/crypto-js@4.0.0/core.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/crypto-js@4.0.0/aes.min.js"></script> ``` #### 2. 加密逻辑实现 ```javascript // 获取或定义RSA公钥字符串形式 const publicKey = `--BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7mZuLzjWkYyXwvKUcN+oHhOeE ... -----END PUBLIC KEY-----`; function generateRandomAesKey() { return CryptoJS.lib.WordArray.random(32); // 生成256位(32字节)的随机数作为AES密钥 } async function rsaEncrypt(publicKeyStr, dataToBeEncrypted) { const cipher = new jsrsasign.KJUR.crypto.Cipher(); await cipher.init({ alg: 'RSA-OAEP', prov: 'native' }, publicKeyStr); let encryptedDataHex = cipher.encrypt(dataToBeEncrypted.toString()); return hex2b64(encryptedDataHex); // 将十六进制转换成Base64编码返回 } function aesEncrypt(aesKey, plaintext) { var iv = CryptoJS.lib.WordArray.random(16); // 初始化向量IV同样重要不可忽略 var ciphertext = CryptoJS.AES.encrypt(plaintext, aesKey, { iv }); return JSON.stringify({ ct: ciphertext.toString(), iv: iv.toString() }); } ``` 上述函数实现了如下功能: - 使用给定长度的随机值创建一个新的AES密钥[^1]。 - 对此新产生的AES密钥应用RSA公钥执行加密动作[^4]。 - 利用刚才生成并保存下来的临时AES密钥完成目标消息体的实际加密过程[^3]。 #### 3. 发送请求前准备 当准备好以上组件之后,在发起HTTP请求之前,应该按照以下顺序打包待发送的信息: ```javascript (async () => { try { const message = "This is a secret message"; // Step A: Generate an ephemeral AES key for this session. const aesSessionKey = generateRandomAesKey(); // Step B: Encrypt the actual payload using generated AES key. const encryptedMessage = aesEncrypt(aesSessionKey, message); // Step C: Securely wrap up our temporary AES key via recipient's public RSA key. const wrappedAesKey = await rsaEncrypt(publicKey, aesSessionKey); console.log(`Sending following structure to server:`); console.dir({ encMsg: encryptedMessage, wrpAesKey: wrappedAesKey }); /* Here you would typically send these two pieces of information (encMsg & wrpAesKey) as part of your AJAX call or fetch request body */ } catch(error){ console.error('Encryption failed:', error); } })(); ``` 这段脚本展示了完整的流程:从生成一次性使用的AES密钥到最终形成可用于网络传输的消息结构。注意这里仅提供了概念性的演示框架;真实场景下还需要考虑更多细节如错误处理机制、兼容性问题等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值