java PEB算法加密

1、PBE(Password Based Encryption,基于口令加密)是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数(这里称之为 盐)杂凑多重加密等方法保证数据的安全性。

2、PBE 算法并没有 真正构建新的加密/解密算法,而是对已知的对称加密算法(eg:DES算法)做了包装;使用PBE算法对数据做加密/解密操作时,其实是使用了 DES 或者 AES 等其他对称加密算法做了相应的操作。

既然,PBE算法是使用了较为常用的对称加密算法,那就无法回避密钥的问题;口令并不能替代密钥,密钥是经过加密算法计算得出的,但口令本身不可能很长,单纯的口令很容易通过穷举攻击方式破译,这就引入了 “盐”。盐能够阻止字典攻击或预先计算的攻击,本身是一个随机的信息,相同的随机信息极不可能使用2次。将盐附加在 口令上,通过消息摘要算法经过迭代计算获取得到 构建密钥/初始化向量的基本材料,使得破译加密信息的难度加大。

PBE 算法是对称加密算法的综合性算法,常见有:PBEWithMD5AndDES,该算法使用了 MD5 和 DES 算法构建 PBE算法。

105938_OLCT_1387400.png

3、实现

java6 和 Bouncy Castle 都提供了 系统算法的 相关实现.110345_mQyw_1387400.png

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

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

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

/**
 * 对称加密 - 口令算法 
 */
public class PBECoder {

	/**指定消息摘要算法 组合*/
	public static final String ALGORITHM = "PBEWITHMD5andDES";
	
	/**迭代次数*/
	public static final int ITERATION_COUNT = 100;
	
	/**
	 * 初始化 盐
	 * 盐的 长度必须为 8 字节 (密钥长度 必须是 8 的 倍数)
	 * @return
	 */
	public static byte[] initSalt(){
		SecureRandom secureRandom = new SecureRandom();
		return secureRandom.generateSeed(8);
	}
	
	/**
	 * 转换密钥
	 */
	public static Key toKey(String password) throws Exception{
		// 材料转换
		PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
		// 生产密钥
		SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM);
		// 初始化
		SecretKey secretKey = secretKeyFactory.generateSecret(pbeKeySpec);
		return secretKey;
	}
	
	/**
	 * 加密数据
	 * @param data 即将要加密的数据
	 * @param password 密码
	 * @param salt 盐
	 * @return
	 * @throws Exception 
	 */
	public static String encrypt(byte[] data, String password, byte[] salt) throws Exception{
		 // 还原密钥
		 Key key = toKey(password);
		 // 实例化 PBE 参数
		 PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
		 
		 // 创建实例
		 Cipher cipher = Cipher.getInstance(ALGORITHM);
		 // 初始化
		 cipher.init(Cipher.ENCRYPT_MODE, key, pbeParameterSpec);
		 byte[] encry = cipher.doFinal(data);
		 return Base64.encode(encry);
	}
	
	/**
	 * 解密数据
	 * @param data 即将要解密的数据
	 * @param password 密码
	 * @param salt 盐
	 * @return
	 */
	public static String decrypt(String data, String password, byte[] salt) throws Exception{
		// 还原即将解密的数据 
		byte[] encry = Base64.decode(data);
		// 还原 key
		Key key = toKey(password);
		// 实例化 PBE 参数
		PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
		
		// 创建实例
		Cipher cipher = Cipher.getInstance(ALGORITHM);
		// 初始化
		cipher.init(Cipher.DECRYPT_MODE, key, pbeParameterSpec);
		byte[] decry = cipher.doFinal(encry);
		return new String(decry);
	}
	
	public static void main(String[] args) throws Exception {
		// 加解密密钥
		String password = "pbe_test";
		String data = "PBE 测试";
		//byte[] salt = initSalt(); // 设置为 随机的 8位数
		byte[] salt = "20170814".getBytes(); // 约定为 yyyyMMdd时间
		String encryStr = encrypt(data.getBytes("utf-8"), password, salt);
		System.out.println(data + "-> 加密后:" + encryStr);
		String decryStr = decrypt(encryStr, password, salt);
		System.out.println(data + "-> 解密后:" + decryStr);
		/** console结果:
		 * PBE 测试-> 加密后:5nv5Gfr9eJwIqhGn2qYiCg==
           PBE 测试-> 解密后:PBE 测试
		 */
	}
}

4、小结

关于 “盐”的说明:

“盐”本身是一种可以由消息 传递双方按照 一定规律约定的信息,例如时间,也可以是某个不可变物理的硬件的编号;甲乙双方可以通过约定消息传递时间,并将其作为 “盐”的基本信息,根据预定算法(如 MD5算法)对其处理,最终获取真正的 “盐”,这样一来,“盐”就无需传递,提供了安全性。

换一种思路考虑,使用者需要将 U 盘插入计算机,同时输入 口令方能登录,那么 U 盘就是 “盐”信息的提供者,即使 U盘丢失,加密的信息也未必能被窃取。从另一个角度来说,“盐”与 口令就像 2把 不可分割的钥匙。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值