一: 常见加密算法
1.对称加密
使用的密钥只有一个,发送和接收双方都使用这个密钥对数据进行加密和解密。这就要求加密和解密方事先都必须知道加密的密钥。其优点是算法公开、计算量小、加密速度快、加密效率高;缺点是密钥泄露之后,数据就会被破解。一般不推荐单独使用。根据实现机制的不同,常见的算法主要有AES、ChaCha20、3DES等。
2.非对称加密
它需要两个密钥,一个称为公开密钥 (public key),即公钥;另一个称为私有密钥 (private key),即私钥。
他俩是配对生成的,就像钥匙和锁的关系。因为加密和解密使用的是两个不同的密钥,所以这种算法称为非对称加密算法。其优点是算法强度复杂、安全性高;缺点是加解密速度没有对称加密算法快。常见的算法主要有RSA、Elgamal等。
3.散列算法
散列算法又称散列函数、哈希函数,是把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定成特定长度的值。一般用于校验数据的完整性,平时我们下载文件就可以校验 MD5 来判断下载的数据是否完整。常见的算法主要有 MD4、MD5、SHA 等。
二:方案
单单使用对称加密
使用两套非对称加密,
上传数据-客户端用公钥加密,下载数据-客户端用私钥解密秘钥更新比较麻烦
对称加密与非对称结合:
上传数据时:
- 客户端用随机生成秘钥对敏感数据进行对称加密,
- 从服务端获取非对称加密的 公钥,
- 对对称加密的秘钥进行非对称加密
下载数据:
- 服务端用对称加密对数据进行加密
总结:
方案二比较简单,但是需要维护两套公钥和私钥,当公钥变化的时候,必须通知对方,灵活性比较差。方案三相对方案二来说,密钥 1 随时可以变化,并且不需要通知服务端,相对来说灵活性、安全性好点并且方案三对内容是对称加密,当数据量大时,对称加密的速度会比非对称加密快。所以本文采用方案三给予代码实现。
三: 代码实现
前端:
// npm 引入npm install crypto-js//utils包下的index文件中增加解密与加密方法const CryptoJS = require('crypto-js')/*** aes加密方法* @param {string} text 待加密的字符串* @param {array} key 加密key*/export function aesEncrypt(text, key) {// var message = JSON.stringify(data);//加密后的字符窜key = CryptoJS.enc.Utf8.parse(key)var encryptedData = CryptoJS.AES.encrypt(text, key, {mode: CryptoJS.mode.ECB, // ECB加密模式 根据后端采用的模式更改padding: CryptoJS.pad.Pkcs7})return encryptedData.toString()}/*** aes解密方法* @param {string} encryptedHex 加密的字符串* @param {array} key 加密key*/export function aesDecrypt(encryptedHex, key) {key = CryptoJS.enc.Utf8.parse(key)var decrypt = CryptoJS.AES.decrypt(encryptedHex, key, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7})return CryptoJS.enc.Utf8.stringify(decrypt).toString()}/*** 随机生成秘钥*/export function getRandomKey(n) {var chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']if (n == null) {n = 16}var res = ''for (var i = 0; i < n; i++) {var id = Math.ceil(Math.random() * 35)res += chars[id]}return res}
常见错误:
Key length not 128/192/256 bits,key的长度必须要是128,192或者256 位
128 位 对应的是 16 个字节
192 位 对应的是 24 个字节
256 位 对应的是 32 个字节
npm install jsencrypt//vue页面引入import { JSEncrypt } from 'jsencrypt'//页面方法内:const encrypt = new JSEncrypt()encrypt.setPublicKey(this.publicKey) //设置公钥data.secretKey = encrypt.encrypt(secretKey) //非对称加密
java:
java部分是引用的Hutool工具包中的方法
//@Configuration配置类中,配置公私钥 将rsa对象放入容器中@Beanpublic RSA RSAGenfactory(){return new RSA(privateKey,publicKey);}//接口方法中对上传数据进行解析引入容器中的RSA对象@AutowiredRSA rsa;//非对称解密String data = rsa.decryptStr(要解密的数据, KeyType.PrivateKey);//对称解密SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, data.getBytes());String repCode = aes.decryptStr(要解密的数据,CharsetUtil.CHARSET_UTF_8);
