JavaScript + GO 通过 AES + RSA 进行数据加解密

浏览器端搞些小儿科的加密,就好比在黑暗夜空中,点缀了几颗星星,告诉黑客「这里有宝贵信息,快来翻牌」

a15b7433eb2b8f5ec01caa99dceb59e8.png

浏览器端的加密,都是相对安全的。

它的具体安危,取决于里面存在的信息价值,是否值得破解者出手一试。

就跟那个经典的笑话一样:

某个客户自己开发了一套软件,并买了一个防破解插件,让大牛测试破解难度。

三天后大牛郁闷地说这还挺难搞的,居然花了 3 天。

仔细一看原来是把人家的防破解插件给破了……

一、信息对齐

其实 JavaScript + Go 的加解密,真实代码调用很简单。

我和服务端小伙伴对着网上资料,库库一顿操作就搞定了。

d6d14180dc01eaa35d88d1d805df8cfc.png

所以在进入代码环节之前,我们先对齐同步一些基本信息,避免其他想了解这块知识点的小伙伴,捋不清里面逻辑。

1.1 什么是加解密

所谓「加密」,就是将你的信息,通过「某种处理」,让它变成不可读,被保护不被非法获取。

而「解密」,就是将处理后的信息,再转换成正常人能读懂的信息。

举个栗子,你要去拿货,对方来了一句「天王盖地虎」。

你是不是要接话,来表明你的身份?

b634f23a8dcb6f610960c9d8f343f592.png

“对暗号”,其实就是一种处理信息的方式,你只有回答出对方的问题,才能进一步操作。

1.2 为什么要数据加密

为了「安全」。

为什么安全要括起来,因为没有绝对的安全。

在浏览器端做数据加解密,只能保证:

  1. 传输的数据是经过加密或者编码的,即使有人通过抓包软件抓取数据,也看不懂或者比较难解开

  2. 确保数据没有经过篡改,确认发送者的身份

注意!以上 2 点只能防抓包,不防注入。

意思就是对方通过 JavaScript 脚本注入,替换你原先写的代码。

6856717ad4f38b46c0a5602bef130f9e.png

这样就可以在你加密信息之前,获取到原信息。

1.3 对称加密

所谓「对称加密」,意思就是大家拿到同一把钥匙,对传递的数据进行加解密。

举个栗子,对称加密就像你和朋友买了一个保险柜并配了 2 把一样的钥匙。

每次你找 ta 聊天,你把信写好,丢到保险柜,把保险柜扔给对方。

然后对方拿一样的钥匙,就可以开保险柜,并把他的信也丢到里面仍回给你。

再举个栗子,高中同学 A 和 B 谈恋爱了,但是他们纸条不能直接写情书呀,要不然被发现就哦豁了。

所以他们想了个法子,写纸条的时候,只写数字,比如 108-1,意思就是找某本书的 108 页第 1 个字。

fa59c934a39c995058e349f30f3cf54c.png

看,他们的钥匙,就是相同的书,这样信息就等同了,对称了。

常见的对称加密算法:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6 和 AES。

1.4 非对称加密

所谓「非对称加密」,就是 A 生成一对密钥,将公钥给别人,然后私钥自己藏好,别人通过公钥加密信息给 A,A 拿自己的私钥解密。

举个栗子,就是甲方是养蛊的,ta 有一对子母蛊。

甲方会把子蛊给乙方,母蛊留给自己。

这样哪怕子蛊丢了,别人拿子蛊传递信息,也只有甲方才能通过母蛊获取。

这种情况只有甲方才能破解信息,别人都没法理解不同人拿子蛊传递的信息。

7703d718ca84a67213189d6ad9344717.png

所以非对称加密可以用在松鼠党上:我可不管谁拿了子蛊,只要传递信息给我,我就都存起来。

对称加密算法的运行速度比非对称加密算法快,所以需要加密大量的数据时,建议采用对称加密算法,提升加解密速度。

常见的非对称加密算法:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用)

1.5 哈希(Hash)算法

所谓哈希(Hash)算法,其实就是将信息做一个不可逆的转换,然后将信息存储起来。

举个栗子,小明同学将自己的密码,通过哈希(Hash)算法,存到了数据库里。

这样别人监听了小明登录账号的接口,也没法获取到里面的内容。

又或者别人看到了数据库,也不知道小明同学记录的原始密码是什么。

