Primero necesitas saber lo siguiente:
Cifrado simétrico AES usando crypto-js en Vue: https://blog.csdn.net/qq_40323256/article/details/123688626
Cifrado asimétrico RSA usando jsencrypt en Vue: https://blog.csdn.net/qq_40323256/article/details/124006449
Generar herramienta en línea de pares de claves RSA: http://web.chacuo.net/netrsakeypair
Proceso de cifrado híbrido:
- El receptor crea un par de claves RSA,
- Envíe la clave pública RSA al remitente y conserve la clave privada RSA
- El remitente crea una clave AES, cifra el texto sin formato que se transmitirá y luego cifra la clave con la clave pública RSA,
- RSA clave pública cifrada clave AES + clave AES texto cifrado texto sin formato ---- enviado al destinatario a través de Internet ----> receptor
- El receptor descifra la clave cifrada con la clave privada RSA y luego descifra el texto cifrado de datos con la clave AES descifrada para obtener el texto sin formato.
Cliente:
<!--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>
Servidor:
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
resultado:
La clave pública y la clave privada anteriores son generadas por node-rsa. Si desea especificar manualmente la clave pública y la clave privada usted mismo, puede usar los siguientes métodos: (El código del cliente sigue siendo el mismo, solo el código del servidor debe ser cambió)
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
Nota: he intentado no mostrar directamente las claves públicas y privadas en el código, sino leer los archivos locales de claves públicas y privadas a través de fs.readFile() Aunque se puede leer, el cifrado y el descifrado fallan al final.
Coloque los archivos de clave pública y privada en la carpeta public/files, para que la ruta de lectura sea posible: fs.readFile('public/files/xxx.txt',(err,data)=>{})