From 3aa978ae7174375e891b031a7f95cd2b8ac8c511 Mon Sep 17 00:00:00 2001 From: Yaser Hsueh Date: Tue, 3 Jan 2023 10:24:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BF=A1=E6=81=AF=E5=8A=A0?= =?UTF-8?q?=E5=AF=86=E5=B7=A5=E5=85=B7=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/simaek/util/EncryptUtil.java | 115 ++++++++++++++++++ .../java/com/simaek/util/EncryptUtilTest.java | 33 +++++ 2 files changed, 148 insertions(+) create mode 100644 src/main/java/com/simaek/util/EncryptUtil.java create mode 100644 src/test/java/com/simaek/util/EncryptUtilTest.java diff --git a/src/main/java/com/simaek/util/EncryptUtil.java b/src/main/java/com/simaek/util/EncryptUtil.java new file mode 100644 index 0000000..e7ecb48 --- /dev/null +++ b/src/main/java/com/simaek/util/EncryptUtil.java @@ -0,0 +1,115 @@ +package com.simaek.util; + +import javax.crypto.*; +import javax.crypto.spec.PBEKeySpec; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.util.Base64; + +/** + * 信息加密工具类,使用PBEWithMD5AndDES加密算法,可对有一定安全性要求的信息进行加密。 + * 安全性要求较高的信息请勿使用此工具进行加密。 + * + * @author Yaser Hsueh + */ +public final class EncryptUtil { + + private EncryptUtil() { + throw new AssertionError("No com.cicdi.utils.EncryptUtil instances for you!"); + } + + /** + * 随机字符生成 + */ + private static final SecureRandom RANDOM = new SecureRandom(); + /** + * 使用的加密算法 + */ + private static final String ALGORITHM = "PBEWithMD5AndDES"; + /** + * 迭代次数 + */ + private static final int ITERATIONS = 1000; + /** + * 盐值长度 + */ + private static final int SALT_LENGTH = 8; + + /** + * 使用PBEWithMD5AndDES算法对信息进行加密 + * + * @param message 需要加密的信息 + * @return 加密后的信息 + */ + public static String encrypt(String message, String password) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, BadPaddingException, InvalidKeyException { + return Base64.getEncoder().encodeToString(encrypt(message.getBytes(StandardCharsets.UTF_8), password)); + } + + /** + * 对使用PBEWithMD5AndDES算法加密后的信息进行解密 + * + * @param encryptedMessage 经过PBEWithMD5AndDES算法加密后的信息 + * @return 解密后的信息 + */ + public static String decrypt(String encryptedMessage, String password) throws InvalidAlgorithmParameterException, IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException { + return new String(decrypt(Base64.getDecoder().decode(encryptedMessage), password), StandardCharsets.UTF_8); + } + + private static byte[] encrypt(byte[] message, String password) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException { + // 创建Key + final SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); + byte[] salt = generateSalt(SALT_LENGTH); + final PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS); + SecretKey key = factory.generateSecret(keySpec); + // 构建Cipher. + final Cipher cipherEncrypt = Cipher.getInstance(ALGORITHM); + cipherEncrypt.init(Cipher.ENCRYPT_MODE, key); + // 保存参数 + byte[] params = cipherEncrypt.getParameters().getEncoded(); + // 加密信息 + byte[] encryptedMessage = cipherEncrypt.doFinal(message); + return ByteBuffer + .allocate(1 + params.length + encryptedMessage.length) + .put((byte) params.length) + .put(params) + .put(encryptedMessage) + .array(); + } + + private static byte[] decrypt(byte[] encryptedMessage, String password) throws BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchPaddingException { + int paramsLength = Byte.toUnsignedInt(encryptedMessage[0]); + int messageLength = encryptedMessage.length - paramsLength - 1; + byte[] params = new byte[paramsLength]; + byte[] message = new byte[messageLength]; + System.arraycopy(encryptedMessage, 1, params, 0, paramsLength); + System.arraycopy(encryptedMessage, paramsLength + 1, message, 0, messageLength); + // 创建Key + final SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM); + final PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray()); + SecretKey key = factory.generateSecret(keySpec); + // 构建参数 + AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(ALGORITHM); + algorithmParameters.init(params); + // 构建Cipher + final Cipher cipherDecrypt = Cipher.getInstance(ALGORITHM); + cipherDecrypt.init(Cipher.DECRYPT_MODE, key, algorithmParameters); + return cipherDecrypt.doFinal(message); + } + + /** + * 生成指定长度的随机字节数组 + * + * @param length 字节数组长度 + * @return 字节数组 + */ + private static byte[] generateSalt(int length) { + byte[] salt = new byte[length]; + synchronized (RANDOM) { + RANDOM.nextBytes(salt); + return salt; + } + } +} diff --git a/src/test/java/com/simaek/util/EncryptUtilTest.java b/src/test/java/com/simaek/util/EncryptUtilTest.java new file mode 100644 index 0000000..44b067f --- /dev/null +++ b/src/test/java/com/simaek/util/EncryptUtilTest.java @@ -0,0 +1,33 @@ +package com.simaek.util; + +import org.junit.jupiter.api.Test; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +/** + * @author Yaser Hsueh + */ +class EncryptUtilTest { + + @Test + void encrypt() throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, IOException, BadPaddingException, InvalidKeyException { + String password = "jlhs@2020"; + String message = "password"; + System.out.println(EncryptUtil.encrypt(message, password));; + } + + @Test + void decrypt() throws InvalidAlgorithmParameterException, IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException { + String password = "jlhs@2020"; + String encrypted = "DzANBAicaKn2c3D5oAIBCsKjPp8wXX1Ux4U/k0V0g657ShUc9L3uNA=="; + // String encrypted = "DzANBAjG4uTtrfjHwgIBClPDEU6MjlN+953giRz6WbM="; + System.out.println(EncryptUtil.decrypt(encrypted, password)); + } +} \ No newline at end of file