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. 查看Samba用户的方法

    有时我们需要查看服务器上都注册了哪些用户,这时我们就可以用下面的命令来查看了. pdbedit可以编辑samba的用户数据库,具体使用方法可以用man查看. pdbedit -L

  2. Python os与sys模块解析

    os与sys模块的官方解释如下: os: This module provides a portable way of using operating system dependent functio ...

  3. 你的计算机也可以看懂世界——十分钟跑起卷积神经网络(Windows+CPU)

    众所周知,如果你想研究Deep Learning,那么比较常用的配置是Linux+GPU,不过现在很多非计算机专业的同学有时也会想采用Deep Learning方法来完成一些工作,那么Linux+GP ...

  4. IO流输入 输出流 字符字节流

    一.流 1.流的概念 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作. ...

  5. 纯原生javascript实现分页效果

    随着近几年前端行业的迅猛发展,各种层出不穷的新框架,新方法让我们有点眼花缭乱. 最近刚好比较清闲,所以没事准备撸撸前端的根基javascript,纯属练练手,写个分页,顺便跟大家分享一下 functi ...

  6. lua 模块

    lua 模块 概述 lua 模块类似于封装库 将相应功能封装为一个模块, 可以按照面向对象中的类定义去理解和使用 使用 模块文件示例程序 mod = {} mod.constant = "模 ...

  7. 获取camera截屏图片

    Camera camera; SpriteRenderer sprRender; Texture2D t2d = New Texture2D(1300, 760, TextureFormat.RGB2 ...

  8. HDU 5008 求第k小子串

    本题要求第k小的distinct子串,可以根据height数组,二分出这个第k小子串所在后缀的位置信息.由于题目要求子串起始下标尽可能小.所以再在rank数组中,二分出与当前后缀LCP大于等于所求子串 ...

  9. HDU3518 后缀数组求不可重叠重复出现的不同子串个数

    枚举子串长度,根据height分组,如果本组sa最小值与sa最大值之差超过枚举的长度,则本组对于答案贡献为1. #include <iostream> #include <vecto ...

  10. oracle 归档日志满 报错ORA-00257: archiver error. Connect internal only, until freed

    归档日志满导致无法用户无法登陆 具体处理办法 --用户登陆 Microsoft Windows [Version 6.1.7601] Copyright (c) Microsoft Corporati ...