PBE加密算法
这是我参加全国信息安全大赛的设计的加密系统中的一个加密算法,虽然比赛的结果不是非常理想但是,我还是学到了很多东西,现在和大家分享一下,比赛收获的东西。
基于口令加密
PBE(Password Based Encryption,基于口令加密)算法是一种基于口令的加密算法,其特点在于口令是由用户自己掌握的,采用随机数杂凑多重加密等方法保证数据的安全性。
PBE算法没有密钥的概念,密钥在其它对称加密算法中是经过算法计算得出来的,PBE算法则是使用口令替代了密钥。
密钥的长短直接影响了算法的安全性,但不方便记忆。即便是我们将密钥经过Base64编码转换为一个可见字符,长密钥一样不容易记忆。因此,在这种情况下密钥是需要存储的,但是口令则不然。比如一般人天天开关电脑,进入操作系统的唯一途径就是输入口令。口令是我们便于记忆的一种凭证,基于这一点,PBE算法使用口令替代了密钥。
PBE算法并没有真正构建新的加密/解密算法,而是对我们已经知道的对称加密算法(如DES算法)做了包装。使用PBE算法对数据做加密/解密操作的时候,其实是使用了DES或者是AES等其它对称加密算法做了相应的操作。
既然PBE算法使用我们较为常用的对称加密算法,那就无法回避密钥的问题。口令并不能替代密钥,密钥是经过加密算法计算得来的,但是口令本身不可能很长看,单纯的口令很容易通过穷举攻击方式破译,这就引入了“盐”。盐能阻止字典攻击或预先计算的攻击,它本身是一个随机信息,相同的随机信息极不可能使用两次。将盐附加在口令上,通过消息摘要算法经过迭代计算获得构建密钥/初始化向量的基本材料,使得破译的难度加大。
基于PBE算法的消息传递模型如下图3-13所示:甲乙双方作为消息传递双方(甲方为发送方,也就是甲方是本系统的服务器,乙方作为接收方,也就是本系统客户端的使用者),假定甲乙双方在消息传递前已经商定加密算法迭代的次数,与完成一次消息传递需要经过如下步骤:
1) 由消息传递双方约定口令,这里由甲方构建口令。
2) 由口令构建者发布口令,即本系统的服务器将口令发送给系统的客户端使用者
3) 由口令构建者构建本次消息传递使用的盐,这里由甲方(本系统)构建盐
4) 由消息发送方使用口令、盐对数据加密,这里由甲方对数据加密
5) 由消息发送者将盐、加密数据放松给消息接收者,这里由甲方将盐、加密数据发送给乙方
6) 由消息接收方使用盐、口令对加密数据解密,这里由乙方完成数据解密
图3-13 基于PBE算法的消息通讯模型
基于PBE算法的消息传递模型理解起来并不是十分复杂。对于上述单项消息传递而言,如果乙方想要恢复甲方消息,甲方并不需要重复步骤1、2,仅仅想要由乙方执行3、4、5,由甲方执行步骤6即可。
同时,甲乙双方也可以在消息传递过程中传递迭代次数。
“盐”本身就是一种可以由消息传递双方按一定规律约定的消息,比如时间。也可以是某个不可变物理硬件的编号,比如U盘的自身唯一标识,而本系统则采用“手机的唯一标识”,WIM 是一个防篡改硬件,在安全层和应用层执行安全功能,保存处理用户的ID 和权限等功能。
甲乙双方可以通过约定消息传递的时间,这里是由本系统直接决定时间,并将其作为基本消息,根据预定的算法(如MD5算法) 对其处理,最终获取真正的“盐”,这样一来,“盐”就无需传递,提高了安全性。
假设一个场景:由这样的一个系统,用户使用者需要通过手机访问一个系统,同同时需要输入口令方能登录系统,那么手机本身就是“盐”的提供者!即使手机丢失,加密的信息也未必能被窃取!即“盐”与口令就像两把不可分离的钥匙。
PBE实现方案:
Java 6 和Bouncy Castle都提供了PBE系列算法的相关实现,差别在于对各种消息摘要算法和对称加密算法的组合。常用的消息摘要算法包括MD5和SHA算法,常用的对称加密算法包括DES、RC2等。PBE系列算法就死将这些算法进行合理组合,其密钥长度均以PBE具体的算法中的对称加密算法为准。
有关PBE算法的Java6 和Bouncy Castle实现细节如下表3-11。
表3-11 PBE算法
总体看来口令和盐两边都需要知道。消息传递过程还是需要指定双方的统一算法进行。而这些算法其实还是用的那些常见的对称加密算法
三、java6和bouncycastle支持的算法列表
算法 密钥长度 密钥长度默认值 工作模式 填充方式 备注
PBEWithMD5AndDES 56 56 CBC PKCS5Padding java6实现
PBEWithMD5AndTripeDES 112、168 168 CBC PKCS6Padding java7实现
PBEWithSHA1AndDESede 112、168 168 CBC PKCS7Padding java8实现
PBEWithSHA1AndRC2_40 40至1024 128 CBC PKCS8Padding java9实现
PBEWithMD5AndDES 64 64 CBC PKCS5Padding/PKCS7Padding/ISO10126Padding/ZeroBytePadding BouncyCastle实现
PBEWithMD5AndRC2 128 128 CBC PKCS5Padding/PKCS7Padding/ISO10127Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHA1AndDES 64 64 CBC PKCS5Padding/PKCS7Padding/ISO10128Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHA1AndRC2 128 128 CBC PKCS5Padding/PKCS7Padding/ISO10129Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAndIDEA-CBC 128 128 CBC PKCS5Padding/PKCS7Padding/ISO10130Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAnd2-KeyTripleDES-CBC 128 128 CBC PKCS5Padding/PKCS7Padding/ISO10131Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAnd3-KeyTripleDES-CBC 192 192 CBC PKCS5Padding/PKCS7Padding/ISO10132Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAnd128BitRC2-CBC 128 128 CBC PKCS5Padding/PKCS7Padding/ISO10133Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAnd40BitRC2-CBC 40 40 CBC PKCS5Padding/PKCS7Padding/ISO10134Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAnd128BitRC4 128 128 CBC PKCS5Padding/PKCS7Padding/ISO10135Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAnd40BitRC4 40 40 CBC PKCS5Padding/PKCS7Padding/ISO10136Padding/ZeroBytePadding BouncyCastle实现
PBEWithSHAAndTwofish-CBC 256 256 CBC PKCS5Padding/PKCS7Padding/ISO10137Padding/ZeroBytePadding BouncyCastle实现
PBE实现代码:
PBECoder.java
package com.wecode.database.secure; 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; /**
* PBE安全编码组件
*
* @author WeCode ( ydonghao2 )
* @version 1.0
*/ public class PBECoder {
public static final String ALGORUTHM = "PBEWITHMD5andDES";
/**
* 迭代次数
*/
public static final int ITERATION_COUN = 100; /**
* "盐"初始化<br>
* 盐长度必须为8字节
* @return byte[] 盐
* @throws Exception
*/
public static byte[] initSalt() throws Exception {
//实例化安全随机数
SecureRandom random = new SecureRandom();
//产出盐
return random.generateSeed(8);
}
/**
* 转换密钥
* @param password 密码
* @return Key密钥
* @throws Exception
*
*/ private static Key toKey(String password) throws Exception {
//密钥材料转换
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
//实例化
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORUTHM);
//生成密钥
SecretKey secretkey = keyFactory.generateSecret(keySpec);
return secretkey;
} /**
* 加密
* @param data 数据
* @param password 密钥
* @param salt 盐
* @return byte[] 加密数据
* @throws Exception
*/ public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception{
//转换密钥
Key key = toKey(password);
//实例化PBE参考数据
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, ITERATION_COUN);
//实例化
Cipher cipher = Cipher.getInstance(ALGORUTHM);
//初始化
cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
//执行操作 return cipher.doFinal(data);
} /**
* 解密
* @param data 数据
* @param password 密码
* @param salt 盐
* @return byte[] 解密数据
* @throws Exception
*/ public static byte[] decrypt(byte[] data, String password, byte[] salt) throws Exception{
//转换密钥
Key key = toKey(password);
//实例化PBE参数材料
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, ITERATION_COUN);
//实例化
Cipher cipher = Cipher.getInstance(ALGORUTHM);
//初始化
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
//执行操作
return cipher.doFinal(data);
}
}
PBE算法是实现过程中需要关注的环节,包括“盐”的初始化,密钥材料的转化和加密/解密的时间。
在初始化“盐”时,必须使用随机的方式构造“盐”,最终要得到一个8字节的字节数组。鉴于安全性的要求,这里的随机数生成器只能使用SecureRandom类,如下所示:
//实例化安全性随机数
SecureRandomrandom = new SecureRandom();
//产出“盐”
byte[]b = random.generateSeed(8);
字节数组b[]就是我们要的“盐”。
密钥材料转换部分不同于其他对称加密算法,这里使用的是PBEKeySpec类,如下所示:
//密钥材料转换
PBEKeySpeckeySpec = new PBEKeySpec(password.toChatArray());
其他对称加密算法的密钥材料实现类的构造方法要求输入字节数组形式的变量,而PBEKeySpec类构造方法则要求输入字符数组变量。
为什么不是字符串(String)而是字符数组(char[])呢?这是因为字符串是可序列化的封装类,可在程序调用时被序列化到文件中,而字符数组只能以内存变量的形式保留在内存中。
在加密/解密实现时,需要注意使用参数材料PBEParameterSpec类,同时注意迭代次数。构建PBE参数材料后就可以转交给Cipher类完成加密/解密操作,如下所示:
//实例化PBE参数材料
PBEParameterSpecparamSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
//实例化
Cipher= cipher = Cipher.getInstance(ALGORITHM);
//初始化
cipher.init(Cipher.DECRYPT_MODE,key, paramSpec);
- KEY_ALGORITHM 指明加密算法,这里是PBEWITHMD5andDES加密算法。
- ITERATION_COUN迭代的次数。
+initSalt()PBE加密方式的初始化盐返回的是byte[] 盐,盐长度必须为8字节。
+ toKey(Stringpassword) 转换密钥,password是密码,返回Key类型密钥。
+encrypt(byte[]data, String password, byte[] salt) 加密方法。Data是数据,password是密钥,salt是盐,返回byte[]类型,是加密以后的数据。
+decrypt(byte[]data, String password, byte[] salt)解密方法,data是数据,password的密码,salt是盐,返回byte[]类型,是解以后的数据。
PBE算法实现和AES算法有很多类似的地方,相似的地方下面代码不具体介绍。
PBE的主要代码如下:
本系统在这里采用的是PBEWITHMD5andDES算法。
public static final String ALGORUTHM ="PBEWITHMD5andDES";
迭代次数
public static final int ITERATION_COUN = 100;
"盐"初始化
盐长度必须为8字节
返回:
byte[]盐
抛出:
java.lang.Exception
public static byte[] initSalt() throws Exception {
//实例化安全随机数
SecureRandom random = new SecureRandom();
//产出盐
return random.generateSeed(8);
}
转换密钥
参数:
password-密码
返回:
Key密钥
抛出:
java.lang.Exception
PBE算法定义并继承了SecretKey接口。
private static Key toKey(String password) throws Exception {
//密钥材料转换
PBEKeySpec keySpec = newPBEKeySpec(password.toCharArray());
//实例化
SecretKeyFactory keyFactory =SecretKeyFactory.getInstance(ALGORUTHM);
//生成密钥
SecretKey secretkey =keyFactory.generateSecret(keySpec);
return secretkey;
}
加密方法
参数:
data- 数据
password- 密钥
salt- 盐
返回:
byte[]加密数据
抛出:
java.lang.Exception
public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception{
//转换密钥
Key key = toKey(password);
//实例化PBE参考数据
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt,ITERATION_COUN);
//实例化
Cipher cipher = Cipher.getInstance(ALGORUTHM);
//初始化
cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);
//执行操作 return cipher.doFinal(data);
}
解密方法
参数:
data- 数据
password- 密码
salt- 盐
返回:
byte[]解密数据
抛出:
java.lang.Exception
public static byte[] decrypt(byte[] data, String password,byte[] salt) throws Exception{
//转换密钥
Key key = toKey(password);
//实例化PBE参数材料
PBEParameterSpec parameterSpec = newPBEParameterSpec(salt, ITERATION_COUN);
//实例化
Cipher cipher = Cipher.getInstance(ALGORUTHM);
//初始化
cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
//执行操作
return cipher.doFinal(data);
}
PBE算法实例验证PBECoder.java:
PBECoderTest.java
package com.wecode.database.secure; import org.apache.commons.codec.binary.Base64;
import org.junit.Test; /**
* PBE 检验
*
* @author WeCode ydonghao2
* @version 1.0
*/ public class PBECoderTest {
/**
* 测试
*
* @throws Exception
*/
/**
* 测试的时候人工可以引入junit.jar包
* @throws Exception
*/
//@Test
public static void main(String[] args) throws Exception {
String inputStr = "PBE";
System.err.println("原文:\t" + inputStr);
byte[] input = inputStr.getBytes();
String pwd = "ydonghao";
System.err.println("密码:\t" + pwd);
// 初始化盐
byte[] salt = PBECoder.initSalt();
System.err.println("盐:\t" + Base64.encodeBase64String(salt));
// 加密
byte[] data = PBECoder.encrypt(input, pwd, salt);
System.err.println("加密后\t" + Base64.encodeBase64String(data));
// 解密
byte[] output = PBECoder.decrypt(data, pwd, salt);
String outputStr = new String(output);
System.err.println("解密后\t" + outputStr);
}
}
这个加密算法的实现需要一些环境的搭建,参考这里:http://blog.csdn.net/ydonghao2/article/details/11046635
PBE加密算法的更多相关文章
- java-信息安全(三)-PBE加密算法
概述 信息安全基本概念: PBE算法(Password Based Encryption,基于口令加密) PBE PBE算法(Password Based Encryption,基于口令加密)是一种基 ...
- JAVA实现对称加密
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.对称加密算法DES 1.概述:采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这 ...
- DES、3DES、AES、PBE对称加密算法实现及应用
1.对称加密算法概述 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去.收信方收到密文后,若想解读原文 ...
- Android应用安全开发之浅谈加密算法的坑
<Android应用安全开发之浅谈加密算法的坑> 作者:阿里移动安全@伊樵,@舟海 阿里聚安全,一站式解决应用开发安全问题 Android开发中,难免会遇到需要加解密一些数据内 ...
- [Java 安全]加密算法
Base64编码 算法简述 定义 Base64内容传送编码是一种以任意8位字节序列组合的描述形式,这种形式不易被人直接识别. Base64是一种很常见的编码规范,其作用是将二进制序列转换为人类可读的A ...
- 使用java库中的对称加密算法
对称加密算法是说加密方和解密方使用相同的密钥.常见的对称加密算法包括4个,DES,DESede(3DES),AES,PBE. 本文讨论的内容是加密算法,不是Message Digest,不是编码.下面 ...
- 介绍对称加密的另一个算法——PBE
除了DES,我们还知道有DESede(TripleDES,就是3DES).AES.Blowfish.RC2.RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法 ...
- Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC
Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC 博客分类: Java/Security Javabase64macmd5sha 加密解密,曾经是我一 ...
- BASE64与单向加密算法MD5&SHA&MAC
言归正传,这里我们主要描述Java已经实现的一些加密解密算法,最后介绍数字证书. 如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Diges ...
随机推荐
- CSDN - 进程结束后new出的内存会回收吗?
http://blog.csdn.net/stanjiang2010/article/details/5386647 关键词:内存回收
- POJ 1141 Brackets Sequence (区间DP)
Description Let us define a regular brackets sequence in the following way: 1. Empty sequence is a r ...
- javascript 高级编程系列 - 继承
1. 原型链继承 (缺点:子类继承父类的引用类型的属性值会在各个实例中共享,创建子类实例时无法向父类构造函数传递参数) // 定义父类构造函数 function SuperClass(father, ...
- caffe搭建----Visual Studio 2015+CUDA8.0+CUDNN5配置Caffe-windows(BLVC)
原文来源: 来源:Angle_Cal 2016-12-19 17:32 本博主修改于2017-09-12. 版权所有,转载请注明出处. BLVC版本的Caffe-windows已经支持Vis ...
- 深入理解Java:注解(Annotation)自定义注解入门(转载)
要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...
- 【BZOJ4950】lydsy七月月赛 C 二分图最大匹配
[BZOJ4950]lydsy七月月赛 C 题面 题解:比较直接的想法就是:每行,每列的最大值都留下,剩下的格子都变成1.但是如果一个格子既是行的最大值又是列的最大值,那么我们只需要把它留下即可.这就 ...
- 关于4Ps 、4Cs 、4Rs 、4Vs营销策略的内容及优劣比较
- Raspberry Pi3 ~ 安装 nfs Server
l 安装必要服务: sudo apt-get install portmap sudo apt-get install nfs-kernel-server sudo apt ...
- ubuntu搭建mysql
步骤1 – 安装MySQL 在 Ubuntu 16.04 中,默认情况下,只有最新版本的 MySQL 包含在 APT 软件包存储库中.在撰写本文时,那是 MySQL 5.7 要安装它,只需更新服务器上 ...
- Shell脚本学习指南笔记
Shell脚本学习指南 作者:Danbo 2015-8-3 脚本编程语言与编译型语言的差异 许多中型.大型的程序都是用编译型语言写的,例如:C.C+.Java等.这类程序只要从源代码(Source C ...