哈希(Hash)算法中,MD5 因为计算机算力提升,可以快速找到一个 MD5 的值对应的原文,所以大家由 MD5 的使用变成了 SHA-256 的使用,提升了加密的安全性。

dd72e0c7898068455b80255803d95ddf.png

当然,如果小伙伴们的密码比较简单,例如 123456 或者 666666 这种,被破解的还是大有可能的,可以在线试试 https://tool.oschina.net/encrypt?type=2

常见的哈希算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1

1.6 数据加密算法的选择

在上面中,我们知道加密算法,大致分为「对称加密」和「非对称加密」以及「哈希(Hash)算法」这 3 种类型。

其中哈希(Hash)算法在对接中不可用了,因为它一般用作存储,不解出来。

而简单的对称加密和非对称加密,可能又过不了安全审查。

所以再三考虑下,我们采用 AES + RSA(对称加密 + 非对称加密)这种加密方式,提高数据传输的安全性。

二、RSA + AES

RSA + AES 的方案,我们采用这种形式:

  1. 服务端生成一堆 RSA 密钥,其中私钥自己保存,公钥下发给浏览器端

  2. 浏览器端通过随机函数,生成 AES 加密需要的 key(下面简称 AES key)

  3. 浏览器端通过 AES 和步骤 2 生成的 key,对要传输的数据进行加密,通过接口的 body 传递

  4. 浏览器端通过 RSA,对自己生成的 AES key 进行加密,通过接口的 header 传递

  5. 服务端拿到数据后,先通过 RSA 解密 header,获取到 AES key,再通过 AES,解密出 body 的数据

777973ad568b47afe18d3ac9ef9e1540.png

2.1 RSA 加解密

这一块的困难点在于 Go,因为 JavaScript 更多用的是一个库,即 jsencrypt

前端的 RSA 加密,是:

  1. 通过 jsencrypt,设置公钥

  2. 加密信息,生成 base64 数据并调用接口,传递给服务端

代码如下:

import JSEncrypt from 'jsencrypt';const encryptor = new JSEncrypt();/*** @name RSA-设置公钥* @param val 公钥*/
export const setPublicKey = (val: string) => {encryptor.setPublicKey(val);
}/*** @name RSA-加密* @param data 待加密数据* @returns {PromiseLike<ArrayBuffer>} 返回加密字符串*/
export const rsaEncrypt = (data: string) => {return encryptor.encrypt(data) || '';
}

服务端的 RSA 解密,是:

  1. 先解密 base64

  2. 再通过 RSA 解密

Go 的代码可参考:

  • 《CSDN - 在vue、golang搭建的前后端系统中使用jsencrypt包实现RSA加解密功能》https://blog.csdn.net/sinat_26553595/article/details/122411287

  • 《语言中文网 - 前后端交互,密码加密,RSA 实现前端 js 加密,后端 go 解密》https://studygolang.com/articles/35387

因为 Go 这边的库可能比较原始,所以如果碰到问题的话,大概率可能是公私钥的生成有问题,它需要按照最原始的标准格式来生成。

2.2 AES 加解密

对这一块确实没啥经验,网上说的文章,要么单独讲 JavaScript 的,要么单独讲 Go 的,整个人看完都懵圈。

好在网上大佬也确实给力,我跟服务端大佬合计了下,将一些点给撇掉了,直接采用:

  • 《思否 - Golang 实现与 crypto-js 一致的 AES 简单加解密》https://segmentfault.com/a/1190000043754783

实际开发中使用 AES 加密解密需要注意的地方:

  • 服务端和我们客户端必须使用一样的密钥和初始向量 IV

  • 服务端和我们客户端必须使用一样的加密模式

  • 服务端和我们客户端必须使用一样的 Padding 模式

首先,上面说这些可能有所信息误导,所以咱们直接看前端通过 JavaScript 生成 AES key 及加解密方法:

// 为什么不直接用 window.crypto,因为这个库做了兼容,可以看 https://github.com/brix/crypto-js/blob/4dcaa7afd08f48cd285463b8f9499cdb242605fa/src/core.js#L13
import CryptoJS from 'crypto-js';/*** @name AESKey* @description 生成 AES Key* @return 随机生成 16 位的 AES Key*/
export const createAesKey = () => {const expect = 16;let str = Math.random().toString(36).substr(2);while (str.length < expect) {str += Math.random().toString(36).substr(2);}str = str.substr(0, 16);return str;
}/*** @name AES-加密* @param raw 待加密字段* @param AESKey AES Key* @return {string} 返回加密字段*/
export const aesEncrypt = (raw: any, AESKey: string) => {const cypherKey = CryptoJS.enc.Utf8.parse(AESKey);CryptoJS.pad.ZeroPadding.pad(cypherKey, 4);const iv = CryptoJS.SHA256(AESKey).toString();const cfg = { iv: CryptoJS.enc.Utf8.parse(iv) };return CryptoJS.AES.encrypt(raw, cypherKey, cfg).toString();
}/*** @name AES-解密* @param raw 待解密数据* @param AESKey 解密 key* @returns {string} 返回解密字符串*/
export const aesDecrypt = (raw: string, AESKey: string) => {const cypherKey = CryptoJS.enc.Utf8.parse(AESKey);CryptoJS.pad.ZeroPadding.pad(cypherKey, 4);const iv = CryptoJS.SHA256(AESKey).toString();const cfg = { iv: CryptoJS.enc.Utf8.parse(iv) };const decrypt = CryptoJS.AES.decrypt(raw, cypherKey, cfg);return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}

然后,在上面这段代码,有几个关键信息指标需要统一:

  • mode:AES 有各种加密模式,例如 CBC、CFB、CTR 等模式,在前端的 crypto-js 说明文档里面可以看到它含有 6 种

9535cbc95db5f1e9418379ffeb7511d1.png

  • iv:AES 在一些加密模式上,需要指定 IV,即初始向量

  • padding:AES 需要加密的数据,不是 16 的倍数的时候,需要对原本的数据做 padding 操作(即补全长度到固定的位数),它有 Pkcs7、AnsiX923 等种类

3c2cb3491682642c6873f9fe2c909811.png

最后,服务端 Go 的代码可以参考:

package mainimport ("fmt""github.com/LinkinStars/go-scaffold/contrib/cryptor"
)func main() {key := "1234"e := cryptor.AesSimpleEncrypt("Hello World!", key)fmt.Println("加密后:", e)d := cryptor.AesSimpleDecrypt(e, key)fmt.Println("解密后:", d)iv := cryptor.GenIVFromKey(key)fmt.Println("使用的 IV:", iv)
}// 输出
// 加密后:NHlpzbcTvOj686VaF7fU7g==
// 解密后:Hello World!
// 使用的 IV: 03ac674216f3e15c

参考文献

搜索关键词:浏览器端 rsa + aes

  • 《博客园 - 常用加密算法概述》https://www.cnblogs.com/colife/p/5566789.html

  • 《CSDN - 浅谈常见的七种加密算法及实现》https://blog.csdn.net/baidu_22254181/article/details/82594072

  • 《简书 - 一、消息摘要算法MD5、SHA-1》https://www.jianshu.com/p/38c93c677124

  • 《简书 - sha256为什么不可逆,sha256的安全性如何》https://www.jianshu.com/p/fb2cc870337a

  • 《CSDN - 网络传输数据加解密方案选择(RSA+AES)》https://blog.csdn.net/yuzhiqiang_1993/article/details/88641265

  • 《掘金 - 实习技术总结(八)前端AES解密》https://juejin.cn/post/7122392902319210503

  • 《CSDN - 网络传输数据加解密方案选择(RSA+AES)》https://blog.csdn.net/yuzhiqiang_1993/article/details/88641265

  • 《KACIRAS - WebCrypto 与 Node 的 AES-GCM 踩坑》https://blog.kaciras.com/article/26/aes-crypto-in-node-and-browser

  • 《掘金 - 前端利用jsencrypt.js进行RSA加密》https://juejin.cn/post/7075542251228626951

  • 《思否 - 一套简单的基于 RSA + AES 加密机制的前端解决方案》https://segmentfault.com/a/1190000019399444

  • 《掘金 - 前端加解密方案探讨》https://juejin.cn/post/6844903745701019662

  • 《掘金 - springboot+vue接口加密:RSA+AES》https://juejin.cn/post/7181726644799963173

  • 《思否 - Golang 实现与 crypto-js 一致的 AES 简单加解密》https://segmentfault.com/a/1190000043754783

  • 《阿里云 - RSA:jsencrypt/Python实现加密》https://developer.aliyun.com/article/813627

  • 《简书 - jsencrypt前台加密,Go后台解密失败》https://www.jianshu.com/p/f2b03fe16193

  • 《CSDN - 在vue、golang搭建的前后端系统中使用jsencrypt包实现RSA加解密功能》https://blog.csdn.net/sinat_26553595/article/details/122411287

  • 《语言中文网 - 前后端交互,密码加密,RSA 实现前端 js 加密,后端 go 解密》https://studygolang.com/articles/35387


