加密解密篇
在某些場景,加密是必須的操作,如:數據庫用戶信息,密碼,關鍵業務信息等。
在我看來,加密分爲兩種,分別有他們對應的場景。
- 可解密:需要回顯,處理等的數據,如:用戶姓名。
- 不可解密:不需要回顯,只需判斷的,如:用戶密碼。
文章目錄
一.可解密
可解密的算法有很多種,我不是從事這個領域的專業人員,故不對概念做闡述,目前來看,會用、知道是什麼加密即可。
觀前警告
本篇文章加密算法,後端均依賴於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. RES
加密
RES加密,需要兩組祕鑰,分別是公鑰和私鑰。一般,我們使用公鑰進行加密,公私鑰進行解密。當然,也可以私鑰加密,公鑰解密。實際可以根據需求而定,而私鑰往往存在服務器,以防暴露。
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 MyRESUtil {
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. RES
加密
需要一個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)