JAVA各种加密与解密方式

2023-11-11

        之前有兴趣研究了一下java的加密与解密的方法,发现市面上有好多种加密解密方式,在这里整理了一下。

目录

1.BASE64加密/解密

 

2.MD5(Message Digest Algorithm)加密

 

3.DES(Data Encryption Standard)对称加密/解密

 

4.AES(Advanced Encryption Standard) 加密/解密

 

5.HMAC(Hash Message Authentication Code,散列消息鉴别码)

 

6.恺撒加密

 

7.SHA(Secure Hash Algorithm,安全散列算法)

 

8.RSA 加密/解密

 

9.PBE 加密/解密


 

1.BASE64加密/解密

      Base64 编码是我们程序开发中经常使用到的编码方法,它用 64 个可打印字符来表示二进制数据。这 64 个字符是:小写字母 a-z、大写字母 A-Z、数字 0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是 65 个字符),其他所有符号都转换成这个字符集中的字符。Base64 编码通常用作存储、传输一些二进制数据编码方法,所以说它本质上是一种将二进制数据转成文本数据的方案。

      通常用作对二进制数据进行加密,示例:

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Base64Util {

	/***
	 * BASE64解密
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryBASE64(String key) throws Exception{
		return (new BASE64Decoder()).decodeBuffer(key);
	}
	
	/***
	 * BASE64加密
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static String encryptBASE64(byte[] key) throws Exception{
		return (new BASE64Encoder()).encode(key);
	}
	
}

 

2.MD5(Message Digest Algorithm)加密

       MD5 是将任意长度的数据字符串转化成短小的固定长度的值的单向操作,任意两个字符串不应有相同的散列值。因此 MD5 经常用于校验字符串或者文件,因为如果文件的 MD5 不一样,说明文件内容也是不一样的,如果发现下载的文件和给定的 MD5 值不一样,就要慎重使用。

       MD5 主要用做数据一致性验证、数字签名和安全访问认证,而不是用作加密。比如说用户在某个网站注册账户时,输入的密码一般经过 MD5 编码,更安全的做法还会加一层盐(salt),这样密码就具有不可逆性。然后把编码后的密码存入数据库,下次登录的时候把密码 MD5 编码,然后和数据库中的作对比,这样就提升了用户账户的安全性。

    是一种单向加密算法,只能加密不能解密,示例:

import java.security.MessageDigest;

public class MD5Util {

	public static final String KEY_MD5 = "MD5";  
	
	/***
	 * MD5加密(生成唯一的MD5值)
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryMD5(byte[] data) throws Exception {
		MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
		md5.update(data);
		return md5.digest();
	}
	
}

 

3.DES(Data Encryption Standard)对称加密/解密

       DES 是一种对称加密算法,所谓对称加密算法就是:加密和解密使用相同密钥的算法。DES 加密算法出自 IBM 的研究,后来被美国政府正式采用,之后开始广泛流传。但近些年使用越来越少,因为 DES 使用 56 位密钥,以现代的计算能力,24 小时内即可被破解。

      顺便说一下 3DES(Triple DES),它是 DES 向 AES 过渡的加密算法,使用 3 条 56 位的密钥对数据进行三次加密。是 DES 的一个更安全的变形。它以 DES 为基本模块,通过组合分组方法设计出分组加密算法。比起最初的 DES,3DES 更为安全。

       使用 Java 实现 DES 加密解密,注意密码长度要是 8 的倍数。加密和解密的 Cipher 构造参数一定要相同,不然会报错。

       数据加密标准算法,和BASE64最明显的区别就是有一个工作密钥,该密钥既用于加密、也用于解密,并且要求密钥是一个长度至少大于8位的字符串,示例:

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class DesUtil {

	private static Key key;
	
	private static String KEY_STR="myKey";
	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 encoder = 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 encoder.encode(doFinal);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	
	/***
	 * 获取解密之后的信息
	 * @param str
	 * @return
	 */
	public static String getDecryptString(String str) {
		BASE64Decoder decoder = new BASE64Decoder();
		try {
			//将字符串decode成byte[]
			byte[] bytes = decoder.decodeBuffer(str);
			//获取解密对象
			Cipher cipher = Cipher.getInstance(ALGORITHM);
			//初始化解密信息
			cipher.init(Cipher.DECRYPT_MODE, key);
			//解密
			byte[] doFial = cipher.doFinal(bytes);
			
			return new String(doFial, CHARSETNAME);
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
}

 

4.AES(Advanced Encryption Standard) 加密/解密

       高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的 DES,已经被多方分析且广为全世界所使用。简单说就是 DES 的增强版,比 DES 的加密强度更高。

       AES 与 DES 一样,一共有四种加密模式:电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)。关于加密模式的介绍,推荐这篇文章:高级加密标准AES的工作模式(ECB、CBC、CFB、OFB)

示例代码:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil {

	public static final String algorithm = "AES";
	// AES/CBC/NOPaddin
	// AES 默认模式
	// 使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new
	// IvParameterSpec(key.getBytes());
	// NOPadding: 使用NOPadding模式时, 原文长度必须是8byte的整数倍
	public static final String transformation = "AES/CBC/NOPadding";
	public static final String key = "1234567812345678";

	/***
	 * 加密
	 * @param original 需要加密的参数(注意必须是16位)
	 * @return
	 * @throws Exception
	 */
	public static String encryptByAES(String original) throws Exception {
		// 获取Cipher
		Cipher cipher = Cipher.getInstance(transformation);
		// 生成密钥
		SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm);
		// 指定模式(加密)和密钥
		// 创建初始化向量
		IvParameterSpec iv = new IvParameterSpec(key.getBytes());
		cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
		// cipher.init(Cipher.ENCRYPT_MODE, keySpec);
		// 加密
		byte[] bytes = cipher.doFinal(original.getBytes());

		return Base64Util.encryptBASE64(bytes);
	}

	/**
	 * 解密
	 * @param encrypted 需要解密的参数
	 * @return
	 * @throws Exception
	 */
	public static String decryptByAES(String encrypted) throws Exception {
		// 获取Cipher
		Cipher cipher = Cipher.getInstance(transformation);
		// 生成密钥
		SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm);
		// 指定模式(解密)和密钥
		// 创建初始化向量
		IvParameterSpec iv = new IvParameterSpec(key.getBytes());
		cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
		// cipher.init(Cipher.DECRYPT_MODE, keySpec);
		// 解密
		byte[] bytes = cipher.doFinal(Base64Util.decryBASE64(encrypted));

		return new String(bytes);
	}

}

 

