Java加密算法工具类(AES、DES、MD5、RSA)

2023-12-28 12:24:00

整理了有关加密算法工具类,结合了几个博客以及自己改良后可直接使用,主要介绍以下四种加密方式:AES、DES、MD5、RSA,详细介绍都在注释里面有讲。

一、AES

import com.alibaba.fastjson.JSONObject;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;
import javax.crypto.*;
import javax.crypto.spec.*;

/**
 * AES-对称加密算法(ECB、CBC模式)
 */
public class AESUtil {

    // 128位密钥 = 16 bytes Key:
    public static String key128 = "zhangximing";

    public static void main(String[] args) throws GeneralSecurityException {
        JSONObject param = new JSONObject();
        param.put("billCode", "FBX123456");
        param.put("remark","测试xxx");
        String message = param.toJSONString();
        byte[] data = message.getBytes(StandardCharsets.UTF_8);

        //对于ECB工作模式,我们使用"AES/ECB/PKCS5Padding"作为加密模式,
        //对于CBC工作模式,我们使用"AES/CBC/PKCS5Padding"作为加密模式。
        //加密后的密文将以Base64编码的形式输出。
        /**
         * ECB(Electronic Codebook)工作模式是AES加密算法的一种,它将明文分为固定大小的块,对每个块进行加密,然后将所有块的密文进行拼接,形成密文。
         * 这种模式的主要优点是简单、并行化处理和错误传播有限;缺点是容易受到密码本重放攻击的影响,不适用于加密大量数据。
         */
        //ECB工作模式
        // 加密:
        byte[] encrypted = encryptECB(key128, data);
        String encodeToString = Base64.getEncoder().encodeToString(encrypted);
        System.out.println("Encrypted: " + encodeToString);
        // 解密:
        byte[] decrypted = decryptECB(key128, Base64.getDecoder().decode(encodeToString));
        System.out.println("Decrypted: " + new String(decrypted, StandardCharsets.UTF_8));

        /**
         * CBC(Cipher Block Chaining)工作模式也是AES加密算法的一种,它将明文分为固定大小的块,对每个块进行加密,并将前一个加密块与当前块进行异或操作,然后将所有块的密文进行拼接,形成密文。
         * 这种模式的主要优点是能够抵御密码本重放攻击,适用于加密大量数据;缺点是需要额外的初始向量(IV)来确保加密的随机性,如果IV被泄露或者被攻击者捕获,可能会导致整个加密消息被解密。
         */
        //CBC工作模式
        // 加密:
        byte[] encrypted2 = encryptCBC(key128,data);
        System.out.println("Encrypted: " + Base64.getEncoder().encodeToString(encrypted2));
        // 解密:
        byte[] decrypted2 = decryptCBC(key128, encrypted2);
        System.out.println("Decrypted: " + new String(decrypted2, StandardCharsets.UTF_8));

    }

    // String类型加密:
    public static String encryptECB(String key, String input) throws GeneralSecurityException {
        byte[] bytes = AESUtil.encryptECB(key, input.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(bytes);
    }

    // 加密:
    public static byte[] encryptECB(String key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        return cipher.doFinal(input);
    }

    // 解密:
    public static String decryptECB(String key, String input) throws GeneralSecurityException {
        byte[] bytes = AESUtil.decryptECB(key128, Base64.getDecoder().decode(input));
        return new String( bytes, StandardCharsets.UTF_8);
    }
    // 解密:
    public static byte[] decryptECB(String key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return cipher.doFinal(input);
    }


    // 加密:
    public static byte[] encryptCBC(String key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        // CBC模式需要生成一个16 bytes的initialization vector:
        SecureRandom sr = SecureRandom.getInstanceStrong();
        byte[] iv = sr.generateSeed(16);
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
        byte[] data = cipher.doFinal(input);
        // IV不需要保密,把IV和密文一起返回:
        return join(iv, data);
    }

    // 解密:
    public static byte[] decryptCBC(String key, byte[] input) throws GeneralSecurityException {
        // 把input分割成IV和密文:
        byte[] iv = new byte[16];
        byte[] data = new byte[input.length - 16];
        System.arraycopy(input, 0, iv, 0, 16);
        System.arraycopy(input, 16, data, 0, data.length);
        // 解密:
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
        return cipher.doFinal(data);
    }

    public static byte[] join(byte[] bs1, byte[] bs2) {
        byte[] r = new byte[bs1.length + bs2.length];
        System.arraycopy(bs1, 0, r, 0, bs1.length);
        System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
        return r;
    }

}

二、DES

import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import com.alibaba.fastjson.JSONObject;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * DES是一种对称加密算法,所谓对称加密算法:加密和解密使用相同的秘钥的算法
 *
 */
public class DESUtil {

