Java 加解密技术系列之 PBE

  • 概念
  • 原理
  • 代码实现
  • 结束语


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

概念

PBE,全称为“Password Base Encryption”,中文名“基于口令加密”,是一种基于密码的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。
PBE算法没有密钥的概念,把口令当做密钥了。因为密钥长短影响算法安全性,还不方便记忆,这里我们直接换成我们自己常用的口令就大大不同了,便于我们的记忆。但是单纯的口令很容易被字典法给穷举出来,所以我们这里给口令加了点“盐”,这个盐和口令组合,想破解就难了。同时我们将盐和口令合并后用消息摘要算法进行迭代很多次来构建密钥初始化向量的基本材料,使破译更加难了。

原理

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

    其次,是基于口令和盐的加密原理图
最后,是基于口令和盐的解密原理图
当然,这种加密方式也具有口令容易记忆的特点,不用放在物理媒体上,因此增加了口令的安全性。可防止攻击者用事先产生的密钥列表进行查找。通过增加消息摘要的计算次数增加了攻击者测试口令的时间。
常用算法有
    代码实现
import sun.misc.BASE64Encoder;  

import javax.crypto.*;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
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; /**
* Created by xiang.li on 2015/2/28.
* 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);
}
}

结束语

到这里,对称加密算法就算是结束了,其实回想起来,PBE 并不算是一种新算法,他只不过是把密钥概念转变成了“口令 + 盐”的方式而已,至于加解密的原理,还是用到常用的对称加密算法,比如 DES 和 AES 等,因此说,没有什么新东西。
对称加密总算是告一段落了,我打算下次讲几个非对称加密的算法,之后这个系列的文章就要画上句号了。好的,小伙伴们,下次再见喽,欢迎大家与我交流,我们共同学习、共同进步。

8.Java 加解密技术系列之 PBE的更多相关文章

  1. Java 加解密技术系列文章

    Java 加解密技术系列之 总结 Java 加解密技术系列之 DH Java 加解密技术系列之 RSA Java 加解密技术系列之 PBE Java 加解密技术系列之 AES Java 加解密技术系列 ...

  2. 11.Java 加解密技术系列之 总结

    Java 加解密技术系列之 总结 序 背景 分类 常用算法 原理 关于代码 结束语 序 上一篇文章中简单的介绍了第二种非对称加密算法 — — DH,这种算法也经常被叫做密钥交换协议,它主要是针对密钥的 ...

  3. 10.Java 加解密技术系列之 DH

    Java 加解密技术系列之 DH 序 概念 原理 代码实现 结果 结束语 序 上一篇文章中简单的介绍了一种非对称加密算法 — — RSA,今天这篇文章,继续介绍另一种非对称加密算法 — — DH.当然 ...

  4. 9.Java 加解密技术系列之 RSA

    Java 加解密技术系列之 RSA 序 概念 工作流程 RSA 代码实现 加解密结果 结束语 序 距 离上一次写博客感觉已经很长时间了,先吐槽一下,这个月以来,公司一直在加班,又是发版.上线,又是新项 ...

  5. 7.java 加解密技术系列之 AES

    java 加解密技术系列之 AES 序 概念 原理 应用 代码实现 结束语 序 这篇文章继续介绍对称加密算法,至于今天的主角,不用说,也是个厉害的角色 — — AES.AES 的出现,就是为了来替代原 ...

  6. 6. Java 加解密技术系列之 3DES

    Java 加解密技术系列之 3DES 序 背景 概念 原理 代码实现 结束语 序 上一篇文章讲的是对称加密算法 — — DES,这篇文章打算在 DES 的基础上,继续多讲一点,也就是 3 重 DES ...

  7. 5.Java 加解密技术系列之 DES

    Java 加解密技术系列之 DES 序 背景 概念 基本原理 主要流程 分组模式 代码实现 结束语 序 前 几篇文章讲的都是单向加密算法,其中涉及到了 BASE64.MD5.SHA.HMAC 等几个比 ...

  8. 4.Java 加解密技术系列之 HMAC

    Java 加解密技术系列之 HMAC 序 背景 正文 代码 结束语 序 上一篇文章中简单的介绍了第二种单向加密算法 — —SHA,同时也给出了 SHA-1 的 Java 代码.有这方面需求的童鞋可以去 ...

  9. 3.Java 加解密技术系列之 SHA

    Java 加解密技术系列之 SHA 序 背景 正文 SHA-1 与 MD5 的比较 代码实现 结束语 序 上一篇文章中介绍了基本的单向加密算法 — — MD5,也大致的说了说它实现的原理.这篇文章继续 ...

随机推荐

  1. (删)Java线程同步实现二:Lock锁和Condition

    在上篇文章(3.Java多线程总结系列:Java的线程同步实现)中,我们介绍了用synchronized关键字实现线程同步.但在Java中还有一种方式可以实现线程同步,那就是Lock锁. 一.同步锁 ...

  2. 常用linux命令及其设置

    完成一个运维的工作,以下的命令和配置是经常会用到的,总结一下工作以来的命令和配置 linux常用命令 linux客户端挂接(mount)其他linux系统或UNIX系统的NFS共享 $ mkdir – ...

  3. Linux命令的复习总结学习

    1.-------------------------linux系统介绍------------------------------------------------------- Linux是一套 ...

  4. Linux之环境变量

    1. 变量的显示与设置 显示变量 echo \(PATH</font></code><br/> 取消变量 <code><font color=&q ...

  5. Azure Messaging-ServiceBus Messaging消息队列技术系列8-服务总线配额

    上篇博文中我们介绍了Azure ServiceBus Messaging的消息事务机制: Azure Messaging-ServiceBus Messaging消息队列技术系列7-消息事务(2017 ...

  6. 腾讯云上Selenium用法示例

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:崔庆才 前言 在上一节我们学习了PhantomJS 的基本用法,归根结底它是一个没有界面的浏览器,而且运 ...

  7. struts2之拦截器

    1. 为什么需要拦截器 早期MVC框架将一些通用操作写死在核心控制器中,致使框架灵活性不足.可扩展性降低, Struts 2将核心功能放到多个拦截器中实现,拦截器可自由选择和组合,增强了灵活性,有利于 ...

  8. error C2664: “UINT GetDriveTypeW(LPCWSTR)”: 无法将参数 1 从“char [5]”转换为“LPCWSTR”

    解决方法:右击项目选择属性--->配置属性--->常规,将字符集改为“使用多字节字符符集”,应用确定即可. 来自为知笔记(Wiz)

  9. storage在IE8下的兼容性写法

    storage 本地缓存,这是HTML5的一个非常好用的地方,具体好用在哪,网上可以找到很多,但是我觉得总结的都不是很完整,我建议大家有空的话可以看下JavaScript权威指南这本书,里面对于这个方 ...

  10. java设计模式--基础思想总结--父类引用操作对象

    看设计模式的相关书籍也有一段时间了,一开始其实是抱着作为java三大框架的基础知识储备来学习的,不过到后来,才发现,在设计模式的一些准则装饰下,java的面向对象威力才真正地体现出来,后面的将会陆续地 ...