不折腾的前端,和咸鱼有什么区别!

觉得文章不错的小伙伴欢迎点赞/点 Star。

如果小伙伴需要联系 jsliang

  • Github

  • 掘金

个人联系方式存放在 Github 首页,欢迎一起折腾~

争取打造自己成为一个充满探索欲,喜欢折腾,乐于扩展自己知识面的终身学习斜杠程序员。

jsliang 的文档库由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议 进行许可。
基于 https://github.com/LiangJunrong/document-library 上的作品创作。
本许可协议授权之外的使用权限可以从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处获得。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/84638.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虹科新品 | 振动监测:提升风能行业效率与安全!

一、 CTC概览 服务于工业振动分析市场ISO 9001认证设计和测试以满足工业环境的实际需求无条件终身保修兼容所有主要数据采集器、分析仪和在线系统美国制造 二、风能行业&#xff1a;为什么要进行监测&#xff1f; 在风能行业&#xff0c;振动监测是一项至关重要的节约成本和安…

学习笔记-JVM监控平台搭建

SpringBoot Actuator 1 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId> </dependency>2 开启配置 # 暴露所有的监控点【含Prometheus】 management.endpoin…

windows下以指定用户访问SMB服务器进行读写

一 概述 最近遇到一个问题&#xff0c;linux 的 smb服务器开启匿名访问&#xff0c;windows访问linux文件夹不需要用户名密码就可以进去使用&#xff0c;但是存在一个问题&#xff0c;ssh连接到linux 后修改的文件&#xff0c;在windows已smb方式下打开某个文件修改 是没有权限…

uniapp文件下载并预览

大概就是这样的咯&#xff0c;文件展示到页面上&#xff0c;点击文件下载并预览该文件&#xff1b; 通过点击事件handleDownLoad(file.path)&#xff0c;file.path为文件的地址&#xff1b; <view class"files"><view class"cont" v-for"(…

docker-compose Install minio

前言 MinIO 是一种高性能、兼容 S3 的对象存储。它专为大规模 AI/ML、数据湖和数据库工作负载而构建。它在本地和任何云(公共或私有云)上运行,从数据中心到边缘。MinIO是GNU AGPL v3下的软件定义和开源。 MinIO是对象存储服务,它基于Apache License 开源协议,兼容Amazon …

无脑——010 复现yolov8 使用rt detr 训练自己的数据集

1.配置环境 1. 首先去官网下载yolov8的zip https://github.com/ultralytics/ultralytics 存放在我的目录下G:\bsh\yolov8 然后使用conda创建新的环境 conda create -n yolov8 python3.8 #然后激活环境 conda activate yolov8然后安装pytorch&#xff0c;注意 &#xff0c;py…

GitOps 与 DevOps:了解关键差异,为企业做出最佳选择

在软件开发领域&#xff0c;GitOps 和 DevOps 是加强协作和实现软件交付流程自动化的重要技术。虽然这两种模式都旨在提高软件开发生命周期的效率&#xff0c;但它们的核心原则和实施方式却各不相同。 本篇文章将帮助您了解 GitOps 和 DevOps 之间的差异、它们的工作流程&am…

linux安装redis带图详细

如何在Linux系统中卸载Redis 一、使用apt-get卸载Redis sudo apt-get purge redis-server如果使用apt-get安装Redis&#xff0c;可以使用apt-get purge命令完全卸载Redis。其中&#xff0c;purge命令会不仅仅删除Redis二进制文件&#xff0c;还会删除配置文件、数据文件和日志…

logstash 采集 docker 日志

1、nginx容器部署 参考&#xff1a;nginx容器部署 将容器内的nginx日志文件映射到宿主机/home/logs/nginx目录下 注意&#xff1a;并且需要需要将日志的输出格式修改为json 2、编辑vim /opt/logstash-7.4.2/config/nginx-log-es.conf 文件&#xff0c;收集docker nginx容器日…

Vue + MapBox快速搭建