5.HMAC(Hash Message Authentication Code,散列消息鉴别码)

       使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证,示例:

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class HMACUtil {

	public static final String KEY_MAC = "HmacMD5";  
	
	/***
	 * 初始化HMAC密钥
	 * @return
	 * @throws Exception
	 */
	public static String initMacKey() throws Exception{
		
		KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
		SecretKey secreKey = keyGenerator.generateKey();
		return Base64Util.encryptBASE64(secreKey.getEncoded());
	}
	
	/**
	 * HMAC加密
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryHMAC(byte[] data, String key) throws Exception{
		SecretKey secreKey = new SecretKeySpec(Base64Util.decryBASE64(key), KEY_MAC);
		Mac mac = Mac.getInstance(secreKey.getAlgorithm());
		mac.init(secreKey);
		return mac.doFinal();
	}
	
}

 

6.恺撒加密

  • 在密码学中,恺撒密码是一种最简单并且最广为人知的加密技术。

  • 它是一种替换加密的技术,明文中的所欲字母都在字母表上向后(或向前)按照一个固定的数目进行偏移后被替换成密文。

  • 例如:当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。

  • 这个加密方法是以恺撒的名字命名的,当年恺撒曾用此方法与其将军们进行联系。

  • 恺撒密码通常被座位其他更复杂的加密方法中的一个步骤。

示例代码:

public class KaisaUtil {

	/***
	 * 使用凯撒加密方式加密数据
	 * @param orignal 原文
	 * @param key 密钥
	 * @return 加密后的字符
	 */
	private static String encryptKaisa(String orignal, int key) {
		//将字符串转换为数组
		char[] chars = orignal.toCharArray();
		StringBuffer buffer = new StringBuffer();
		//遍历数组
		for(char aChar : chars) {
			//获取字符的ASCII编码
			int asciiCode = aChar;
			//偏移数据
			asciiCode += key;
			//将偏移后的数据转为字符
			char result = (char)asciiCode;
			//拼接数据
			buffer.append(result);
		}
		return buffer.toString();
	}
	
	/**
	 * 使用凯撒加密方式解密数据
	 *
	 * @param encryptedData :密文
	 * @param key           :密钥
	 * @return : 源数据
	 */
	private static String decryptKaiser(String encryptedData, int key) {
	    // 将字符串转为字符数组
	    char[] chars = encryptedData.toCharArray();
	    StringBuilder sb = new StringBuilder();
	    // 遍历数组
	    for (char aChar : chars) {
	        // 获取字符的ASCII编码
	        int asciiCode = aChar;
	        // 偏移数据
	        asciiCode -= key;
	        // 将偏移后的数据转为字符
	        char result = (char) asciiCode;
	        // 拼接数据
	        sb.append(result);
	    }

	    return sb.toString();
	}
	
	
	public static void main(String[] args) {
		String str = "open fire";
		String encode = encryptKaisa(str, 3);
		System.out.println("加密后:"+encode);
		
		String decode = decryptKaiser(encode, 3);
		System.out.println("解密后:"+decode);
		
	}
	
}

 

