前端常用的几种加密方法
在信息安全越来越受重视的今天,JS 安全一直是前端工程师们注重的大问题,前端的各种加密也变得更加重要。通常跟服务器的交互中,为保障数据传输的安全性,避免被人抓包篡改数据,除了 https 的应用,还需要对传输数据进行加解密,保证了所有使用者的权益不被侵犯。
常见加密方式:
- 对称加密算法(对称加密算法是指加密和解密使用相同密钥的加密算法。在前端常用的对称加密算法包括 AES、DES 等。对称加密算法的安全性依赖于密钥,泄露密钥就意味着任何人都可以对他们发送或接收的消息解密,所以密钥的保密性对通信的安全性至关重要。对称加密算法的优点在于算法公开、计算量小、加密速度快、加密效率高,缺点在于在数据传送前,发送方和接收方必须商定好密钥,然后双方保存好密钥。如果一方的密钥被泄露,那么加密信息也就不安全了。对称加密算法适用于本地数据加密、https 通信、网络传输等场景。)
- Hash 算法(Hash 算法是一种将任意长度的数据转换成固定长度的哈希值的算法。在前端常用的 Hash 算法包括 MD5、SHA-1 等。Hash 算法是不可逆的,因此常用于验证数据的完整性,例如文件校验和、密码加密等。Hash 算法的优点在于可以将任意长度的数据转换成固定长度的哈希值,且计算速度快、效率高,缺点在于无法通过哈希值恢复原始数据。Hash 算法适用于数据完整性校验等场景。)
- 非对称加密算法(非对称加密算法是指加密和解密使用不同密钥的加密算法,其中公钥用于加密,私钥用于解密。在前端常用的非对称加密算法包括 RSA 等。非对称加密算法的安全性依赖于公钥和私钥的生成和管理,泄露任何一把密钥都意味着任何人都可以对他们发送或接收的消息解密,所以公钥和私钥的保密性对通信的安全性至关重要。非对称加密算法的优点在于可以保证数据传输的安全性,缺点在于算法复杂、计算量大、加密速度慢、效率低。非对称加密算法适用于数字签名、身份认证等场景。)
md5 加密(不可逆)
MD5 是比较常见的 Hash 算法,对于 MD5 而言,有两个特性是很重要的,第一:明文数据经过散列以后的值是定长的;第二:是任意一段明文数据,经过散列以后,其结果必须永远是不变的。前者的意思是可能存在有两段明文散列以后得到相同的结果,后者的意思是如果我们散列特定的数据,得到的结果一定是相同的。
js-md5 加密方式 MD5 加密后的位数有两种:16 位与 32 位。默认使用 32 位。(16 位实际上是从 32 位字符串中取中间的第 9 位到第 24 位的部分)为提高安全性。根据业务需求,可以对 md5 添加偏移量。如对原有字符拼接指定位数的字符串
npm 安装
npm install --save js-md5
使用
// 然后在页面中 引入
import md5 from 'js-md5'
md5('加密内容') //默认32位
md5('加密内容').substring(8, 24) // 从第8个字符开始截取16位
base64 位加密(可加密可解密)
Base64 是用于网络上传输 8Bit 字节码的最常见的编码方法之一,Base64 不是安全领域的加密算法。实际上,Base64 只能算是一种编码算法,对数据内容进行编码以适应传输。Base64 是一种将二进制数据转换为 ASCII 字符串的编码方法。它将每 3 个字节的数据编码为 4 个可打印的 ASCII 字符,因此 Base64 编码后的数据长度总是原数据长度的约 4/3 倍(不足 4 的倍数时进行补位)。Base64 编码表由 64 个字符组成,其中包含大小写字母、数字和两个特殊字符 “+”, “/”,同时还有一个填充字符 “=”。Base64 编码是一种可逆操作,可以通过解码操作还原原始数据。
npm 安装
npm install --save js-base64
使用
/**
* BASE64加密
* @param str
* @returns {string}
*/
base64Encode(str) {
return btoa(unescape(encodeURI***ponent(str)))
}
/**
* BASE64解密
* @param str
* @returns {string}
*/
base64Decode(str) {
return decodeURI***ponent(escape(atob(str)))
}
RSA 加密(公钥加密,私钥解密)
RSA 加密:RSA 是一种非对称加密算法,它使用公钥和私钥进行加密和解密。在前端使用 RSA 加密时,需要使用第三方库进行加密和解密操作,例如 jsencrypt。RSA 加密适用于加密大量数据或进行数字签名等场景。
// 使用公钥加密
var publicKey = 'public_key_123'
var encrypt = new JSEncrypt()
encrypt.setPublicKey(publicKey)
var encrypted = encrypt.encrypt('Hello World')
// 使用私钥解密
var privateKey = 'private_key_123'
var decrypt = new JSEncrypt()
decrypt.setPrivateKey(privateKey)
var uncrypted = decrypt.decrypt(encrypted)
AES 加密(需要密钥才能解密)
AES 加密:AES 是一种对称加密算法,它使用相同的密钥进行加密和解密。在前端使用 AES 加密时,需要使用第三方库进行加密和解密操作,例如 crypto-js。AES 加密适用于加密大量数据或进行对称加密等场景。
var CryptoJS = require('crypto-js')
var data = { id: 1, text: 'Hello World' }
// 加密生成密文
var ciphertext = CryptoJS.AES.encrypt(
JSON.stringify(data),
'secret_key_123'
).toString()
// 解密得到明文
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret_key_123')
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
CryptoJS
CryptoJS 是一个 JavaScript 的加解密的工具包。它支持多种算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160 的哈希散列,以及进行 AES、DES、Rabbit、RC4、Triple DES 加解密。
npm 安装
npm install crypto-js
封装加密文件 asc.js
// 1.引入CryptoJS加密插件
import CryptoJS from 'crypto-js'
// 2.设置秘钥和偏移量需要和后端一致
// 十六位十六进制数作为密钥
const KEY = CryptoJS.enc.Utf8.parse('wtkjtoba***o12345')
// 十六位十六进制数作为密钥偏移量
const IV = CryptoJS.enc.Utf8.parse('123456wtkj654321')
export default {
/**
* 加密方法
* @param {*} word
* @param {*} keyStr
* @param {*} ivStr
*/
encrypt(word, keyStr, ivStr) {
let key = KEY
let iv = IV
if (keyStr) {
key = CryptoJS.enc.Utf8.parse(keyStr)
iv = CryptoJS.enc.Utf8.parse(ivStr)
}
let srcs = CryptoJS.enc.Utf8.parse(word)
var encrypted = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding,
})
return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
},
/**
* 解密方法
* @param {*} word
* @param {*} keyStr
* @param {*} ivStr
*/
decrypt(word, keyStr, ivStr) {
let key = KEY
let iv = IV
if (keyStr) {
key = CryptoJS.enc.Utf8.parse(keyStr)
iv = CryptoJS.enc.Utf8.parse(ivStr)
}
let base64 = CryptoJS.enc.Base64.parse(word)
let src = CryptoJS.enc.Base64.stringify(base64)
let decrypt = CryptoJS.AES.decrypt(src, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding,
})
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
return decryptedStr.toString()
},
}
在登录组件 login.vue 使用
<template>
<div class="home">
<el-form
:model="userForm"
status-icon
:rules="rules"
ref="userForm"
label-width="100px"
class="demo-userForm"
label-position="top"
>
<el-form-item prop="phone">
<el-input
type="text"
v-model="userForm.phone"
prefix-icon="el-icon-user"
placeholder="请输入用户名"
>
</el-input>
</el-form-item>
<el-form-item prop="password" style="margin-top: 20px !important">
<el-input
type="password"
v-model="userForm.password"
show-password
prefix-icon="el-icon-goods"
placeholder="请输入密码"
>
</el-input>
</el-form-item>
</el-form>
<el-button @click="submitForm('userForm')">登录</el-button>
</div>
</template>
<script>
import asc from "@/plugins/asc"; //引入封装好的加密
export default{
name:'login',
data(){
return{
// 表单绑定数据
userForm: {
phone: "",
password: "",
},
encryptionFrom: {}, //加密表单
// 校验规则
rules: {
phone: [{ required: true, message: "账号不能为空!" }],
password: [{ required: true, message: "密码不能为空!" }],
},
}
}
methods:{
// 登录按钮事件
submitForm(formName) {
this.$refs[formName].validate((valid) => {
// this.$router.push({ name: "toba***oBureau" });
if (valid) {
this.loading = true;
this.encryptionFrom = JSON.parse(JSON.stringify(this.userForm));
// 加密
this.encryptionFrom.password = asc.encrypt(this.userForm.password);
this.$axios({
url: `auth/login`,
method: "POST",
params: this.encryptionFrom,
})
.then(async (res) => {
if (res.su***ess) {
if (this.isRemenberPassword) {
// 判断是否勾选了记住密码
this.saveLocalPassword();
} else {
localStorage.removeItem("localPassword");
}
console.log("res", res);
sessionStorage.setItem("token", res.data.token);//存储token
await this.$store.dispatch("getUserInfo");
// this.$router.push({ name: "case" });
// this.$message.su***ess("登录成功");
}
})
.catch((err) => {})
.finally(() => {
this.loading = false;
});
}
});
},
//保存缓存密码
saveLocalPassword() {
console.log("保存", this.form);
localStorage.setItem("localPassword", JSON.stringify(this.form));
},
// 获取缓存密码
getLocalPassword() {
this.isRemenberPassword = false;
let form = JSON.parse(localStorage.getItem("localPassword"));
if (form) {
this.isRemenberPassword = true;
this.form = form;
}
},
}
}
</script>
常用的加密方式–demo
<template>
<div class="main">
<el-form :model="form" :rules="rules" ref="dialog_form" label-width="80px">
<el-row>
<el-col :span="6">
<el-form-item label="密码:">
<el-input
placeholder="请输入"
size="small"
v-model="form.password"
@change="passwordChange"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row
>----------------------------------------------------------------------------------------------------------------</el-row
>
<el-row>
<h1 class="title">md5加密(默认32位)</h1>
<span>{{ md5Encode(form.password) }}</span>
</el-row>
<el-row>
<h1 class="title">md5加密(16位)</h1>
<span>{{ md5Encode2(form.password) }}</span>
</el-row>
<el-row>
<span class="detail"
>js-md5加密方式 MD5 加密后的位数有两种:16 位与 32 位。默认使用 32
位。 (16 位实际上是从 32 位字符串中取中间的第 9 位到第 24
位的部分)为提高安全性。根据业务需求,可以对 md5
添加偏移量。如对原有字符拼接指定位数的字符串。</span
>
</el-row>
<el-row>
<h1 class="title">base64加密(方法1 window.btoa)</h1>
<span>{{ base64Encode1(form.password) }}</span>
</el-row>
<el-row>
<h1 class="title">base64加密(方法3 Base64.encode使用插件)</h1>
<span>{{ base64Encode2(form.password) }}</span>
</el-row>
<el-row>
<h1 class="title">
base64加密(方法3 btoa(unescape(encodeURI***ponent)))
</h1>
<span>{{ base64Encode3(form.password) }}</span>
</el-row>
<el-row>
<h1 class="title">
base64解密(方法3 decodeURI***ponent(escape())使用插件)
</h1>
<span>{{ base64Decode(base64Encode3(form.password)) }}</span>
</el-row>
<el-row>
<h1 class="title">asc加密(使用CryptoJS插件)</h1>
<span>{{ encrypt(form.password) }}</span>
</el-row>
<el-row>
<h1 class="title">asc解密(使用CryptoJS插件)</h1>
<span>{{ decrypt(encrypt(form.password)) }}</span>
</el-row>
<el-row>
<span class="detail">
CryptoJS 是一个 JavaScript
的加解密的工具包。它支持多种算法:MD5、SHA1、SHA2、SHA3、RIPEMD-160
的哈希散列,以及进行 AES、DES、Rabbit、RC4、Triple DES 加解密。</span
>
</el-row>
<el-row>
<h1 class="title">对称(RSA)加密:jsencrypt</h1>
<span>{{ RSAEncode(form.password) }}</span>
</el-row>
<el-row>
<el-col :span="14">
<span class="detail">
关于该加密模块,出现在自己做的一个后台管理系统项目中,前端是vue,后端是Java。应用的场景是需要前端通过公钥对需要加密的密文进行加密,后端通过私钥对前端加密的密文进行解密。这样能比之前三个能极大的提高密文安全性。相关的使用方式可以参照下面
关于前端的其他加密解密好文中的第二个。
这里把关于前端方面简化后的代码贴在下方,可供参考,后端方面的参考下方链接的第二个博文
</span>
</el-col>
</el-row>
<div></div>
</el-form>
</div>
</template>
<script>
import md5 from 'js-md5' //引入md5加密插件
import { Base64 } from 'js-base64' //base64加密插件
import CryptoJS from 'crypto-js' //引入CryptoJS加密插件
import JSEncrypt from 'jsencrypt' //引入JSEncrypt加密插件
export default {
data() {
return {
form: {
password: '123', //密码
},
rules: {}, //校验
}
},
methods: {
passwordChange() {},
// md5加密(默认32位)
md5Encode(str) {
return md5(str)
},
// 使用 MD5 加密算法进行16位加密
md5Encode2(str) {
return md5(str).substring(8, 24) // 从第8个字符开始截取16位
},
// base64加密(方法1--window.btoa)
base64Encode1(str) {
return window.btoa(str)
},
// base64加密(方法2-- Base64.encode) 使用插件
base64Encode2(str) {
return Base64.encode(str)
},
// base64加密(方法3--window.btoa)
/**
* BASE64加密
* @param str
* @returns {string}
*/
base64Encode3(str) {
return btoa(unescape(encodeURI***ponent(str)))
},
/**
* BASE64解密
* @param str
* @returns {string}
*/
base64Decode(str) {
return decodeURI***ponent(escape(atob(str)))
},
// asc加密
/**
* 加密方法
* @param {*} word
* @param {*} keyStr
* @param {*} ivStr
*/
encrypt(word, keyStr, ivStr) {
// 设置秘钥和偏移量需要和后端一致
// 十六位十六进制数作为密钥
const KEY = CryptoJS.enc.Utf8.parse('123456jmff654321')
// 十六位十六进制数作为密钥偏移量
const IV = CryptoJS.enc.Utf8.parse('654321jmff123456')
let key = KEY
let iv = IV
if (keyStr) {
key = CryptoJS.enc.Utf8.parse(keyStr)
iv = CryptoJS.enc.Utf8.parse(ivStr)
}
let srcs = CryptoJS.enc.Utf8.parse(word)
var encrypted = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding,
})
return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
},
// asc解密
/**
* 解密方法
* @param {*} word
* @param {*} keyStr
* @param {*} ivStr
*/
decrypt(word, keyStr, ivStr) {
// 设置秘钥和偏移量需要和后端一致
// 十六位十六进制数作为密钥
const KEY = CryptoJS.enc.Utf8.parse('123456jmff654321')
// 十六位十六进制数作为密钥偏移量
const IV = CryptoJS.enc.Utf8.parse('654321jmff123456')
let key = KEY
let iv = IV
if (keyStr) {
key = CryptoJS.enc.Utf8.parse(keyStr)
iv = CryptoJS.enc.Utf8.parse(ivStr)
}
let base64 = CryptoJS.enc.Base64.parse(word)
let src = CryptoJS.enc.Base64.stringify(base64)
let decrypt = CryptoJS.AES.decrypt(src, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding,
})
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
return decryptedStr.toString()
},
// 非对称加密密钥生成网站:http://web.chacuo.***/***rsakeypair
// RSA非对称加密是一种广泛使用的加密算法,它使用两个密钥:一个公钥用于加密数据,一个私钥用于解密数据。在JavaScript中,可以使用CryptoJS库来实现RSA非对称加密。
// 非对称(RSA)加密:jsencrypt
RSAEncode(str) {
let encryptor = new JSEncrypt() // 新建JSEncrypt对象
let publicKey = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuY3BqJVVeLwYF/qk6VeM
ZNKruSQUfAsrz3Hv0ExmK7FdlsgtEBRMpFNylCFw2pbhdFtC0iedr5+DDKqqasUh
boXMRR5KV27Zan96RbyQaqT9oXP6n9d6JBPNxuTglLtnK+FielB8oXmlz8YmOvs6
mH2n6GNoYAFwaNMXPAtiNFk+BbyTeN7t6aejQiidqq8OW87c/B6KD1ffbQBC56u2
CGYHPHjvL4G7QtR3vheXFNXjz2e0iVvHZ5hv/rBXRk9XNnV0eID3/TXlGiCFcyqd
wm6tMV54H9tv9XX00NqhBnKtPIxLTCe5Ys/83K+KuniOYYtLQmy5NLgNaNTm6hCD
ZwIDAQAB` //设置公钥,可以从上面的非对称加密密钥生成网站中得到
encryptor.setPublicKey(publicKey) // 将得到的公钥通过setPbulicKey方法设置到JSEncrypt对象中
return encryptor.encrypt(str) // 对需要加密的数据进行加密,rspPassWord就是加密密文
},
},
}
</script>
<style lang="scss" scoped>
.main {
width: 100%;
height: 100%;
padding: 10px;
.banner {
width: 800px;
height: 600px;
margin: 0 auto;
box-sizing: border-box;
border: 1px solid #***c;
}
.title {
font-size: 16px;
// color: rgb(150, 15, 212);
display: inline-block;
}
.detail {
color: darkgray;
}
}
</style>
需要注意的是,前端加密并不能保证绝对的安全性,应该结合其他安全措施来提高系统的安全性。同时,在选择加密算法时应该根据具体的需求和场景进行选择,综合考虑安全性和性能等因素。
✒️总结
如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对前端端或者对python感兴趣的朋友,请多多关注💖💖💖,咱们一起探讨和努力!!!
👨🔧 个人主页 : 前端初见