你开发的聊天软件消息加密了吗

您所在的位置:网站首页 rsa算法是对称密钥密码算法吗 你开发的聊天软件消息加密了吗

你开发的聊天软件消息加密了吗

2023-06-13 06:52| 来源: 网络整理| 查看: 265

前言

最近发现一些成熟的 IM 服务消息传输都是经过加密进行传输的,所以使用 RSA 加密对此进行一次尝试

RSA 简介

RSA 是一种非对称加密算法,它由三位密码学家 Ron Rivest、Adi Shamir 和 Leonard Adleman 在 1977 年共同提出,以他们姓氏的首字母命名。RSA 算法是目前广泛使用的加密算法之一。 RSA 算法基于两个数学问题的难解性:大素数分解和求模幂运算的逆运算。它的核心思想是使用一对相关的密钥,一个公钥和一个私钥,其中公钥用于加密数据,私钥用于解密数据。公钥可以自由发布给任何人,而私钥则必须保密。

RSA 算法的安全性基于大数分解的困难性。目前没有已知的有效算法可以在合理的时间内分解大的复合数,所以 RSA 算法在实际应用中被广泛用于数据加密、数字签名和密钥交换等领域。

代码实现思路

00001.png

阅读须知 本文使用 vite-vue,以及 node 的 koa 开发 本文使用 RSA 对数据进行加密 本文 web 端使用jsencrypt生成公钥和私钥,后端使用node-rsa生成 项目搭建 创建后端服务 初始化目录并安装依赖 npm init pnpm i koa pnpm i ts-node-dev 创建 index.ts 编写 server 测试 const Koa = require("koa"); const app = new Koa(); app.use(async (ctx) => { ctx.body = "Hello World"; }); app.listen(3000); 使用 vite 初始化一个 vue 项目 pnpm create vite pnpm install --save-dev @arco-design/web-vue 客户端和服务端密钥的生成 客户端 创建密钥 import JSEncrypt from "jsencrypt"; export const initConfigRSA = async () => { const crypt = new JSEncrypt(); crypt.getKey(); const privateKey = crypt.getPrivateKey(); const publicKey = crypt.getPublicKey(); return { privateKey, publicKey }; }; 加密数据 // 将字符串按照指定长度分割成数组 const splitString = (str: string, leng = 10) => { const list = []; let index = 0; while (index < str.length) { list.push(str.slice(index, (index += leng))); } return list; }; export const encryption = (options: Object, key: string) => { //先将发往服务端的数据转成字符串 const str = JSON.stringify(options); const encrypt = new JSEncrypt(); //设置加密使用的公钥 encrypt.setPublicKey(key); let data = ""; //由于加密的数据长度不能超过密钥的长度,所以我们要对加密的数据进行分段加密 const list = splitString(str); for (const iterator of list) { const res = encrypt.encrypt(iterator); console.log(res); if (res) { data = data + res; } } console.log(data); //将字符串数据 const encoder = new TextEncoder(); const res = encoder.encode(data); return res; }; 解密数据 export const decryption = (str: string, key: string) => { const encrypt = new JSEncrypt(); encrypt.setPrivateKey(key); let data = ""; const list = str.split("="); for (const iterator of list) { const res = encrypt.decrypt(iterator); if (res) { data = data + res; } } return data || ""; }; 实现效果 78115ec2c10fba9dcf9a4ce4e4b7427.png 服务端 创建密钥 import NodeRSA from "node-rsa"; export const initConfigRSA = () => { const key = new NodeRSA({ b: 1024 }); //此处使用`pkcs1`的原因是因为jsencrypt是使用pkcs1标准生成密钥的 key.setOptions({ encryptionScheme: "pkcs1" }); const privateKey = key.exportKey("pkcs8-private-pem"); const publicKey = key.exportKey("pkcs8-public-pem"); return { privateKey, publicKey }; }; 加密数据

和客户端一样的逻辑

const splitString = (str: string, leng = 10) => { const list: string[] = []; let index = 0; while (index < str.length) { list.push(str.slice(index, (index += leng))); } return list; }; export const encryption = (options: Object, key: string) => { const str = JSON.stringify(options); const encrypt = new NodeRSA(key, "pkcs8-public-pem"); encrypt.setOptions({ encryptionScheme: "pkcs1" }); let data = ""; const list = splitString(str); for (const iterator of list) { const res = encrypt.encrypt(iterator, "base64"); console.log(res); if (res) { data = data + res; } } return data || ""; }; 解密数据 export const decryption = (str: string, key: string) => { const encrypt = new NodeRSA(key, "pkcs8-private-pem"); encrypt.setOptions({ encryptionScheme: "pkcs1" }); let data = ""; const list = str.split("="); for (const iterator of list) { const res = encrypt.decrypt(iterator + "=", "utf8"); if (res) { data = data + res; } } if (data) { return JSON.parse(data); } return ""; }; 实现效果

3802a6ee97ba63f49b5ffeecffa81e4.png

server 中创建 ws 服务 import http from "http"; import Koa from "koa"; import chalk from "chalk"; import WebSocket from "ws"; import { initConfigRSA } from "./configRSA"; const app = new Koa(); const useKeys = initConfigRSA(); console.log(useKeys); let users: Map = new Map(); const server = http.createServer(app.callback()); const ws = new WebSocket.Server({ server, }); server.listen(3000); console.log("[" + chalk.green("http") + "]", "http://127.0.0.1:3000"); 服务端 WS 监听 // 监听到客户端连接事件后将服务的公钥发往客户端 ws.on("connection", (client) => { console.log("客户端已连接"); }); 交换公钥

在客户端连接成功后将服务端公钥发送到客户端,后续中客户端发往服务端的数据将使用此公钥加密

client.send( Buffer.from( JSON.stringify({ type: "server", data: { server: useKeys.publicKey } }) ) );

效果如下

41ea3ec10e9501d9e9ef2ab9e379eca.png

87bd6df964a60a1828da1d13d0b174d.png

消息交换 客户端向服务端 客户端 const msg = encryption(data, serverPublicKey.value); client.send(msg); 服务端 const message: { type: string; data: any } = decryption( req.toString("utf8"), useKeys.privateKey ); 效果如下

1686540996385.png

服务端向客户端 服务端 // 获取用户信息 const user = users.get(client.userId); // 通过用户的公钥加密 const data = encryption(message, user!.publicKey); 客户端 //先将buffer解码 const decoder = new TextDecoder(); const data = decoder.decode(res); //通过自己的私钥解密服务端发来的数据 const message = JSON.parse(decryption(data, useKeys.privateKey!));

3.效果如下

1686541060528.png

参考文档 TextEncoder developer.mozilla.org/en-US/docs/… jsencrypt和node-rsa实现参考 stackoverflow.com/questions/7… stackoverflow.com/questions/3…


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3