	private static Key key;
	//设置秘钥key
	private static String KEY_STR="guoyi";
	private static String CHARSETNAME="UTF-8";
	private static String ALGORITHM="DES";

	static{
		try{
			//生成DES算法对象
			KeyGenerator generator=KeyGenerator.getInstance(ALGORITHM);
			//运用SHA1安全策略
			SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG");
			//设置上密钥种子
			secureRandom.setSeed(KEY_STR.getBytes());
			//初始化基于SHA1的算法对象
			generator.init(secureRandom);
			//生成密钥对象
			key=generator.generateKey();
			generator=null;
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获取加密的信息
	 * @param str
	 * @return
	 */
	public static String getEncryptString(String str){
		//基于BASE64编码,接收byte[]并转换成String
		BASE64Encoder base64Encoder=new BASE64Encoder();
		try {
			// 按UTF8编码
			byte[] bytes = str.getBytes(CHARSETNAME);
			// 获取加密对象
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			// 初始化密码信息
			cipher.init(Cipher.ENCRYPT_MODE, key);
			// 加密
			byte[] doFinal = cipher.doFinal(bytes);
			// byte[]to encode好的String并返回
			return base64Encoder.encode(doFinal);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 获取解密之后的信息
	 *
	 * @param str
	 * @return
	 */
	public static String getDecryptString(String str) {
		// 基于BASE64编码,接收byte[]并转换成String
		BASE64Decoder base64decoder = new BASE64Decoder();
		try {
			// 将字符串decode成byte[]
			byte[] bytes = base64decoder.decodeBuffer(str);
			// 获取解密对象
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			// 初始化解密信息
			cipher.init(Cipher.DECRYPT_MODE, key);
			// 解密
			byte[] doFinal = cipher.doFinal(bytes);
			// 返回解密之后的信息
			return new String(doFinal, CHARSETNAME);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static void main(String[] args) {
		JSONObject param = new JSONObject();
		param.put("billCode", "FBX123456");
		param.put("remark","测试xxx");
		//加密
		String encryptString = getEncryptString(param.toJSONString());
		System.out.println(encryptString);
		//解密
		System.out.println(getDecryptString(encryptString));
	}
}

三、MD5

import com.alibaba.fastjson.JSONObject;
import java.security.MessageDigest;

/**
 * MD5加密(不可逆,一般用于校验)
 */
public class MD5Util {

	/**
	 * 对传入的String进行MD5加密
	 *
	 * @param s
	 * @return
	 */
	public static final String getMd5(String s) {
		// 16进制数组
		char hexDigits[] = { '5', '0', '5', '6', '2', '9', '6', '2', '5', 'q', 'b', 'l', 'e', 's', 's', 'y' };
		try {
			char str[];
			// 将传入的字符串转换成byte数组
			byte strTemp[] = s.getBytes();
			// 获取MD5加密对象
			MessageDigest mdTemp = MessageDigest.getInstance("MD5");
			// 传入需要加密的目标数组
			mdTemp.update(strTemp);
			// 获取加密后的数组
			byte md[] = mdTemp.digest();
			int j = md.length;
			str = new char[j * 2];
			int k = 0;
			// 将数组做位移
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			// 转换成String并返回
			return new String(str);
		} catch (Exception e) {
			return null;
		}
	}

	public static void main(String[] args) {
		JSONObject param = new JSONObject();
		param.put("billCode", "FBX123456");
		param.put("remark","测试xxx");
		String content = param.toJSONString();
		System.out.println(MD5Util.getMd5(content));//5y6y9590ssq2bss56ss6b5eybs6595b5
	}
}

四、RSA

import com.alibaba.fastjson.JSONObject;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA 是一种基于公钥加密算法,它可以在不共享密钥的情况下,使用公钥加密信息,并使用私钥解密信息。
 * 一般来说是公钥加密,私钥解密。因为公钥用于公开给多个人,而私钥是个人的,然后私钥加密的一般用于加签的形式,但是容易信息泄漏,因为含明文(RSA加签在许多应用场景中都有广泛应用,例如数字证书、电子签名等。)。
 * 加密:公钥放在客户端,使用公钥对数据进行加密,服务端拿到数据后用私钥进行解密。
 * 加签:私钥放在客户端,使用私钥对数据进行加签,服务端拿到数据后用公钥进行验签。
 */
public class RSAUtil {

    private final static String RSA_ALGORITHM = "RSA";
    private final static String SIGNATURE_ALGORITHM = "MD5withRSA";
    private final static String RSA_PUBLIC_KEY = "RSAPublicKey";
    private final static String RSA_PRIVATE_KEY = "RSAPrivateKey";

    //base64对二进制数据进行编码解码
    public static String encodeBase64(byte[] binaryData) {
        Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encodeToString(binaryData);
    }

    public static byte[] decodeBase64(String encoded) {
        Base64.Decoder decoder = Base64.getDecoder();
        return decoder.decode(encoded);
    }

    //生成密钥对
    public static Map<String,Object> getKey() throws NoSuchAlgorithmException {
        // 因为只存公钥和私钥,所以指明Map的长度是2
        Map<String,Object> keyMap = new HashMap<String,Object>(2);

        // 获取RSA算法实例
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA_ALGORITHM);

        // 1024代表密钥二进制位数
        keyPairGen.initialize(1024);

        // 产生KeyPair工厂
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        keyMap.put(RSA_PUBLIC_KEY, publicKey);
        keyMap.put(RSA_PRIVATE_KEY, privateKey);

        return keyMap;
    }

    /**
     * 使用私钥对数据进行加密
     */
    public static byte[] encryptPrivateKey(byte[] binaryData, String privateKey) throws Exception {
        byte[] keyBytes = decodeBase64(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        Key priKey = keyFactory.generatePrivate(keySpec);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, priKey);
        return cipher.doFinal(binaryData);
    }

    /**
     * 使用公钥对数据进行加密
     */
    public static byte[] encryptPublicKey(byte[] binaryData, String publicKey) throws Exception {
        byte[] keyBytes = decodeBase64(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        Key pubKey = keyFactory.generatePublic(keySpec);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return cipher.doFinal(binaryData);
    }

    /**
     * 使用私钥对数据进行解密
     */
    public static byte[] decryptPrivateKey(byte[] binaryData, String privateKey) throws Exception {
        byte[] keyBytes = decodeBase64(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        Key priKey = keyFactory.generatePrivate(keySpec);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return cipher.doFinal(binaryData);
    }

    /**
     * 使用公钥对数据进行解密
     */
    public static byte[] decryptPublicKey(byte[] binaryData, String publicKey) throws Exception {
        byte[] keyBytes = decodeBase64(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        Key pubKey = keyFactory.generatePublic(x509KeySpec);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, pubKey);
        return cipher.doFinal(binaryData);
    }

    /**
     * 使用私钥对数据进行签名
     */
    public static String sign(byte[] binaryData, String privateKey)
            throws Exception {
        byte[] keyBytes = decodeBase64(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PrivateKey priKey = keyFactory.generatePrivate(keySpec);

        // 获取签名算法
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(priKey);
        signature.update(binaryData);
        return encodeBase64(signature.sign());
    }


    /**
     * 使用公钥对数据签名进行验证
     */
    public static boolean verify(byte[] binaryData, String publicKey, String sign)
            throws Exception {
        byte[] keyBytes = decodeBase64(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PublicKey pubKey = keyFactory.generatePublic(keySpec);

        // 获取签名算法
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(pubKey);
        signature.update(binaryData);
        return signature.verify(decodeBase64(sign));
    }

    //公钥
    public static String getPublicKey(Map<String,Object> map){
        RSAPublicKey rsaPublicKey = (RSAPublicKey) map.get(RSA_PUBLIC_KEY);
        byte[] publicKeyBytes = rsaPublicKey.getEncoded();
        return encodeBase64(publicKeyBytes);
    }
    //密钥
    public static String getPrivateKey(Map<String,Object> map){
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) map.get(RSA_PRIVATE_KEY);
        byte[] privateKeyBytes = rsaPrivateKey.getEncoded();
        return encodeBase64(privateKeyBytes);
    }


    //测试
    public static void main(String[] args) throws Exception {
        // 1.获取公钥私钥
        Map<String,Object> map = getKey();
        System.out.println("公钥:"+getPublicKey(map));
        System.out.println("私钥:"+getPrivateKey(map));

        JSONObject param = new JSONObject();
        param.put("billCode", "FBX123456");
        param.put("remark","测试xxx");
        String content = param.toJSONString();

        System.out.println("============   分隔符     ===========");
        // 2.使用私钥加密
        byte[] encodeContent = encryptPrivateKey(content.getBytes(),getPrivateKey(map));
        //转字符串
        String encodeContentStr = Base64.getEncoder().encodeToString(encodeContent);
        //翻转字节数组
        byte[] encodeContentB = Base64.getDecoder().decode(encodeContentStr);
        System.out.println("私钥加密后的数据:"+ encodeContentStr);

        // 3.使用公钥解密
        byte[] decodeContent = decryptPublicKey(encodeContentB,getPublicKey(map));
        System.out.println("公钥解密后的数据:"+new String(decodeContent));

        System.out.println("============   分隔符     ===========");
        // 4.使用公钥加密
        byte[] encodeContent2 = encryptPublicKey(content.getBytes(),getPublicKey(map));
        //转字符串
        String encodeContentStr2 = Base64.getEncoder().encodeToString(encodeContent2);
        //翻转字节数组
        byte[] encodeContentB2 = Base64.getDecoder().decode(encodeContentStr2);
        System.out.println("公钥加密后的数据:"+encodeContentStr2);

        // 5.使用私钥解密
        byte[] decodeContent2 = decryptPrivateKey(encodeContentB2,getPrivateKey(map));
        System.out.println("私钥解密后的数据:"+new String(decodeContent2));

        System.out.println("============   分隔符     ===========");
        // 6.加签
        String sign = sign(content.getBytes(),getPrivateKey(map));
        System.out.println("加签后的数据:"+sign);

        // 7.验签
        boolean result = verify(content.getBytes(),getPublicKey(map),sign);
        System.out.println("验签结果:"+result);
    }
}

运行结果:

公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbLgxOXD+GOmjuPCxdJiiSvgkGxILKUw0+P7OmpJ2YPgrLZIQqTzdyleAlOYkan5/r3Yh0O8A8Ysp9iXRBLdWgUML9y4DBBO3esUP4uiNlJ/iRHVjvcSjLgpi2dH4iXABiYmjDGZ+Ly31R8KoFa+xmO/G9CkkU/vpoL9WrNYUyiwIDAQAB
私钥:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANsuDE5cP4Y6aO48LF0mKJK+CQbEgspTDT4/s6aknZg+CstkhCpPN3KV4CU5iRqfn+vdiHQ7wDxiyn2JdEEt1aBQwv3LgMEE7d6xQ/i6I2Un+JEdWO9xKMuCmLZ0fiJcAGJiaMMZn4vLfVHwqgVr7GY78b0KSRT++mgv1as1hTKLAgMBAAECgYEAsKqQPsU6at4/3+9erwJn58gHjI3vAlgpL4i3LNY5NRKlLsZphZTuk4zc7ARRT8VkaQDa0R2sWMAkiUW3ECZ6rkzCShSB1WZvJ/vIRGQEXamVuTwDTDzcSsZow7uW3d6TVbZ+RDmFxhUd27BEqZemPX8YtmLPv8X92S9uA2deJgkCQQD4N8gNGcbNM+bcjv610aTieQwEJTr1CoUmSTGifF7uYP6vSKwzX7LhANLIy4ogZ4oQiaS/oxuHF20KUV7WBHVXAkEA4g00deOd9Z8oLUFcN/xaYWzC3UpxL13YFkQZu3vWMgNzwsTaAg/LXxOE/C8OGCK5Vp58dvOZEbOjQ67w1hxX7QJADx2egiW6tI5flbjjjAD7UItcjvgRchC08RLuAd4fDdc8S0Jasjo2s3sQWwgCHl0PzFgFf2IYcA6eJk20P8Y/uwJBANdqCAUT3LJ1cf72WyAK/kH7OBNTXlrqDgLh8LemQi809Pq1Rp9SV9aJrl/3o3HCnWX679cXOlYRHtNgAae4KN0CQAPbFAlGBj1SX9M4imTH2EN+HcKQeXykCgs8/7lp8mp2sX4bwvMYpRhSDP0J8kpjcSF3TO5CldrV/iWAsqeJxDA=
============   分隔符     ===========
私钥加密后的数据:zSB0VYpAtzhfLUbmILcahTAG/6t60XUZ/lN7GKWrlDhM27yZaRx3pXh0cdZFLnsfe6zEKEzZ+iMTrDcXxVsrK2GfBrUmBtXi+gniaAUUPw/F/yMH3pX25P2kvFhLRxkLleUuoe2vqTEtWnu5ta3ueOW7kfVii8TGUOID8y1vJI0=
公钥解密后的数据:{"billCode":"FBX123456","remark":"测试xxx"}
============   分隔符     ===========
公钥加密后的数据:yVT+6AHk4dMKhBUCiUTVNRY6tE7hUtkIeDV6fQ5xrL6ZzHfR2OdvrnXOArAaglE6QVmQhteNm9eC9xa3cRAbk2jboAWJ2OGda5DDj2qjnem1Z7ykn4GnqOfHxbxCvpKtDM6B5iNQKmCskIhR/44Z5g7JFEaMXVJSqF/JJWxer+4=
私钥解密后的数据:{"billCode":"FBX123456","remark":"测试xxx"}
============   分隔符     ===========
加签后的数据:De656tVltViMDPm3LEwivqH0i6kwukvZQQCRfkMxXRtNAKnpSGvRZ4axNXi9FIB5VO+nmHv5ujHllfKfVKaC6AGrMe18CaIoaxp1ekr+l7Um1N2L1hR6S6/KdwETuEPj9u2HkcDp0OMZkBQe/EJhM3v7HCd3gEhSsDY/uguWrms=
验签结果:true

文章来源:https://blog.csdn.net/weixin_43316702/article/details/135265491
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。