7.SHA(Secure Hash Algorithm,安全散列算法)

        SHA全名叫做安全散列算法,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

        数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域,示例:

import java.security.MessageDigest;

public class SHAUtil {

	public static final String KEY_SHA = "SHA";  
    public static final String ALGORITHM = "SHA-256";
	
	/***
	 * SHA加密(比MD5更安全)
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptSHA(byte[] data) throws Exception{
		MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
		sha.update(data);
		return sha.digest();
	}
	
	
	public static String SHAEncrypt(final String content) {
        try {
            MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
            byte[] sha_byte = sha.digest(content.getBytes());
            StringBuffer hexValue = new StringBuffer();
            for (byte b : sha_byte) {
                //将其中的每个字节转成十六进制字符串:byte类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数。
                String toHexString = Integer.toHexString(b & 0xff);
                hexValue.append(toHexString.length() == 1 ? "0" + toHexString : toHexString);
            }
            return hexValue.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
       return "";
    }


    
    //SHA-256加密
    public static String SHA256Encrypt(String sourceStr) {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance(ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        if (null != md) {
            md.update(sourceStr.getBytes());
            String digestStr = getDigestStr(md.digest());
            return digestStr;
        }

        return null;
    }

    private static String getDigestStr(byte[] origBytes) {
        String tempStr = null;
        StringBuilder stb = new StringBuilder();
        for (int i = 0; i < origBytes.length; i++) {
            tempStr = Integer.toHexString(origBytes[i] & 0xff);
            if (tempStr.length() == 1) {
                stb.append("0");
            }
            stb.append(tempStr);

        }
        return stb.toString();
    }
}

 

8.RSA 加密/解密

       RSA算法是一种非对称加密算法,所谓非对称就是该算法需要一对密钥,若使用其中一个加密,则需要用另一个才能解密。目前它是最有影响力和最常用的公钥加密算法,能够抵抗已知的绝大多数密码攻击。从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。

       该算法基于一个的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。由于进行的都是大数计算,RSA 最快的情况也比 DES 慢上好几倍,比对应同样安全级别的对称密码算法要慢 1000 倍左右。所以 RSA 一般只用于少量数据加密,比如说交换对称加密的密钥。

使用 RSA 加密主要有这么几步:生成密钥对、公开公钥、公钥加密私钥解密、私钥加密公钥解密。

示例代码:

import com.sun.org.apache.xml.internal.security.utils.Base64;
import javax.crypto.Cipher;

import org.apache.commons.io.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RsaUtil {

	/**
     * 生成密钥对并保存在本地文件中
     *
     * @param algorithm : 算法
     * @param pubPath   : 公钥保存路径
     * @param priPath   : 私钥保存路径
     * @throws Exception
     */
    private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {
        // 获取密钥对生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 获取密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 获取公钥
        PublicKey publicKey = keyPair.getPublic();
        // 获取私钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 获取byte数组
        byte[] publicKeyEncoded = publicKey.getEncoded();
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 进行Base64编码
        String publicKeyString = Base64.encode(publicKeyEncoded);
        String privateKeyString = Base64.encode(privateKeyEncoded);
        // 保存文件
        FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));
        FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));

    }

    /**
     * 从文件中加载公钥
     *
     * @param algorithm : 算法
     * @param filePath  : 文件路径
     * @return : 公钥
     * @throws Exception
     */
    private static PublicKey loadPublicKeyFromFile(String algorithm, String filePath) throws Exception {
        // 将文件内容转为字符串
        String keyString = FileUtils.readFileToString(new File(filePath), Charset.forName("UTF-8"));

        return loadPublicKeyFromString(algorithm, keyString);

    }

    /**
     * 从字符串中加载公钥
     *
     * @param algorithm : 算法
     * @param keyString : 公钥字符串
     * @return : 公钥
     * @throws Exception
     */
    private static PublicKey loadPublicKeyFromString(String algorithm, String keyString) throws Exception {
        // 进行Base64解码
        byte[] decode = Base64.decode(keyString);
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范
        X509EncodedKeySpec keyspec = new X509EncodedKeySpec(decode);
        // 获取公钥
        return keyFactory.generatePublic(keyspec);

    }

    /**
     * 从文件中加载私钥
     *
     * @param algorithm : 算法
     * @param filePath  : 文件路径
     * @return : 私钥
     * @throws Exception
     */
    private static PrivateKey loadPrivateKeyFromFile(String algorithm, String filePath) throws Exception {
        // 将文件内容转为字符串
        String keyString = FileUtils.readFileToString(new File(filePath), Charset.forName("UTF-8"));
        return loadPrivateKeyFromString(algorithm, keyString);

    }

    /**
     * 从字符串中加载私钥
     *
     * @param algorithm : 算法
     * @param keyString : 私钥字符串
     * @return : 私钥
     * @throws Exception
     */
    private static PrivateKey loadPrivateKeyFromString(String algorithm, String keyString) throws Exception {
        // 进行Base64解码
        byte[] decode = Base64.decode(keyString);
        // 获取密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 构建密钥规范
        PKCS8EncodedKeySpec keyspec = new PKCS8EncodedKeySpec(decode);
        // 生成私钥
        return keyFactory.generatePrivate(keyspec);

    }

    /**
     * 使用密钥加密数据
     *
     * @param algorithm      : 算法
     * @param input          : 原文
     * @param key            : 密钥
     * @param maxEncryptSize : 最大加密长度(需要根据实际情况进行调整)
     * @return : 密文
     * @throws Exception
     */
    private static String encrypt(String algorithm, String input, Key key, int maxEncryptSize) throws Exception {
        // 获取Cipher对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化模式(加密)和密钥
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // 将原文转为byte数组
        byte[] data = input.getBytes();
        // 总数据长度
        int total = data.length;
        // 输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        decodeByte(maxEncryptSize, cipher, data, total, baos);
        // 对密文进行Base64编码
        return Base64.encode(baos.toByteArray());

    }

    /**
     * 解密数据
     *
     * @param algorithm      : 算法
     * @param encrypted      : 密文
     * @param key            : 密钥
     * @param maxDecryptSize : 最大解密长度(需要根据实际情况进行调整)
     * @return : 原文
     * @throws Exception
     */
    private static String decrypt(String algorithm, String encrypted, Key key, int maxDecryptSize) throws Exception {
        // 获取Cipher对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 初始化模式(解密)和密钥
        cipher.init(Cipher.DECRYPT_MODE, key);
        // 由于密文进行了Base64编码, 在这里需要进行解码
        byte[] data = Base64.decode(encrypted);
        // 总数据长度
        int total = data.length;
        // 输出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        decodeByte(maxDecryptSize, cipher, data, total, baos);
        // 输出原文
        return baos.toString();

    }

    /**
     * 分段处理数据
     *
     * @param maxSize : 最大处理能力
     * @param cipher  : Cipher对象
     * @param data    : 要处理的byte数组
     * @param total   : 总数据长度
     * @param baos    : 输出流
     * @throws Exception
     */
    private static void decodeByte(int maxSize, Cipher cipher, byte[] data, int total, ByteArrayOutputStream baos) throws Exception {
        // 偏移量
        int offset = 0;
        // 缓冲区
        byte[] buffer;
        // 如果数据没有处理完, 就一直继续
        while (total - offset > 0) {
            // 如果剩余的数据 >= 最大处理能力, 就按照最大处理能力来加密数据
            if (total - offset >= maxSize) {
                // 加密数据
                buffer = cipher.doFinal(data, offset, maxSize);
                // 偏移量向右侧偏移最大数据能力个
                offset += maxSize;
            } else {
                // 如果剩余的数据 < 最大处理能力, 就按照剩余的个数来加密数据
                buffer = cipher.doFinal(data, offset, total - offset);
                // 偏移量设置为总数据长度, 这样可以跳出循环
                offset = total;
            }
            // 向输出流写入数据
            baos.write(buffer);
        }
    }
}

  加密算法的安全级别(Security Level of Cryptographic Algorithms):

