介紹
Hutool工具是一個國產開源Java工具集,旨在簡化Java開發中繁瑣的過程,Hutool-crypto模塊便是針對JDK加密解密做了大大簡化。
此文主要介紹利用Hutool-crypto簡化非對稱加密解密。
對於非對稱加密,最常用的就是RSA和DSA,在Hutool中使用AsymmetricCrypto
對象來負責加密解密。
非對稱加密有公鑰和私鑰兩個概念,私鑰自己擁有,不能給別人,公鑰公開。根據應用的不同,我們可以選擇使用不同的密鑰加密:
-
簽名:使用私鑰加密,公鑰解密。用於讓所有公鑰所有者驗證私鑰所有者的身份並且用來防止私鑰所有者發佈的內容被篡改,但是不用來保證內容不被他人獲得。
-
加密:用公鑰加密,私鑰解密。用於向公鑰所有者發佈信息,這個信息可能被他人篡改,但是無法被他人獲得。
使用
引入Hutool
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.1.2</version>
</dependency>
在非對稱加密中,我們可以通過AsymmetricCrypto(AsymmetricAlgorithm algorithm)
構造方法,通過傳入不同的算法枚舉,獲得其加密解密器。
當然,爲了方便,我們針對最常用的RSA和DSA算法構建了單獨的對象:RSA
和DSA
。
基本使用
我們以RSA爲例,介紹使用RSA加密和解密 在構建RSA對象時,可以傳入公鑰或私鑰,當使用無參構造方法時,Hutool將自動生成隨機的公鑰私鑰密鑰對:
RSA rsa = new RSA();
//獲得私鑰
rsa.getPrivateKey()
rsa.getPrivateKeyBase64()
//獲得公鑰
rsa.getPublicKey()
rsa.getPublicKeyBase64()
//公鑰加密,私鑰解密
byte[] encrypt = rsa.encrypt(StrUtil.bytes("我是一段測試aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
Assert.assertEquals("我是一段測試aaaa", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));
//私鑰加密,公鑰解密
byte[] encrypt2 = rsa.encrypt(StrUtil.bytes("我是一段測試aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PrivateKey);
byte[] decrypt2 = rsa.decrypt(encrypt2, KeyType.PublicKey);
Assert.assertEquals("我是一段測試aaaa", StrUtil.str(decrypt2, CharsetUtil.CHARSET_UTF_8));
對於加密和解密可以完全分開,對於RSA對象,如果只使用公鑰或私鑰,另一個參數可以爲
null
自助生成密鑰對
有時候我們想自助生成密鑰對可以:
KeyPair pair = SecureUtil.generateKeyPair("RSA");
pair.getPrivate();
pair.getPublic();
自助生成的密鑰對是byte[]形式,我們可以使用Base64.encode
方法轉爲Base64,便於存儲爲文本。
當然,如果使用RSA
對象,也可以使用encryptStr
和decryptStr
加密解密爲字符串
案例
案例一:
已知私鑰和密文,如何解密密文?
String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIL7pbQ+5KKGYRhw7jE31hmA"
+ "f8Q60ybd+xZuRmuO5kOFBRqXGxKTQ9TfQI+aMW+0lw/kibKzaD/EKV91107xE384qOy6IcuBfaR5lv39OcoqNZ"
+ "5l+Dah5ABGnVkBP9fKOFhPgghBknTRo0/rZFGI6Q1UHXb+4atP++LNFlDymJcPAgMBAAECgYBammGb1alndta"
+ "xBmTtLLdveoBmp14p04D8mhkiC33iFKBcLUvvxGg2Vpuc+cbagyu/NZG+R/WDrlgEDUp6861M5BeFN0L9O4hz"
+ "GAEn8xyTE96f8sh4VlRmBOvVdwZqRO+ilkOM96+KL88A9RKdp8V2tna7TM6oI3LHDyf/JBoXaQJBAMcVN7fKlYP"
+ "Skzfh/yZzW2fmC0ZNg/qaW8Oa/wfDxlWjgnS0p/EKWZ8BxjR/d199L3i/KMaGdfpaWbYZLvYENqUCQQCobjsuCW"
+ "nlZhcWajjzpsSuy8/bICVEpUax1fUZ58Mq69CQXfaZemD9Ar4omzuEAAs2/uee3kt3AvCBaeq05NyjAkBme8SwB0iK"
+ "kLcaeGuJlq7CQIkjSrobIqUEf+CzVZPe+AorG+isS+Cw2w/2bHu+G0p5xSYvdH59P0+ZT0N+f9LFAkA6v3Ae56OrI"
+ "wfMhrJksfeKbIaMjNLS9b8JynIaXg9iCiyOHmgkMl5gAbPoH/ULXqSKwzBw5mJ2GW1gBlyaSfV3AkA/RJC+adIjsRGg"
+ "JOkiRjSmPpGv3FOhl9fsBPjupZBEIuoMWOC8GXK/73DHxwmfNmN7C9+sIi4RBcjEeQ5F5FHZ";
RSA rsa = new RSA(PRIVATE_KEY, null);
String a = "2707F9FD4288CEF302C972058712F24A5F3EC62C5A14AD2FC59DAB93503AA0FA17113A020EE4EA35EB53F"
+ "75F36564BA1DABAA20F3B90FD39315C30E68FE8A1803B36C29029B23EB612C06ACF3A34BE815074F5EB5AA3A"
+ "C0C8832EC42DA725B4E1C38EF4EA1B85904F8B10B2D62EA782B813229F9090E6F7394E42E6F44494BB8";
byte[] aByte = HexUtil.decodeHex(a);
byte[] decrypt = rsa.decrypt(aByte, KeyType.PrivateKey);
Assert.assertEquals("虎頭闖杭州,多擡頭看天,切勿只管種地", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));