All Downloads are FREE. Search and download functionalities are using the official Maven repository.

winter.com.ideaaedi.classwinter.util.EncryptUtil Maven / Gradle / Ivy

The newest version!
package winter.com.ideaaedi.classwinter.util;

import winter.com.ideaaedi.classwinter.author.JustryDeng;
import winter.com.ideaaedi.classwinter.exception.ClassWinterException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Random;

/**
 * 加解密工具类
 *
 * @author {@link JustryDeng}
 * @since 2021/4/23 20:34:09
 */
public final class EncryptUtil {
    
    /**
     * 盐
     */
    private static final char[] SALT = {'c', 'h', 'i', '@', 'm', 'i', 'a', 'n', '#', 'y', 'a', 'o', '%', 'f', 'a', 'n', 'g', '^', 'y', 'a', 'n'};
    
    /**
     * AES 算法/模式/补码方式
     */
    private static final String AES_MODE = "AES/ECB/PKCS5Padding";
    
    /**
     * 加密
     * 

* 与{@link EncryptUtil#decrypt(byte[], char[])}成对使用 *

* * @param source 要加密的内容 * @param password 用户密钥 * * @return 加密后的内容 */ public static byte[] encrypt(byte[] source, char[] password) { try { String pwd = md5(StrUtil.toBytes(StrUtil.mergeChar(password, SALT)), true, true); return encryptByAes(source, pwd.toCharArray()); } catch (NoSuchAlgorithmException e) { throw new ClassWinterException(e); } } /** * 解密 *

* 与{@link EncryptUtil#encrypt(byte[], char[])}成对使用 *

* * @param source 要解密的内容 * @param password 用户密钥 * * @return 解密后的内容 */ public static byte[] decrypt(byte[] source, char[] password) { try { String pwd = md5(StrUtil.toBytes(StrUtil.mergeChar(password, SALT)), true, true); return decryptByAes(source, pwd.toCharArray()); } catch (NoSuchAlgorithmException e) { throw new ClassWinterException(e); } } /** * 加密 *

* 与{@link EncryptUtil#decrypt(String, char[])}成对使用 *

* * @param source 要加密的内容 * @param password 用户密钥 * * @return 加密后的内容 */ public static String encrypt(String source, char[] password) { Objects.requireNonNull(source, "source cannot be null."); return Base64.getEncoder().encodeToString(encrypt(source.getBytes(StandardCharsets.UTF_8), password)); } /** * 解密 *

* 与{@link EncryptUtil#encrypt(String, char[])}成对使用 *

* * @param source 要解密的内容 * @param password 用户密钥 * * @return 解密后的内容 */ public static String decrypt(String source, char[] password) { Objects.requireNonNull(source, "source cannot be null."); return new String(decrypt(Base64.getDecoder().decode(source), password), StandardCharsets.UTF_8); } /** * 生成指定长度的随机字符串 * * @param length 长度 * * @return 字符数组 */ public static char[] generateCharArr(int length) { char[] result = new char[length]; Character[] chars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', '_', '+', '.' }; List list = Arrays.asList(chars); // "洗牌" Collections.shuffle(list); Random random = new SecureRandom(); for (int i = 0; i < length; i++) { if (i < chars.length) { result[i] = list.get(i); } else { result[i] = list.get(random.nextInt(chars.length)); } } return result; } /** * 进行MD5加密 *

* 摘录自 *

* 注:MD5加密得到的是长度固定的为126bit的二进制串(一堆0和1,一共128),为了更友好的表示结果, * 一般都将128位的二进制串转换为32个16进制位或16个16进制位。(16位的结果是取32位的结果值的中间部分,即32位中第8~24位的片段) * * @param source 要加密的内容 * @param abbreviation true-返回16位结果;false-返回32位结果 * @param upperCase true-结果大写;false-结果小写 * * @return MD5加密结果 * * @throws NoSuchAlgorithmException 无此算法时抛出 */ @SuppressWarnings("SameParameterValue") private static String md5(byte[] source, boolean abbreviation, boolean upperCase) throws NoSuchAlgorithmException { // 1. 获取MessageDigest对象 MessageDigest digest = MessageDigest.getInstance("md5"); // 2. 执行加密操作 // 在MD5算法这,得到的目标字节数组的特点是:长度固定为16 byte[] targetBytes = digest.digest(source); // 3. 声明字符数组 char[] characters = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; // 4. 遍历targetBytes StringBuilder builder = new StringBuilder(); for (byte b : targetBytes) { // 5. 取出b的高四位的值 // 先把高四位通过右移操作拽到低四位 int high = (b >> 4) & 15; // 6. 取出b的低四位的值 int low = b & 15; // 7. 以high为下标从characters中取出对应的十六进制字符 char highChar = characters[high]; // 8. 以low为下标从characters中取出对应的十六进制字符 char lowChar = characters[low]; builder.append(highChar).append(lowChar); } String result = builder.toString(); if (abbreviation) { result = result.substring(8, 24); } if (upperCase) { result = result.toUpperCase(Locale.ENGLISH); } return result; } /** * AES加密 * * @param source 要加密的内容 * @param key 密钥 * * @return 加密后的内容 */ private static byte[] encryptByAes(byte[] source, char[] key) { try { byte[] raw = StrUtil.toBytes(key); SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance(AES_MODE); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec); return cipher.doFinal(source); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new ClassWinterException(e); } } /** * AES解密 * * @param source 要解密的内容 * @param key 密钥 * * @return 解密后的内容 */ private static byte[] decryptByAes(byte[] source, char[] key) { try { byte[] raw = StrUtil.toBytes(key); SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance(AES_MODE); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); return cipher.doFinal(source); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new ClassWinterException(e); } } /** * 测试 */ public static void main(String[] args) { // // => 测试一 // String originStr = "嘿~boy~"; // byte[] encryptedContent = encrypt(originStr.getBytes(StandardCharsets.UTF_8), "好想吃烧烤JustryDeng123.. // .".toCharArray()); // String plaintext = new String(decrypt(encryptedContent, "好想吃烧烤JustryDeng123...".toCharArray()), // StandardCharsets.UTF_8); // System.err.println("原文:" + originStr); // System.err.println("加密后:" + encryptedContent); // ///System.err.println("加密后:" + new String(Base64.getEncoder().encode(encryptedContent))); // System.err.println("解密后:" + plaintext); // => 测试二 String originStr = "嘿~boy~"; String encryptedContent = encrypt(originStr, "好想吃烧烤JustryDeng123...".toCharArray()); String plaintext = decrypt(encryptedContent, "好想吃烧烤JustryDeng123...".toCharArray()); System.err.println("原文:" + originStr); System.err.println("加密后:" + encryptedContent); System.err.println("解密后:" + plaintext); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy