java 基于口令加密算法,基于口令加密 -- PEB

1、概述

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

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

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

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

2、模型图

ce30cd37515c9f76ee8ccb6a38b28cf5.png

3、实现

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

4472acbe2af0ece6120d00083d68c232.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把 不可分割的钥匙。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值