对称密码之PBE


前边的几篇文章,已经讲了几个对称加密的算法了,今天这篇文章再介绍最后一种对称加密算法 — — PBE,这种加密算法,对我的认知来说,并没有 DES、3DES、AES 那么流行,也不尽然,其实是我之前并没有这方面的需求,当然接触他的机会也就很少了,因此,可想而知,没听过显然在正常不过了。


概念


PBE,全称为“Password Base Encryption”,中文名“基于口令加密”,是一种基于密码的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。

PBE算法没有密钥的概念,把口令当做密钥了。因为密钥长短影响算法安全性,还不方便记忆,这里我们直接换成我们自己常用的口令就大大不同了,便于我们的记忆。但是单纯的口令很容易被字典法给穷举出来,所以我们这里给口令加了点“盐”,这个盐和口令组合,想破解就难了。同时我们将盐和口令合并后用消息摘要算法进行迭代很多次来构建密钥初始化向量的基本材料,使破译更加难了。


原理


首先,是基于口令的加密原理图



然后,是基于口令的解密原理图



由于这种加密方式的口令容易记忆,不用放在物理媒体上,因此增加了口令的安全性。密钥空间较小,安全性不高,用字典法比较容易破译。攻击者可产生一套密钥列表,用所有可能的密钥进行查找。

常用算法有

  • PBEWithSHAAndDES
  • PBEWithSHAAndBlowfish
  • PBEWithSHAAnd128BitRC4
  • PBEWithSHAAndIDEA-CBC
  • PBEWithSHAAnd3-KeyTripleDES-CBC

其次,是基于口令和盐的加密原理图



最后,是基于口令和盐的解密原理图



当然,这种加密方式也具有口令容易记忆的特点,不用放在物理媒体上,因此增加了口令的安全性。可防止攻击者用事先产生的密钥列表进行查找。通过增加消息摘要的计算次数增加了攻击者测试口令的时间。

常用算法有

  • PBEWithSHAAndDES
  • PBEWithSHAAndBlowfish
  • PBEWithSHAAnd128BitRC4
  • PBEWithSHAAndIDEA-CBC
  • PBEWithSHAAnd3-KeyTripleDES-CBC


代码实现


import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Random;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import sun.misc.BASE64Encoder;

/**
 * PBE 加解密工具类
 */
public class PBE {
	/**
	 * 定义加密方式 支持以下任意一种算法
	 * <p/>
	 * 
	 * <pre>
	 * PBEWithMD5AndDES 
	 * PBEWithMD5AndTripleDES 
	 * PBEWithSHA1AndDESede 
	 * PBEWithSHA1AndRC2_40
	 * </pre>
	 */
	private final static String KEY_PBE = "PBEWITHMD5andDES";

	private final static int SALT_COUNT = 100;

	/**
	 * 初始化盐(salt)
	 * 
	 * @return
	 */
	public static byte[] init() {
		byte[] salt = new byte[8];
		Random random = new Random();
		random.nextBytes(salt);
		return salt;
	}

	/**
	 * 转换密钥
	 * 
	 * @param key
	 *            字符串
	 * @return
	 */
	public static Key stringToKey(String key) {
		SecretKey secretKey = null;
		try {
			PBEKeySpec keySpec = new PBEKeySpec(key.toCharArray());
			SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_PBE);
			secretKey = factory.generateSecret(keySpec);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}
		return secretKey;
	}

	/**
	 * PBE 加密
	 * 
	 * @param data
	 *            需要加密的字节数组
	 * @param key
	 *            密钥
	 * @param salt
	 *            盐
	 * @return
	 */
	public static byte[] encryptPBE(byte[] data, String key, byte[] salt) {
		byte[] bytes = null;
		try {
			// 获取密钥
			Key k = stringToKey(key);
			PBEParameterSpec parameterSpec = new PBEParameterSpec(salt,
					SALT_COUNT);
			Cipher cipher = Cipher.getInstance(KEY_PBE);
			cipher.init(Cipher.ENCRYPT_MODE, k, parameterSpec);
			bytes = cipher.doFinal(data);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		}
		return bytes;
	}

	/**
	 * PBE 解密
	 * 
	 * @param data
	 *            需要解密的字节数组
	 * @param key
	 *            密钥
	 * @param salt
	 *            盐
	 * @return
	 */
	public static byte[] decryptPBE(byte[] data, String key, byte[] salt) {
		byte[] bytes = null;
		try {
			// 获取密钥
			Key k = stringToKey(key);
			PBEParameterSpec parameterSpec = new PBEParameterSpec(salt,
					SALT_COUNT);
			Cipher cipher = Cipher.getInstance(KEY_PBE);
			cipher.init(Cipher.DECRYPT_MODE, k, parameterSpec);
			bytes = cipher.doFinal(data);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		}
		return bytes;
	}

	/**
	 * BASE64 加密
	 * 
	 * @param key
	 *            需要加密的字节数组
	 * @return 字符串
	 * @throws Exception
	 */
	public static String encryptBase64(byte[] key) throws Exception {
		return (new BASE64Encoder()).encodeBuffer(key);
	}

	/**
	 * 测试方法
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		// 加密前的原文
		String str = "hello world !!!";
		// 口令
		String key = "qwert";
		// 初始化盐
		byte[] salt = init();
		// 采用PBE算法加密
		byte[] encData = encryptPBE(str.getBytes(), key, salt);
		// 采用PBE算法解密
		byte[] decData = decryptPBE(encData, key, salt);
		String encStr = null;
		String decStr = null;
		try {
			encStr = encryptBase64(encData);
			decStr = new String(decData, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("加密前:" + str);
		System.out.println("加密后:" + encStr);
		System.out.println("解密后:" + decStr);
	}
}

原博客地址

http://blog.youkuaiyun.com/happylee6688/article/details/44650517




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值