加密工具類:
package group.hound.starter.core.util; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.digest.DigestUtils; import org.springframework.util.StringUtils; import group.hound.starter.core.exception.ContentNotFoundSaltException; import group.hound.starter.core.exception.EncryptionException; /** * <p> * 加解密工具類 * </p> * * @author 廢柴 2018/9/13 星期四 11:56 */ @SuppressWarnings("all") public class EncryptionUtils { private static final String DEFAULT_CHARSET = "UTF-8"; private EncryptionUtils() { } /** * MD5 非對稱加密 */ public static class MD5 { /** * MD5 加密 * * @param content 加密內容 * @return 加密結果 */ public static String encrypt(String content) { return DigestUtils.md5Hex(content); } /** * MD5 加密 * * @param content 加密內容 * @return 加密結果 */ public static String encrypt(byte[] content) { return DigestUtils.md5Hex(content); } /** * MD5 加密 * * @param contentStream 加密內容 * @return 加密結果 */ public static String encrypt(InputStream contentStream) { try { return DigestUtils.md5Hex(contentStream); } catch (IOException e) { throw new EncryptionException("MD5 encrypt failed!", e); } } } /** * AES 對稱加密 */ public static class AES { private static final String ALGORITHM = "AES"; /** * 生成秘鑰 */ public static String generaterKey() { KeyGenerator keygen = null; try { keygen = KeyGenerator.getInstance(ALGORITHM); } catch (NoSuchAlgorithmException e) { throw new EncryptionException("AES generater Key failed!", e); } // 16 字節 == 128 bit keygen.init(128, new SecureRandom()); SecretKey secretKey = keygen.generateKey(); return Base64.getEncoder().encodeToString(secretKey.getEncoded()); } /** * 生成密鑰 */ private static SecretKeySpec getSecretKeySpec(String secretKeyStr) { return new SecretKeySpec(Base64.getDecoder().decode(secretKeyStr), ALGORITHM); } /** * 加密 */ public static String encrypt(String content, String secretKey) { Key key = getSecretKeySpec(secretKey); try { // 創建密碼器 Cipher cipher = Cipher.getInstance(ALGORITHM); // 初始化 cipher.init(Cipher.ENCRYPT_MODE, key); return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes(DEFAULT_CHARSET))); } catch (Exception e) { throw new EncryptionException("AES encrypt failed!", e); } } /** * 解密 */ public static String decrypt(String content, String secretKey) { Key key = getSecretKeySpec(secretKey); try { Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, key); return new String(cipher.doFinal(Base64.getDecoder().decode(content)), StandardCharsets.UTF_8); } catch (Exception e) { throw new EncryptionException("AES decrypt failed!", e); } } } @FunctionalInterface interface WithSalt { /** * 加鹽 * * @param content 加密內容 * @param salt 鹽 * @return 加鹽密文 */ String withSalt(String content, String salt); } private static final WithSalt DEFAULT_WITH_SALT = new WithSalt() { @Override public String withSalt(String content, String salt) { return content + salt; } }; @FunctionalInterface interface WithoutSalt { /** * 加鹽 * * @param content 加密內容 * @param salt 鹽 * @return 加鹽密文 */ String withoutSalt(String content, String salt); } private static final WithoutSalt DEFAULT_WITHOUT_SALT = new WithoutSalt() { @Override public String withoutSalt(String content, String salt) { if (!StringUtils.hasText(content)) { return content; } if (content.endsWith(salt)) { return content.substring(0, salt.length()); } throw new ContentNotFoundSaltException(content, salt); } }; /** * RSA 對稱加密 */ public static class RSA { private static final String ALGORITHM = "RSA"; private static final String ALGORITHMS_SHA1 = "SHA1WithRSA"; /** * 生成秘鑰對 * throw {@link NoSuchAlgorithmException} 找不到算法異常 * * @return first : 私鑰/second : 公鑰 */ public static Pair<String, String> generateKeyPair() { KeyPairGenerator keygen = null; try { keygen = KeyPairGenerator.getInstance(ALGORITHM); } catch (NoSuchAlgorithmException e) { throw new EncryptionException("RSA generate Key Pair failed!", e); } keygen.initialize(512, new SecureRandom()); // 生成密鑰對 KeyPair keyPair = keygen.generateKeyPair(); return Pair.of(Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()), Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded())); } /** * 生成秘鑰對 * * @param keySize 密鑰大小 * throw {@link NoSuchAlgorithmException} 找不到算法異常 * @return first : 私鑰/second : 公鑰 */ public static Pair<String, String> generateKeyPair(int keySize) { KeyPairGenerator keygen = null; try { keygen = KeyPairGenerator.getInstance(ALGORITHM); } catch (NoSuchAlgorithmException e) { throw new EncryptionException("RSA generate Key Pair failed!", e); } keygen.initialize(keySize, new SecureRandom()); // 生成密鑰對 KeyPair keyPair = keygen.generateKeyPair(); return Pair.of(Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()), Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded())); } /** * 獲取公鑰 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link NoSuchAlgorithmException} 找不到算法異常 * * @param publicKey 公鑰 * @return 公鑰 */ public static RSAPublicKey getPublicKey(String publicKey) { try { return (RSAPublicKey) KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey))); } catch (Exception e) { throw new EncryptionException("RSA get Public Key failed!", e); } } /** * 獲取私鑰 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link NoSuchAlgorithmException} 找不到算法異常 * * @param privateKey 私鑰 * @return 私鑰 */ public static RSAPrivateKey getPrivateKey(String privateKey) { try { return (RSAPrivateKey) KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); } catch (Exception e) { throw new EncryptionException("RSA get Private Key failed!", e); } } /** * 私鑰簽名內容 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link NoSuchAlgorithmException} 無效的 Key * throw {@link UnsupportedEncodingException} 不支持的編碼 * throw {@link SignatureException} 簽名異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * * @param content 內容 * @param privateKey 私鑰 * @return 私鑰簽名 */ public static String sign(String content, String privateKey) { try { Signature signature = Signature.getInstance(ALGORITHMS_SHA1); signature.initSign(getPrivateKey(privateKey)); signature.update(content.getBytes(DEFAULT_CHARSET)); return Base64.getEncoder().encodeToString(signature.sign()); } catch (Exception e) { throw new EncryptionException("RSA sign failed!", e); } } /** * 公鑰校驗簽名 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link NoSuchAlgorithmException} 無效的 Key * throw {@link UnsupportedEncodingException} 不支持的編碼 * throw {@link SignatureException} 簽名異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * * @param content 內容 * @param sign 簽名 * @param publicKey 公鑰 * @return 是否匹配 */ public static boolean verify(String content, String sign, String publicKey) { try { Signature signature = Signature.getInstance(ALGORITHMS_SHA1); signature.initVerify(getPublicKey(publicKey)); signature.update(content.getBytes(DEFAULT_CHARSET)); return signature.verify(Base64.getDecoder().decode(sign)); } catch (Exception e) { throw new EncryptionException("RSA verify failed!", e); } } /** * 使用公鑰或者私鑰加密 * <p> * throw {@link InvalidKeyException} 無效的 Key * throw {@link UnsupportedEncodingException} 不支持的解碼 * throw {@link BadPaddingException} 錯誤間隔異常 * throw {@link IllegalBlockSizeException} 無效塊大小異常 * throw {@link NoSuchPaddingException} 無效的監間距異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * * @param content 內容 * @param key 公鑰或者私鑰 * @return 密文 */ public static String encrypt(String content, Key key) { try { Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, key); return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes(DEFAULT_CHARSET))); } catch (Exception e) { throw new EncryptionException("RSA encrypt failed!", e); } } /** * 使用公鑰或者私鑰解密 * <p> * throw {@link InvalidKeyException} 無效的 Key * throw {@link BadPaddingException} 錯誤間隔異常 * throw {@link IllegalBlockSizeException} 無效塊大小異常 * throw {@link NoSuchPaddingException} 無效的監間距異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * * @param content 內容 * @param key 公鑰或者私鑰 * @return 明文 */ public static String decrypt(String content, Key key) { try { Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, key); return new String(cipher.doFinal(Base64.getDecoder().decode(content)), StandardCharsets.UTF_8); } catch (Exception e) { throw new EncryptionException("RSA decrypt failed!", e); } } /** * 使用公鑰加鹽加密 * * @param content 明文 * @param publicKey 公鑰 * @return 密文 */ public static String encrypt(String content, String publicKey) { return RSA.encrypt(content, null, publicKey, null); } /** * 使用公鑰加鹽加密 * * @param content 明文 * @param key 鹽 * @param publicKey 公鑰 * @return 密文 */ public static String encrypt(String content, String key, String publicKey) { return RSA.encrypt(content, key, publicKey, DEFAULT_WITH_SALT); } /** * 使用公鑰加鹽加密 * * @param content 明文 * @param key 鹽 * @param publicKey 公鑰 * @param withSalt 明文加鹽 * @return 密文 */ public static String encrypt(String content, String key, String publicKey, WithSalt withSalt) { return RSA.encrypt(withSalt != null ? withSalt.withSalt(content, key) : content, getPublicKey(publicKey)); } /** * 使用私鑰解密去鹽 * * @param content 密文 * @param privateKey 私鑰 * @return 明文 */ public static String decrypt(String content, String privateKey) { return decrypt(content, null, privateKey, null); } /** * 使用私鑰解密去鹽 * * @param content 密文 * @param key 鹽 * @param privateKey 私鑰 * @return 明文 */ public static String decrypt(String content, String key, String privateKey) { return decrypt(content, key, privateKey, DEFAULT_WITHOUT_SALT); } /** * 使用私鑰解密去鹽 * * @param content 密文 * @param key 鹽 * @param privateKey 私鑰 * @param withoutSalt 解密內容去鹽 * @return 明文 */ public static String decrypt(String content, String key, String privateKey, WithoutSalt withoutSalt) { return withoutSalt != null ? withoutSalt.withoutSalt(decrypt(content, getPrivateKey(privateKey)), key) : decrypt(content, getPrivateKey(privateKey)); } } /** * RSA2 對稱加密 */ public static class RSA2 { private static final String ALGORITHMS_SHA256 = "SHA256WithRSA"; /** * 生成秘鑰對 * <p> * throw {@link NoSuchAlgorithmException} 找不到算法異常 * * @return first : 私鑰/second : 公鑰 */ public static Pair<String, String> generateKeyPair() { return RSA.generateKeyPair(); } /** * 獲取公鑰 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link NoSuchAlgorithmException} 找不到算法異常 * * @param publicKey 公鑰 * @return 公鑰 */ private static RSAPublicKey getPublicKey(String publicKey) { return RSA.getPublicKey(publicKey); } /** * 獲取私鑰 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link NoSuchAlgorithmException} 找不到算法異常 * * @param privateKey 私鑰 * @return 私鑰 */ private static RSAPrivateKey getPrivateKey(String privateKey) { return RSA.getPrivateKey(privateKey); } /** * 私鑰簽名內容 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link InvalidKeyException} 無效的 Key * throw {@link UnsupportedEncodingException} 不支持的編碼 * throw {@link SignatureException} 簽名異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * * @param content 內容 * @param privateKey 私鑰 * @return 私鑰簽名 */ public static String sign(String content, String privateKey) { try { Signature signature = Signature.getInstance(ALGORITHMS_SHA256); signature.initSign(getPrivateKey(privateKey)); signature.update(content.getBytes(DEFAULT_CHARSET)); return Base64.getEncoder().encodeToString(signature.sign()); } catch (Exception e) { throw new EncryptionException("RSA2 sign failed!", e); } } /** * 公鑰校驗簽名 * <p> * throw {@link InvalidKeySpecException} 無效的 Key Spec * throw {@link InvalidKeyException} 無效的 Key * throw {@link UnsupportedEncodingException} 不支持的編碼 * throw {@link SignatureException} 簽名異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * throw {@link NoSuchPaddingException} 無效的監間距異常 * * @param content 內容 * @param sign 簽名 * @param publicKey 公鑰 * @return 是否匹配 */ public static boolean verify(String content, String sign, String publicKey) { try { Signature signature = Signature.getInstance(ALGORITHMS_SHA256); signature.initVerify(getPublicKey(publicKey)); signature.update(content.getBytes(DEFAULT_CHARSET)); return signature.verify(Base64.getDecoder().decode(sign)); } catch (Exception e) { throw new EncryptionException("RSA2 verify failed!", e); } } /** * 使用公鑰或者私鑰加密 * <p> * throw {@link IllegalBlockSizeException} 無效塊大小異常 * throw {@link InvalidKeyException} 無效的 Key * throw {@link UnsupportedEncodingException} 不支持的解碼 * throw {@link BadPaddingException} 錯誤間隔異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * throw {@link NoSuchPaddingException} 無效的監間距異常 * * @param content 內容 * @param key 公鑰或者私鑰 * @return 密文 */ public static String encrypt(String content, Key key) { return RSA.encrypt(content, key); } /** * 使用公鑰或者私鑰解密 * <p> * throw {@link IllegalBlockSizeException} 無效塊大小異常 * throw {@link InvalidKeyException} 無效的 Key * throw {@link BadPaddingException} 錯誤間隔異常 * throw {@link NoSuchAlgorithmException} 無效的算法 * throw {@link NoSuchPaddingException} 無效的監間距異常 * * @param content 內容 * @param key 公鑰或者私鑰 * @return 明文 */ public static String decrypt(String content, Key key) { return RSA.decrypt(content, key); } } }