一、说明&#xff1a; 1.mapbox-gl自2.0版本开始不再开源&#xff0c;需要用户在官网申请key使用。 2.maplibre GL JS是一个开源库&#xff0c;它起源于 mapbox-gl-js 的开源分支。该库的初始版本&#xff08;1.x&#xff09;旨在替代Mapbox的OSS版本。简单来说maplibre是mapb…

Chatgpt API调用报错:openai.error.RateLimitError

Chatgpt API 调用报错&#xff1a; openai.error.RateLimitError: You exceeded your current quota, please check your plan and billing details. 调用OpenAI API接口 import openai import osopenai.api_key os.getenv("OPENAI_API_KEY")result openai.Chat…

Linux系统之使用cmatrix实现数字雨效果

Linux系统之使用cmatrix实现数字雨效果 一、cmatrix介绍二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、环境准备工作3.1 安装开发环境3.2 安装基本软件3.3 安装 ImageMagick等工具 四、安装aalib工具4.1 新建目录4.2 下载aalib安装包4.3 解压软件包4.4 编译安装aalib …

Unity Git项目添加子模块

在 当前仓库根目录下执行命令 git submodule add https://github.com/xxx/child.git 检查仓库状态 git status 更新子库 git submodule update --remote 下拉父仓库Git并保住子库也更新 git pull --recurse-submodules 推荐使用 Githubdesktop工具 这样你可以更清楚的看到自己…

Redis学习笔记Day01-Redis入门

声明&#xff1a;本博客部分内容是从终极SpringBoot讲义摘抄的&#xff0c;文字是OCR识别出来的&#xff0c;有可能存在识别错误的可能&#xff0c;如有错误&#xff0c;请大胆指正&#xff0c;我马上修改&#xff01; 目录 0.官方参考手册API1.连接命令2.key相关命令3.String命…

基础实验篇 | QGC实时调整控制器参数实验

PART 1 实验名称及目的 QGC实时调整控制器参数实验&#xff1a;在进行硬件在环仿真和真机实验时&#xff0c;常常需要在QGC地面站中观察飞行状态&#xff0c;并对控制器参数进行实时调整&#xff0c;以使得飞机达到最佳的控制效果&#xff0c;但是&#xff0c;在Simulink中设…

【Python机器学习】实验11 神经网络-感知器

文章目录 人工神经网络感知机二分类模型算法 1. 基于手写代码的感知器模型1.1 数据读取1.2 构建感知器模型1.3 实例化模型并训练模型1.4 可视化 2. 基于sklearn的感知器实现2.1 数据获取与前面相同2.2 导入类库2.3 实例化感知器2.4 采用数据拟合感知器2.5 可视化 实验1 将上面数…

保姆级Arcgis安装图文安装教程

参考视频&#xff1a;【钟老师arcGIS从放弃到入门】02软件下载与安装_哔哩哔哩_bilibili 安装包在视频简介中有 注释&#xff1a;安装过程中有犯错误&#xff0c;请耐心看完一遍再跟着操作 &#xff08;一&#xff09;安装包下载 下载视频中分享的压缩包(压缩包密码&#x…

【C++】二叉搜索树的模拟实现(K,KV树)递归与非递归方式

文章目录 前言一、K树1.结点的定义2.构造函数3.拷贝构造函数4.赋值运算符重载5.析构函数6.二叉搜索树的查找&#xff08;find&#xff09;1.非递归2.递归 7.二叉搜索树的插入&#xff08;Insert&#xff09;1.非递归2.递归 8.二叉搜素树的删除&#xff08;Erase&#xff09;1.非…

yolov5的报错

【定期水一期】 &#xff08;这个问题很抓马&#xff0c;可以看一下这篇文章&#xff1a;Git Bash 教程&#xff01;【不是所有人都会用Git】&#xff09; 一&#xff1a;没有cv2这个模块 解决方案&#xff1a; pip install opencv-python -i http://pypi.douban.com/simple/…

emqx-5.1.4开源版使用记录

emqx-5.1.4开源版使用记录 windows系统安装eqmx 去官网下载 emqx-5.1.4-windows-amd64.zip&#xff0c;然后找个目录解压 进入bin目录,执行命令启动emqx 执行命令 emqx.cmd start使用emqx 访问内置的web管理页面 浏览器访问地址 http://localhost:18083/#/dashboard/overv…