1、编码和解码字符串
JavaScript 定义了 6 个全局方法用于 Unicode 字符串的编码和解码:
-
escape()
:对字符串进行编码。 -
unescape()
:对由escape()
编码的字符串进行解码。 -
encodeURI()
:把字符串编码为 URI。 -
decodeURI()
:对由encodeURI()
编码的 URI 进行解码。 -
encodeURIComponent()
:把字符串编码为 URI 组件。 -
decodeURIComponent()
:对由encodeURIComponent()
编码的 URI 组件进行解码。
1.1 具体什么场合使用?
1.1.1 如果只是编码字符串,使用escape
escape("Need tips? Visit RUNOOB!")
// Need%20tips%3F%20Visit%20RUNOOB%21
1.1.2 如果需要编码整个URL,然后需要使用这个URL,使用encodeURl
encodeURI("http://www.w3school.com.cn/My first/")
// http://www.w3school.com.cn/My%20first/
1.1.3 如果需要编码URL中的参数,使用encodeURlComponent
encodeURIComponent("http://www.w3school.com.cn/p 1/")
// http%3A%2F%2Fwww.w3school.com.cn%2Fp%201%2F
CryptoJS (crypto.js) 为 JavaScript 提供了各类各样的加密算法,因为它使用起来稍微有些复杂。因此本文主要着重说一下CryptoJS进行MD5/SHA256/BASE64/AES加解密的方法与示例。
crypto-js (base64 、RSA、AES、DES、MD5)
安装crypto-js
npm install crypto-js
引入crypto-js
import CryptoJS from "crypto-js";
2、base64 加解密
加密:
CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse('hello world'))
// 'aGVsbG8gd29ybGQ='
解密:
CryptoJS.enc.Base64.parse('aGVsbG8gd29ybGQ=').toString(CryptoJS.enc.Utf8)
//'hello world'
【拓展】
从 IE10+ 浏览器开始,所有浏览器就原生提供了 Base64 编码、解码方法,不仅可以用于浏览器环境,Service Worker环境也可以使用。
浏览器对原生提供的 Base64编码、解码方法:
- 编码:
atob()
方法。 - 解码:
btoa()
方法。
使用 atob()
和 btoa()
方法加密解密:
window.btoa('hello world') // 编码
window.atob('aGVsbG8gd29ybGQ=') // 解码
3、摘要算法
常用的摘要算法有MD5,SHA1
。摘要算法是一个不可逆过程,就是无论多大数据,经过算法运算后都是生成固定长度的数据,一般结果使用16进制进行显示。
主要用途有:
-
消息完整性:由于每一份数据生成的MD5值不一样,因此发送数据时可以将数据和其MD5值一起发送,然后就可以用MD5验证数据是否丢失、修改。
-
安全访问认证:这是使用了算法的不可逆性质,(就是无法从MD5值中恢复原数据)对账号登陆的密码进行MD5运算然后保存,这样可以保证除了用户之外,即使数据库管理人员都无法得知用户的密码。
3.1 MD5 加密(不可逆)
MD5 加密理论上是不能破解的,因为 MD5 是一种散列函数,使用的是hash算法。
CryptoJS.MD5('hello world').toString()
常用场景:
- 用户密码
对于用户密码加密最高境界就是:别人获得你数据库的用户资料别人也没有办法获知密码.要达到就要有一套复杂的加密规则,一般常用的规则比如:
MD5(MD5(用户名+用户密码)+MD5(KEY+项目名+公司名)) 这样可以避免和别人碰库不排除别人用MD5来攻击你的服务器来匹配.
- 请求参数
为了避免被拦截,参数被修改的常用方法就是对请求参数进行校验,就算拦截了请求参数修改了只要模拟不出MD5加密出来的值,在服务器过滤器直接就会进行拦截.
我这边推荐的请求校验方法在传递参数的时候带上 MD5值 随机数 时间戳 ,比如:
MD5=MD5(随机数+时间戳+MD5(KEY+公司名+项目名))
请求参数在服务器拦截器就用客户端传递过来的 随机数 时间戳 来做校验如果不通过就不让继续访问(在这里的随机数 时间戳在后面的请求安全请求唯一性验证中会起到很大的作用所以建议保留)
- 文件校验
如果有一个5MB的文件 客户端把它分割成5份 1MB的文件 在上传的时候 上传两个MD5值 一个是当前上传的片1MB文件流的MD5 还有一个就是拼接之后的MD5(如果现在上传的是第二片 这个MD5就应该是第一片加上第二片的MD5)通过这样的方式能保证文件的完整性
3.2 SHA 加密(不可逆)
CryptoJS.SHA1("Message").toString()
CryptoJS.SHA256("Message").toString()
CryptoJS.SHA512("Message").toString()
4、对称加密算法
对称加密算法只是为了区分非对称加密算法。其中鲜明的特点是
对称加密是加密解密使用相同的密钥,而非对称加密加密和解密时使用的密钥不一样。
对于大部分情况我们都使用对称加密,而对称加密的密钥交换时使用非对称加密,这有效保护密钥的安全。非对称加密加密和解密密钥不同,那么它的安全性是无疑最高的,但是它加密解密的速度很慢,不适合对大数据加密。而对称加密加密速度快,因此混合使用最好。
常用的对称加密算法有:AES
和 DES
.
DES
:比较老的算法,一共有三个参数入口(原文,密钥,加密模式)。而3DES只是DES的一种模式,是以DES为基础更安全的变形,对数据进行了三次加密,也是被指定为AES的过渡算法。AES
:高级加密标准,新一代标准,加密速度更快,安全性更高(不用说优先选择)
4.2 AES
// 加密
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase").toString();
// 解密
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase").toString(CryptoJS.enc.Utf8);
4.2 DES
// 加密
var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase").toString();
// 解密
var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase").toString(CryptoJS.enc.Utf8);
5、非对称加密
5.1 RSA加解密
RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。在使用 RSA 进行加密和解密时需要一对公钥和私钥,公钥一般存储在前端(前端使用公钥进行加密),而私钥一般存储与后端(后端使用私钥对密文进行解密);
安装jsencrypt
npm install jsencrypt
封装
import JSEncrypt from 'jsencrypt'
let RSA = {
//使用公钥加密
encrypt(str, pubKey) {
let encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
let encrypted = encrypt.encrypt(str);
return encrypted
console.log('加密后数据:%o', encrypted);
},
//使用私钥解密
decrypt(str,priKey) {
let decrypt = new JSEncrypt();
decrypt.setPrivateKey(priKey);
let uncrypted = decrypt.decrypt(str);
return uncrypted;
console.log('解密后数据:%o', uncrypted);
}
}
export default RSA;
公钥私钥的获取
Linux 下可直接通过终端命令来获取;
通过在线网站生成: http://web.chacuo.net/netrsakeypair(选择合适的秘钥位数和格式)
5.2 国密算法(SM2)
安装
npm install --save sm-crypto
封装使用
const sm2 = require('sm-crypto').sm2
const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1
// 加密
export function sm2Encrypt(text, publicKey) {
const enText = sm2.doEncrypt(text, publicKey, cipherMode)
return '04' + enText
}
// 解密
export function sm2Decrypt(text, privateKey) {
const deText = sm2.doDecrypt(text, privateKey, cipherMode)
return deText
}