安全级别 
(Security Level)
工作因素 
(Work Factor)
算法 
(Algorithms)
薄弱(Weak) O(240) DESMD5
传统(Legacy) O(264) RC4SHA-1
基准(Baseline) O(280) 3DES
标准(Standard) O(2128) AES-128SHA-256
较高(High) O(2192) AES-192SHA-384
超高(Ultra) O(2256) AES-256SHA-512

 

9.PBE 加密/解密

     PBE是一种基于口令的加密算法,使用口令代替其他对称加密算法中的密钥,其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。

     PBE算法是对称加密算法的综合算法,常见算法PBEWithMD5AndDES,使用MD5和DES算法构建了PBE算法。将盐附加在口令上,通过消息摘要算法经过迭代获得构建密钥的基本材料,构建密钥后使用对称加密算法进行加密解密。

算法/密钥长度/默认密钥长度:

1.PBEWithMD5AndDES/56/56
2.PBEWithMD5AndTripleDES/112,168/168
3.PBEWithSHA1AndDESede/112,168/168
4.PBEWithSHA1AndRC2_40/40 to 1024/128

工作模式:CBC
填充方式:PKCS5Padding

示例代码:

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

public class PBEUtil {

	public static final String ALGORITHM = "PBEWITHMD5andDES";
	
