欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java加密技术(Jasypt、MD5、AES)

程序员文章站 2024-03-16 20:07:34
...
java加解密算法有很多,在此记录常用的三种Jasypt、MD5、AES加密算法的使用;

(1) Jasypt

  • Jasypt 加密, 通常用于加密配置文件中的密码,比如mysql密码、redis密码等;
<!--  jasypt 加解密-->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>2.1.1</version>
</dependency>
配置:
# 加密的盐
jasypt:
  encryptor:
    password: qwetqweyiquq

# ENC(加密后的密文)
redis:
	password: ENC(VPSapwY1AJzmHZQjWq62KpBiMDu7W37M)
测试代码:
@Test
public void testJasypt(){
    BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
    //加密所需的salt(盐)
    textEncryptor.setPassword("qwetqweyiquq");
    //要加密的数据(数据库的用户名或密码)
    String username = textEncryptor.encrypt("root");
    String password = textEncryptor.encrypt("123456");
    System.out.println("username:" + username);
    System.out.println("password:" + password);

    // 解密
    String realUsername = textEncryptor.decrypt(username);
    String realPassword = textEncryptor.decrypt(password);
    System.out.println("realUsername:" + realUsername);
    System.out.println("realPassword:" + realPassword);
}

(2)MD5 加密算法

  • MD5 是一种单向加密算法,只能加密不能解密。

  • 常用于用户登录密码的加密。

  • 防止被在线解密方案:可以在得到MD5加密后的密文进行进一步处理,如截取前16位保存后16位用随机码补充,不允许设置简单密码等。


import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
/**
 * MD5加密工具类
 * @author cxq
 * @date 2021/6/25
 */
public class MD5Util {
    //用来将字节转换成16进制表示的字符
    private static char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    /**
     * 私有构造函数,防止实例化使用
     */
    private MD5Util() {}

    /**
     * 对参数进行MD5加密
     * @param bytes 要加密的参数
     * @return MD5值
     */
    public static String getMD5(byte[] bytes) {
        String result = null;
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            byte[] temp = md.digest(); //MD5的计算结果是一个128位长整数,用字节表示就是16字节
            char[] chars = new char[32]; //每个字节用16进制表示的话,需要2个字符,所以共32个字符

            //对MD5的每个字节转换成16进制的字符
            int k = 0;
            for (int i = 0; i < 16; i++) {
                byte aByte = temp[i];
                chars[k++] = hexDigits[aByte >>> 4 & 0xf];
                chars[k++] = hexDigits[aByte & 0xf];
            }

            result = new String(chars);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 对参数进行MD5加密
     * @param str 要加密的参数
     * @return MD5值
     */
    public static String getMD5(String str) {
        return getMD5(str.getBytes());
    }

    /**
     * 计算文件的MD5加密值,注意如果文件较大、计算MD5时可能性能较差
     * @param file 文件
     * @return MD5值
     */
    public static String getFileMD5(File file) {
        FileInputStream in = null;
        String result = null;
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            in = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            while (in.read(buffer) != -1) {
                md.update(buffer);
            }
            BigInteger bigInt = new BigInteger(1, md.digest());
            result = bigInt.toString(16);
        } catch (Exception e) {
            throw new RuntimeException("MD5加密异常");
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e) {
                throw new RuntimeException("MD5加密时,流关闭异常");
            }
        }
        return result;
    }

    /**
     * 计算文件的MD5加密值
     * @param fileName 文件名
     * @return MD5值
     */
    public static String getFileMD5(String fileName) {
        File file = new File(fileName);
        return getFileMD5(file);
    }

    public static void  main(String[] arg){
        String md5 = getMD5("111111");
        System.out.println(md5);
    }
}

(3)AES 对称加解密算法

  • AES高级加密标准,是一种区块加密标准。这个标准用来替代原先的DES,比DES安全级别高,已经被多方分析且广为全世界所使用。
  • AES加密算法,速度快,安全级别高:目前是最安全的加密算法之一。
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

/**
 * AES 加密工具类
 * @author cxq
 * @date 2021/6/25
 */
public class AESUtil {
    //自己定义的秘钥,128bit即16位的随机串。也支持192,25bit,长度越长安全性越高,对应的加解密时间越长
    private final static String KEY_STR = "gOZ+l59TRoBajn3G";// 可以写进配置
    private final Key key;
    private static AESUtil instance = new AESUtil();
    private static final String ALGORITHM = "AES";
    private static final String RANDOM_ALGORITHM = "SHA1PRNG";

    /**
     * 私有构造函数,防止通过实例化使用
     */
    private AESUtil() {
        try {
            KeyGenerator generator = KeyGenerator.getInstance(ALGORITHM);//Java的秘钥生产器,使用的是AES
            SecureRandom random = SecureRandom.getInstance(RANDOM_ALGORITHM);//随机数的算法,NativePRNG和SHA1PRNG
            random.setSeed(KEY_STR.getBytes());//用我们设定的秘钥串作为随机数的种子,因为种子是我们固定的,产生的随机数也是固定的
            generator.init(random);
            key = generator.generateKey();//生成的秘钥,我们在加密解密需要用到相同秘钥
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("AES构造函数异常");
        }
    }

    public static AESUtil getInstance() {
        return instance;
    }

    /**
     * 对byte[]参数进行加密
     * @param bytes 要加密的参数
     * @return 加密后的参数
     */
    private byte[] getEncCode(byte[] bytes) {
        byte[] result = null;
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES");//获取算法实例
            cipher.init(Cipher.ENCRYPT_MODE, key);//初始化,入参为加密模式和秘钥
            result = cipher.doFinal(bytes);//进行加密
        } catch (Exception e) {
            throw new RuntimeException("AES加密异常");
        } finally {
            cipher = null;
        }
        return result;
    }

    /**
     * 对byte[]参数进行解密
     * @param bytes 要解密的参数
     * @return 解密后的参数
     */
    private byte[] getDesCode(byte[] bytes) {
        byte[] result = null;
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("AES");//获取算法实例
            cipher.init(Cipher.DECRYPT_MODE, key);//初始化,入参为解密模式和秘钥
            result = cipher.doFinal(bytes);//进行解密
        } catch (Exception e) {
            throw new RuntimeException("AES解密异常");
        } finally {
            cipher = null;
        }
        return result;
    }

    /**
     * 对string参数进行加密
     * @param str 要加密的参数
     * @return 加密后的参数
     */
    public String getEncString(String str) {
        BASE64Encoder base64en = new BASE64Encoder();
        byte[] input = null; //明文
        byte[] output = null; //密文
        String result = null;
        try {
            input = str.getBytes();
            output = getEncCode(input);
            result = base64en.encode(output);

        } catch (Exception e) {
            throw new RuntimeException("AES解密异常,参数:" + str);
        } finally {
            input = null;
            output = null;
        }
        return result;
    }

    /**
     * 对String参数进行解密
     * @param str 要解密的参数
     * @return 解密后的参数
     */
    public String getDesString(String str) {
        BASE64Decoder base64De = new BASE64Decoder();
        byte[] input = null; //密文
        byte[] output = null; //明文
        String result = null;
        try {
            input = base64De.decodeBuffer(str);
            output = getDesCode(input);
            result = new String(output);

        } catch (Exception e) {
            throw new RuntimeException("AES解密异常,参数:" + str);
        } finally {
            input = null;
            output = null;
        }
        return result;
    }
}