vue+koa中使用aes和rsa混合加密

首先需要了解以下内容:

Vue中使用crypto-js进行AES对称加密:https://blog.csdn.net/qq_40323256/article/details/123688626

Vue中使用jsencrypt进行RSA非对称加密:https://blog.csdn.net/qq_40323256/article/details/124006449 

生成RSA密钥对在线工具:http://web.chacuo.net/netrsakeypair

混合加密流程:

  1. 接收方创建RSA秘钥对,
  2. 发送RSA公钥给发送方,自己保留RSA私钥
  3. 发送方创建AES密钥,加密待传送的明文,之后用RSA公钥加密该密钥,
  4. RSA公钥加密AES的密钥+AES密钥加密明文的密文----通过Internet发给---->接收方
  5. 接收方用RSA私钥解密加密的密钥,之后再用解密后的AES密钥解密数据密文,得到明文。

客户端:

<!--main-->
<template>
  <div>
    <el-button @click="test()">test</el-button>
  </div>
</template>
<script>
import { JSEncrypt } from "jsencrypt";
import CryptoJS from "crypto-js";
import axios from "axios";
export default {
  methods: {
    async test() {
      //待加密传输的data数据
      const data = {
        username: "李疆",
        password: 123,
      };
      console.log("aes加密前的data数据:", data);

      //aes密钥
      let key_aes = "385f33cb91484b04a177828829081ab7";
      console.log("aes密钥:", key_aes);

      //aes加密data数据
      const data_encrypted_by_aes = CryptoJS.AES.encrypt(
        JSON.stringify(data),
        CryptoJS.enc.Utf8.parse(key_aes),
        {
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7,
        }
      ).ciphertext.toString();
      console.log("aes加密后的data数据:", data_encrypted_by_aes);

      //从服务端获取公钥
      let { data: publicKey } = await axios.get("/api/test/publicKey");
      console.log("从服务端获取的rsa公钥:", publicKey);

      //rsa公钥加密aes密钥
      let encryptor = new JSEncrypt();
      encryptor.setPublicKey(publicKey);
      let aeskey_encrypted_by_rsa = encryptor.encrypt(key_aes);
      console.log("被rsa公钥加密后的aes密钥:", aeskey_encrypted_by_rsa);

      //发送aes加密后的data数据和被rsa公钥加密的aes密钥到服务端
      let result = await axios.post("/api/test/decryption", {
        data_encrypted_by_aes,
        aeskey_encrypted_by_rsa,
      });
      console.log("result:", result);
    },
  },
};
</script>

服务端:

const router = require('koa-router')()
const CryptoJS = require("crypto-js");
const NodeRSA = require('node-rsa');

router.prefix('/test')

router.get('/', (ctx, next) => {
    ctx.body = 'this is a users response!'
})

const key_rsa = new NodeRSA({ b: 1024 });//密钥长度1024位
key_rsa.setOptions({ encryptionScheme: 'pkcs1' });//指定加密格式.不改格式得话可能会报错
router.get('/publicKey', async (ctx, next) => {
    let publicKey = key_rsa.exportKey('public');//生成公钥
    // let privateKey = key_rsa.exportKey('private');//生成私钥
    ctx.body = publicKey;
});
router.post('/decryption', async (ctx, next) => {
    let { data_encrypted_by_aes, aeskey_encrypted_by_rsa, } = ctx.request.body;

    console.log("aes加密后的data数据:", data_encrypted_by_aes)
    console.log("被rsa公钥加密的aes密钥:", aeskey_encrypted_by_rsa)

    //rsa私钥解密出aes密钥
    const aeskey_decrypted_by_rsa = key_rsa.decrypt(aeskey_encrypted_by_rsa, 'utf8');
    console.log('被rsa私钥解密出的aes密钥: ', aeskey_decrypted_by_rsa);

    // aes密钥解密出data数据
    let data_decrypted_by_aes = JSON.parse(CryptoJS.enc.Utf8.stringify(CryptoJS.AES.decrypt(
        CryptoJS.format.Hex.parse(data_encrypted_by_aes),
        CryptoJS.enc.Utf8.parse(aeskey_decrypted_by_rsa),
        {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        }
    )))
    console.log('被aes密钥解密出的data数据:', data_decrypted_by_aes);

    ctx.body = { message: "success" };

});

module.exports = router

结果:

上面的公钥和私钥是通过node-rsa生成的,如果想自己手动指定公钥和私钥,可通过如下方式:(客户端代码不变,只需要改服务端代码)

const router = require('koa-router')()
const CryptoJS = require("crypto-js");
const NodeRSA = require('node-rsa');

router.prefix('/test')

router.get('/', (ctx, next) => {
    ctx.body = 'this is a users response!'
})

router.get('/publicKey', async (ctx, next) => {
    let publicKey = `-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDARcNxlvPXZQSup9yPV6iVzqMI
    eBr2Rztd4zxYUCwL2pqaig3ZP17eFpzfiI+aBf2F4qp/QHPMVnEQmx33/fGlssvc
    cqplP7gvk7BKporUWtnyqYKqy/fAE07c/Yxpe5WZoMo2pRyaBDMLMZ49MpfAzHXS
    pTzUY9W4F49C0Y8SPQIDAQAB
    -----END PUBLIC KEY-----`
    ctx.body = publicKey;
});
router.post('/decryption', async (ctx, next) => {
    let { data_encrypted_by_aes, aeskey_encrypted_by_rsa, } = ctx.request.body;

    console.log("aes加密后的data数据:", data_encrypted_by_aes)
    console.log("被rsa公钥加密的aes密钥:", aeskey_encrypted_by_rsa)

    let privateKey = `-----BEGIN PRIVATE KEY-----
    MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAMBFw3GW89dlBK6n
    3I9XqJXOowh4GvZHO13jPFhQLAvampqKDdk/Xt4WnN+Ij5oF/YXiqn9Ac8xWcRCb
    Hff98aWyy9xyqmU/uC+TsEqmitRa2fKpgqrL98ATTtz9jGl7lZmgyjalHJoEMwsx
    nj0yl8DMddKlPNRj1bgXj0LRjxI9AgMBAAECgYEAsjd34y+yMTKXVnSNQehUgRcZ
    kt4Qz7pS0sGvy4P0b8BekWPpVjcg7eYz3hYsVO28gn8I3g6Vxw9Qmb3N13HwqrPt
    1z6pGkr54FtgsxPDaS0Cu86gt9G+MfAHMbYHtCd3VEhfXmj17/NeV/nFUG0mlgGZ
    bZY0wLlDNYX6t+clYQECQQDphC6/5xhdWr1yelNO5fybt/1p9Cp5q3nRR1NjEwCY
    77WE1VMwbdSYkj9whSL9EcnEGFL6/PgcWjkXuY4Jpg9hAkEA0sj79IVYt7L0xnTO
    tNg6RBoF9vnt9T0HUAqU0Q9YHbV+SzEMUOKepMW5XwSlPomeOpOQEYot7SmXuUL5
    aBj8XQJBAKNj+dIMwN+RPj17mg76nWXXt1kLnyzC7tmgLpiEE0bvcvMe0LZyIu8e
    ZYU1ouWwLJ0o5+b2WiR8fLY8/0WBDAECQQCa7mXbfiQOqjgmovbIkGKLagFWXrBc
    YKY+W/i0ja278IpK5FtkHJ51CGxPfg+jnu2xqoLrkYBeYQMHhkXiEPN1AkEAmjlL
    3AWqcl6I0vsvt1cK4XiQmez8L6JomMddjF9vi96mNy8Be8+7OCxWv+aZ2P8AhZKD
    WrHvhaHSs389XzS3HQ==
    -----END PRIVATE KEY-----
    `
    const key_rsa = new NodeRSA(privateKey);
    key_rsa.setOptions({ encryptionScheme: 'pkcs1' }); // 因为jsencrypt自身使用的是pkcs1加密方案, nodejs需要修改成pkcs1。
    const aeskey_decrypted_by_rsa = key_rsa.decrypt(aeskey_encrypted_by_rsa, 'utf8');
    console.log('被rsa私钥解密出的aes密钥: ', aeskey_decrypted_by_rsa);

    let data_decrypted_by_aes = JSON.parse(CryptoJS.enc.Utf8.stringify(CryptoJS.AES.decrypt(
        CryptoJS.format.Hex.parse(data_encrypted_by_aes),
        CryptoJS.enc.Utf8.parse(aeskey_decrypted_by_rsa),
        {
            mode: CryptoJS.mode.ECB,
            padding: CryptoJS.pad.Pkcs7
        }
    )))
    console.log('被aes密钥解密出的data数据:', data_decrypted_by_aes);

    ctx.body = { message: "success" };
});

module.exports = router

注意:我尝试过代码中不直接展示公钥和私钥,而是通过fs.readFile()的方式读取本地的公钥和私钥文件,虽然可以读取,但是最后加密解密失败。

把公钥私钥文件放到public/files文件夹中,这样读取路径是可以的:fs.readFile('public/files/xxx.txt',(err,data)=>{})

猜你喜欢

转载自blog.csdn.net/qq_40323256/article/details/124017789