加密解密篇
在某些场景,加密是必须的操作,如:数据库用户信息,密码,关键业务信息等。
在我看来,加密分为两种,分别有他们对应的场景。
- 可解密:需要回显,处理等的数据,如:用户姓名。
- 不可解密:不需要回显,只需判断的,如:用户密码。
文章目录
一.可解密
可解密的算法有很多种,我不是从事这个领域的专业人员,故不对概念做阐述,目前来看,会用、知道是什么加密即可。
观前提醒
本篇文章加密算法,后端均依赖于Hutool
工具类,POM
引入即可。官网
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.4</version>
</dependency>
1. AES
加密
最常见的对称加密算法
(微信小程序加密传输就是用这个加密算法的)。
其中:密码(KEY)
,偏移量(THE_OFFSET)
,模式(Mode)
和补码方式(Padding)
,这几个字段信息,可以根据实际进行修改。
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
public class AESUtil {
private static final String KEY = "123456789ABCDEFG";
private static final String THE_OFFSET = "1234567898765432";
private static AES getAes() {
return new AES(Mode.CTS, Padding.PKCS5Padding, KEY.getBytes(), THE_OFFSET.getBytes());
}
/**
* 加密
* @param content 加密内容
* @return 加密结果
*/
public static String encrypt(String content) {
if (StrUtil.isEmpty(content)) {
return "";
}
return getAes().encryptHex(content);
}
/**
* 解密
* @param encryptHex 加密字段
* @return 解密结果
*/
public static String decrypt(String encryptHex) {
if (StrUtil.isEmpty(encryptHex)) {
return "";
}
String res = "";
try {
res = getAes().decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
} catch (Exception e) {
log.error("解密信息无效:{}",encryptHex);
}
return res;
}
public static void main(String[] args) {
String encrypt = encrypt("LitongZero");
System.out.println(encrypt);
String decrypt = decrypt(encrypt);
System.out.println(decrypt);
}
}
2. RSA
加密
RSA加密,需要两组秘钥,分别是公钥和私钥。一般,我们使用公钥进行加密,公私钥进行解密。当然,也可以私钥加密,公钥解密。实际可以根据需求而定,而私钥往往存在服务器,以防暴露。
下列代码中,包含随机获取一对公私钥
的工具。可自行生产密钥对,安全保险。
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.json.JSONUtil;
import java.util.Map;
/**
* @author litong
* @date 2020/4/27 0:11
*/
public class MyRSAUtil {
final static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOHrv6o1clkfaHTYwbmMuVrsmANDVrkIBrXdqzZjLjIo1Z0npQ0ZRRUsCYC4aee7jJxyVXYDEKzaVRVs6gMeAeZ4QiBsZUqxhHr9q9IrE+M7nknt6fotUt8LxiVnyRAjwLmSu503s4tGP15yudzPchyMC8+ZNphUQ8FtEtGIKOwQIDAQAB";
final static String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAM4eu/qjVyWR9odNjBuYy5WuyYA0NWuQgGtd2rNmMuMijVnSelDRlFFSwJgLhp57uMnHJVdgMQrNpVFWzqAx4B5nhCIGxlSrGEev2r0isT4zueSe3p+i1S3wvGJWfJECPAuZK7nTezi0Y/XnK53M9yHIwLz5k2mFRDwW0S0Ygo7BAgMBAAECgYApM2OH2haVX/PTX+Dds1Eefm2wvr7e3WeODpiku4z4cfOnPLdOaFYpW008FzG1hC2Px8rjCEtFSY3+EEgFJXMSxMOZPWIr/nrmHTdIue7mXHIE0cC/yDiIxfgYkw1QB4mNClg3sQj7kkMmUHhOosRw7QgPrKKTLleZ/Qs7cWzusQJBAPRtw9C1Nh6Fp14UdBAZKgeOkx1ciCtifFGHMshQOGRELEGfZxPd/0s77fPEo/sU08zlGUUUSduqBVNkQ0oVNF8CQQDX4LSlT7R2ZQrwMZJy03sN6SnhE7BEFeOZuBE+K6kdCdb65QEJ3Es/cI9EVT/MWiRepJhvbioyf41cYFGZvBDfAkEAhMVm+2SjnBq/miQEE4aHxQkWMnnD4cUigGqvFA43Q4egfpjmtez9stE/5Q0ogceDcSX0/wgRQoftUqoAvyobgwJAR61UTY8pXCYwe4/6ECYntXa1cQYYgILED0YOc5YLkJizyJpAvgVm9qlo6Edl53QGn2YHNvhdCmdPiFxyu5i2AQJAZpoVtYVEH2do6Yc3QIlRJr1SHGJ9uh43/DnGXuhbNWLKVI2nMYb695FmYl8VqixoVk9Cvsd7AnNRPFixWo8aaQ==";
/**
* 加密
*
* @param str 待加密信息
* @return 加密后内容
*/
public static String decrypt(String str) {
try {
RSA rsa = new RSA(PRIVATE_KEY, PUBLIC_KEY);
byte[] encrypt = rsa.encrypt(StrUtil.bytes(str, CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
return Base64.encode(encrypt);
} catch (Exception e) {
return "";
}
}
/**
* 解密
*
* @param str
* @return 解密后信息
*/
public static String encrypt(String str) {
RSA rsa = new RSA(PRIVATE_KEY, PUBLIC_KEY);
try {
byte[] decrypt = rsa.decrypt(str, KeyType.PrivateKey);
return StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8);
} catch (Exception e) {
return "";
}
}
public static void main(String[] args) {
// 使用hutool随机获取一对公私钥
RSA rsa = new RSA();
//获得私钥
System.out.println(rsa.getPrivateKey());
System.out.println(rsa.getPrivateKeyBase64());
//获得公钥
System.out.println(rsa.getPublicKey());
System.out.println(rsa.getPublicKeyBase64());
String a = decrypt("{\"idCardNumber\":\"123456789\",\"name\":\"Litong\"}");
System.out.println(a);
System.out.println(encrypt(a));
}
}
二.不可解密
摘要加密,顾名思义,无法还原数据本身内容,故无法解密。
当然,有一种解密,叫爆破解密,据说,量子计算机,可以分分钟暴力破解MD5,而这不是现在要考虑的(笑)。
1. MD5
SecureUtil.md5("idCardNumber:123456789");
2. SHA-256
SecureUtil.sha256("idCardNumber:123456789");
3…
等等,Hutool
实现的摘要加密算法有很多种,基本都是直接使用的,如上述。官网
MD2
MD5
SHA-1
SHA-256
SHA-384
SHA-512
HmacMD5
HmacSHA1
HmacSHA256
HmacSHA384
HmacSHA512
三. 前端
某些场景,需要我们跟前端一起进行加解密操作,如:防篡改。
1. AES
加密
// 密码
const key = '123456789ABCDEFG'
// 偏移量
const iv = '1234567898765432'
// 待解密内容
const text = '8e65a9a7a00503b1c1becb8d2922f77e'
// 解密
let decrypted = CryptoJS.AES.decrypt(
CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(text))
, CryptoJS.enc.Utf8.parse(key), {
iv: CryptoJS.enc.Utf8.parse(iv),
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
console.log(decrypted.toString(CryptoJS.enc.Utf8).toString())
console.log(decrypted.toString(CryptoJS.enc.Utf8).toString(CryptoJS.format.Hex))
2. RSA
加密
需要一个js加密工具类,下载地址。h5等端的可以直接使用。
微信小程序,需要加一下东西,适配。地址,密uehp。
//公钥
var PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOHrv6o1clkfaHTYwbmMuVrsmANDVrkIBrXdqzZjLjIo1Z0npQ0ZRRUsCYC4aee7jJxyVXYDEKzaVRVs6gMeAeZ4QiBsZUqxhHr9q9IrE+M7nknt6fotUt8LxiVnyRAjwLmSu503s4tGP15yudzPchyMC8+ZNphUQ8FtEtGIKOwQIDAQAB';
//使用公钥加密
var encrypt = new JSEncrypt();
encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----' + PUBLIC_KEY + '-----END PUBLIC KEY-----');
var str = {
"uid":"1223334",
"pwd":"asd"
}
var encrypted = encrypt.encrypt(JSON.stringify(str));
console.log('加密前数据:%o', str);
console.log('加密后数据:%o', encrypted);
3.摘要加密
大同小异,基本操作如下。
引入https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js
md5(pwd)