	public static final int ITERATION_COUNT = 100;
	
	
	public static byte[] initSalt() throws Exception{
		//实例化安全随机数
		SecureRandom random = new SecureRandom();
		return random.generateSeed(8);
	}
	
	/***
	 * 转换密钥
	 * @param password 密码
	 * @return 密钥
	 * @throws Exception
	 */
	private static Key toKey(String password) throws Exception{
		//密钥材料
		PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
		//实例化
		SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
		//生成密钥
		return factory.generateSecret(keySpec);
	}
	
	/***
	 * 加密
	 * @param data 待加密数据
	 * @param password 密钥
	 * @param salt
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception{
		//转换密钥
		Key key = toKey(password);
		//实例化PBE参数材料
		PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT);
		//实例化
		Cipher cipher = Cipher.getInstance(ALGORITHM);
		//初始化
		cipher.init(Cipher.ENCRYPT_MODE, key, spec);
		return cipher.doFinal(data);
	}
	
	
	/***
	 * 解密
	 * @param data 待解密数据
	 * @param password 密钥
	 * @param salt
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(byte[] data, String password, byte[] salt) throws Exception{
		//转换密钥
		Key key = toKey(password);
		//实例化PBE参数材料
		PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT);
		//实例化
		Cipher cipher = Cipher.getInstance(ALGORITHM);
		//初始化  
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
		//执行操作  
		return cipher.doFinal(data);  
	}
	
	
	private static String showByteArray(byte[] data) {
		if(null == data) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		for(byte b : data) {
			sb.append(b).append(",");
		}
		sb.deleteCharAt(sb.length()-1);
		sb.append("");
		return sb.toString();
	}
	
	
	public static void main(String[] args) throws Exception{
		byte[] salt = initSalt();
		System.out.println("salt:"+showByteArray(salt));
		String password = "1111";
		System.out.println("口令:"+password);
		String data = "PBE数据";
		System.out.println("加密前数据:String:"+data);
		System.out.println("加密前数据:byte[]:"+showByteArray(data.getBytes()));
		
		byte[] encryptData = encrypt(data.getBytes(), password, salt);
		System.out.println("加密后数据:byte[]:"+showByteArray(encryptData));
		
		byte[] decryptData = decrypt(encryptData, password, salt);
        System.out.println("解密后数据: byte[]:"+showByteArray(decryptData));
        System.out.println("解密后数据: string:"+new String(decryptData));
	}
}

 

本篇文章参考了以下两位的文章,感谢

https://www.jianshu.com/p/26adec49cb34

https://www.jianshu.com/p/213d69ac27b3

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA各种加密与解密方式 的相关文章

  • CSS图标与链接

    目录 如何添加图标 Font Awesome 图标 实例 Bootstrap 图标 实例 Google 图标 实例 为图标添加样式或颜色 设置链接样式 实例 实例 文本装饰 实例 背景色 实例 链接按钮 实例 更多实例 如何添加图标 向 H
  • 结构体强制类型转换

    在c语言中 结构体和int等类型一样 都是数据类型 其他类型怎么转换 结构体就怎么转换 没有特殊的地方 对于这个问题 可能想问的是这个吧 如果将一个结构体强制类型转换为另一个结构体 或者类型 那这个结构体的成员怎么样了 如果将一个结构体强制
  • 智能化的设备管理系统,为企业信息化建设添砖加瓦

    设备管理的智能化 数字化 可视化是企业信息化建设的三大趋势 也是智能智慧工厂建设的重要内容 因此引进成熟先进的设备管理系统 是每一个企业当下的重要工作 璞华大数据HawkEye设备智能维保平台分为两个维度协助企业进行设备管理 即设备资产管理
  • 11-10 格式化文本的输入输出

    1 scanf 和 printf scanf 和 printf 函数日常使用较多 此处不多介绍了 详细内容可参考 https zh cppreference com w c io fscanf 2 sscanf 和 sprintf ssca
  • JVM虚拟机技术原理与实现

    一 Java语言与Java虚拟机 1 Java语言简介 Java是Sun公司推出的Java语言和Java平台的总称 在操作系统中安装Java平台后Java应用程序即可直接运行 Java程序被编译成字节码解释执行 使Java程序与平台无关 J
  • es根据条件删除数据

    es根据条件删除数据 POST请求 http localhost 9200 indexName delete by query 请求参数 query match columnName 搜索列的条件
  • 哪些元器件在未来会有更广泛的应用?

    随着科技的发展和进步 电子技术已经成为现代社会的重要组成部分 元器件作为电子产品的基本构成单元 其发展和应用对于电子技术的进步和创新有着至关重要的作用 随着人工智能 物联网和智能制造等新兴技术的快速发展 一些元器件已经或者将在未来得到更广泛
  • 解决 mysql 自动增长的 id 不是从 1 开始 或 不连续

    原因 1 insert 失败后 id 已自动增加 会造成 id 不连续 2 delete 后 再重新插入数据后 id 会从删除前最后的 id 开始增加 造成 id 不是从1开始增加 注意 删除全部数据时 不要用 delete from ta
  • Random.Range()的范围问题

    Random Range 方法的是进行差生随机数的一个方法 int i Random Range min max 这里进行产生的随机数 当min max相等 产生的随机数返回的是min 因为min max 产生的最大的也就是max 当min
  • HTML-页面经3秒之后自动跳转,动态刷新秒数

    样图 div div
  • MATLAB复习

    目录 矩阵 定义矩阵 查找矩阵元素 特殊矩阵 矩阵运算 乘方与点乘 字符串数组 创建字符串 查找字符 字符串转换 创建字符串数组 元胞数组 元胞数组的创建 元胞数组的显示 celldisp 和 cellplot 元胞数组的扩充和收缩 元胞数

随机推荐

  • VMware中安装mysql

    文章目录 1 将windows下的安装包上传到Linux服务器 安装包移动并解压 3 卸载系统自带的mysql 4 安装mysql服务端 5 安装mysql客户端 6 登录mysql 6 1 查看root密码 6 2 启动mysql服务 6
  • 刷脸支付自主创业超低门槛等您来

    新兴的人工智能技术不断被应用到支付场景中 指纹支付 声纹支付到刷脸支付 新技术的蔓延总是能出乎我们的意料 迅速地渗透进生活的方方面面 行业监管趋严 智能应用不断迭代 双重作用下 支付行业正迎来一次革命性的转折 刷脸支付开始普及 中国有700
  • Excel:LOOKUP函数的经典用法

    1 逆向查询 下面这个表中 A C列是员工基础信息表 分别是部门 姓名和职务 现在要根据E5单元格中的员工姓名 在这个信息表中查询属于哪个部门 也就是咱们常说的逆向查询 就可以使用LOOKUP函数了 F5单元格输入以下公式 LOOKUP 1
  • 转:基于 Drone + Gogs 构建私有 CI/CD 平台

    前言 很久之前 部署方案选择了基于 Docker 的容器化落地方案 极简描述与总结于 gogs drone docker 但是随着微服务抽象定义的服务越来越多 团队规模越来越壮大时 单机部署的自动化持续部署平台在并行处理任务可能会出现大量排
  • 构造函数访问权限和基类构造函数,派生类的构造函数调用顺序

    include
  • MyBatis多条件查询、动态SQL、多表操作、注解开发详细教程

    一 多条件查询 二 动态SQL 1 if where 2 choose when ortherwise 3 foreach 三 多表操作 1 一对一 2 一对多 3 多对多 四 注解开发 MyBatis封装了JDBC通过Mapper代理的方
  • Flutter如何使widget始终保持在屏幕底部

    Flutter如何使widget始终保持在屏幕底部 问题描述 在登录或者注册页面 需要在底部展示一些隐私政策或者是隐私协议 就是用了一种Stack布局方式 但是使用这种方式在没有键盘弹出的时候看起来一起正常 但是只要有软键盘弹出就会把底部使
  • matlab中的导函数驻点,Matlab用导数作定性分析

    Matlab用导数作定性分析 5 1知识要点 函数作图 用导数定性描述函数 clf x linspace 8 8 30 f x 3 2 4 x 1 plot x f fplot x 3 2 4 x 1 8 8 clf x sym x f x
  • 软件工程开发模式:从传统到现代的演进

    引言 软件工程开发模式是指导软件开发过程的重要框架 旨在提高软件开发的效率和质量 随着技术的不断进步 软件工程开发模式也在不断发展演变 以适应不同的项目需求和开发环境 本文将介绍传统软件工程开发模式和现代敏捷 精益和DevOps软件工程开发
  • Docker进阶学习:docker-compose的体验

    安装好docker compose后 我们要体验一下了解基础的操作和命令 搞一个官方demo python应用 计数器 redis 我先来一个官方文档地址 基本很多都是按照文档来的 建议尽量去官方文档来产看最新的 我这个可能也只是主要内容搬
  • Jmeter(二十一) - 从入门到精通 - JMeter断言 - 上篇(详解教程)

    1 简介 最近由于在搭建自己的个人博客可能更新的有点慢 断言组件用来对服务器的响应数据做验证 常用的断言是响应断言 其支持正则表达式 虽然我们的通过响应断言能够完成绝大多数的结果验证工作 但是JMeter还是为我们提供了适合多个场景的断言元
  • python获取列表的任意行任意列

    import numpy as np a 1 12 13 14 2 22 23 24 3 32 33 34 4 42 43 44 a np array a print 获取列表的任意列 print a 3 2 1 0 0 print 获取列
  • 2021年网络安全省赛--服务器内部信息获取解析(中职组)

    2021年省赛服务器内部信息获取解析 一 竞赛时间 180分钟 共计3小时 二 竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 1 收集服务器场景中的服务信息 并获取服务器中开放的端口号信息 将服务器端口号作为flag提交 如果有多
  • linux内核历史版本及网址介绍

    官网 https www kernel org 最新版本4 12 rc4 Protocol Location HTTP https www kernel org pub GIT https git kernel org RSYNC rsyn
  • esBuild + SWC 构建 TS 项目

    1 esBuild 介绍 在 esbuild 的官方介绍中打包 threejs 只需要 0 37 秒 Esbuild 是一个非常新的模块打包工具 它提供了与 Webpack Rollup Parcel 等工具 相似 的资源打包能力 却有着高
  • 两个3*3的卷积核替代5*5(三个3*3卷积核替代7*7)分析

    文章目录 为什么一个5x5的卷积核可以用两个3x3的卷积核来替代 一个5 5卷积 两个3 3卷积核 为什么一个7x7的卷积核可以用三个个3x3的卷积核来替代 一个7 7卷积 三个3 3卷积核 优点总结 为什么一个5x5的卷积核可以用两个3x
  • 输入一个字符串,把一个字符串的字符逆序输出

    package com qf day4 import java util Scanner public class Test29 public static void main String args 把一个字符串的字符逆序输出 Scann
  • 可能是最详细的React组件库搭建总结

    可能是最详细的React组件库搭建总结 概览 本文包含以下内容 prepare 组件库前期开发准备工作 eslint commit lint typescript等等 dev 使用docz进行开发调试以及文档编写 build umd cjs
  • TeamViewer账号未激活问题

    出现如下问题 解决步骤 1 点击重新发送电子邮件 2 网页上登录 3 QQ邮箱里面添加设备信任 4 返回登录页面再重新 刷新重新输入登录信息登录 然后重新发送电子邮件到qq邮箱 5 点击激活 6 登录 gt gt gt 不要现在登录 gt
  • JAVA各种加密与解密方式

    之前有兴趣研究了一下java的加密与解密的方法 发现市面上有好多种加密解密方式 在这里整理了一下 目录 1 BASE64加密 解密 2 MD5 Message Digest Algorithm 加密 3 DES Data Encryptio