一、簡述
PBE算法(Password Base Encryption,基於口令加密)算法是一種基於口令的加密算法。特點在於口令由用戶自己掌握,採用隨機數(我們這裏叫做 鹽)雜湊多重加密等方法保證數據的安全性。
PBE算法沒有密鑰的概念,把口令當做密鑰了。因爲密鑰長短影響算法安全性,還不方便記憶,這裏我們直接換成我們自己常用的口令就大大不同了,便於我們的記憶。但是單純的口令很容易被字典法給窮舉出來,所以我們這裏給口令加了點“鹽”,這個鹽和口令組合,想破解就難了。
同時我們將鹽和口令合併後用消息摘要算法進行迭代很多次來構建密鑰初始化向量的基本材料,使破譯更加難了。
PBE算法沒構建新的加密算法,就是用了我們常用的對稱加密算法,例如AES,DES等算法。
二、模型分析
這裏我們還是假設甲乙雙發要傳遞消息,需要口令和鹽還有算法
傳統的對稱加密算法就是,構建密鑰,指定算法,然後發送數據前用密鑰加密數據,密鑰和加密後的數據一起發送給對方,對方拿着密鑰對數據進行解密。
現在是密鑰沒有了,我們就用“口令+鹽”構造出一個密鑰,然後對數據進行加密
這裏“口令”我們可以隨便設置,都可以設置成我們開自己電腦的密碼
這裏“鹽”的設置可以採用隨機數,可以是甲乙雙方約定的數據
最終我們的口令和鹽都要公佈給雙方
1、消息傳遞雙方約定口令,這裏甲方構建口令
2、甲方構建口令後,公佈給乙方
3、由口令構建方(甲方)構建本次消息傳遞使用的鹽,其實也可以雙方約定一個數據,例如硬盤號,今天的日期等等,不一定非要寫個安全算法計算出來,只要雙方一致就行
4、甲方使用口令、鹽對數據加密
5、甲方將鹽、加密數據發送給消息接收者(乙方)
6、乙方用收到的口令、鹽(可以是約定的數據)對數據進行解密
總體看來口令和鹽兩邊都需要知道。消息傳遞過程還是需要指定雙方的統一算法進行。而這些算法其實還是用的那些常見的對稱加密算法
三、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實現 |
四、程序展示
- package com.ca.test;
- 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 org.apache.commons.codec.binary.Base64;
- /**
- * 對稱加密算法:基於口令加密-PBE算法實現
- * 使用java6提供的PBEWITHMD5andDES算法進行展示
- * @author kongqz
- * */
- public class PBECoder {
- /**
- * JAVA6支持以下任意一種算法
- * PBEWITHMD5ANDDES
- * PBEWITHMD5ANDTRIPLEDES
- * PBEWITHSHAANDDESEDE
- * PBEWITHSHA1ANDRC2_40
- * PBKDF2WITHHMACSHA1
- * */
- public static final String ALGORITHM="PBEWITHMD5andDES";
- /**
- * 迭代次數
- * */
- public static final int ITERATION_COUNT=100;
- /**
- * 鹽初始化
- * 鹽長度必須爲8字節
- * @return byte[] 鹽
- * */
- public static byte[] initSalt() throws Exception{
- //實例化安全隨機數
- SecureRandom random=new SecureRandom();
- //產出鹽
- return random.generateSeed(8);
- }
- /**
- * 轉換密鑰
- * @param password 密碼
- * @return Key 密鑰
- * */
- private static Key toKey(String password) throws Exception{
- //密鑰彩禮轉換
- PBEKeySpec keySpec=new PBEKeySpec(password.toCharArray());
- //實例化
- SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(ALGORITHM);
- //生成密鑰
- SecretKey secretKey=keyFactory.generateSecret(keySpec);
- return secretKey;
- }
- /**
- * 加密
- * @param data 待加密數據
- * @param password 密碼
- * @param salt 鹽
- * @return byte[] 加密數據
- *
- * */
- public static byte[] encrypt(byte[] data,String password,byte[] salt) throws Exception{
- //轉換密鑰
- Key key=toKey(password);
- //實例化PBE參數材料
- PBEParameterSpec paramSpec=new PBEParameterSpec(salt,ITERATION_COUNT);
- //實例化
- Cipher cipher=Cipher.getInstance(ALGORITHM);
- //初始化
- cipher.init(Cipher.ENCRYPT_MODE, key,paramSpec);
- //執行操作
- return cipher.doFinal(data);
- }
- /**
- * 解密
- * @param data 待解密數據
- * @param password 密碼
- * @param salt 鹽
- * @return byte[] 解密數據
- *
- * */
- public static byte[] decrypt(byte[] data,String password,byte[] salt) throws Exception{
- //轉換密鑰
- Key key=toKey(password);
- //實例化PBE參數材料
- PBEParameterSpec paramSpec=new PBEParameterSpec(salt,ITERATION_COUNT);
- //實例化
- Cipher cipher=Cipher.getInstance(ALGORITHM);
- //初始化
- cipher.init(Cipher.DECRYPT_MODE, key,paramSpec);
- //執行操作
- return cipher.doFinal(data);
- }
- /**
- * 使用PBE算法對數據進行加解密
- * @throws Exception
- *
- */
- public static void main(String[] args) throws Exception {
- //待加密數據
- String str="PBE";
- //設定的口令密碼
- String password="azsxdc";
- System.out.println("原文:/t"+str);
- System.out.println("密碼:/t"+password);
- //初始化鹽
- byte[] salt=PBECoder.initSalt();
- System.out.println("鹽:/t"+Base64.encodeBase64String(salt));
- //加密數據
- byte[] data=PBECoder.encrypt(str.getBytes(), password, salt);
- System.out.println("加密後:/t"+Base64.encodeBase64String(data));
- //解密數據
- data=PBECoder.decrypt(data, password, salt);
- System.out.println("解密後:"+new String(data));
- }
- }
- 控制檯結果輸出:
- 原文: PBE
- 密碼: azsxdc
- 鹽: VeEQqRzOw2Y=
- 加密後: 7bQTon5WD04=
- 解密後:PBE
五、總結
PBE不是一個新構建的算法,就是將密鑰的概念轉成 “口令+鹽” 的方式,將不便於記憶的密鑰轉成便於記憶的口令
算法還是用的基本的對稱加密算法,從上邊的支持表中就能看到。
這個是不是和我們到銀行開的U盾有些像呢?
就拿民生銀行的U盾來說,我們插上U盾,還需要我們去輸入口令。然後才能到網上銀行去登陸操作,付款的時候還是需要我們去輸入口令。
1、U盾的鹽從何來?:應該是那個閃盤的序列編號經過一定的處理得出的一個值,因爲我們想要U盾生效,在民生的大廳中需要找一個機器激活的。那個激活的動作應該是將我們U盾這個閃盤中的數據寫入到我們個人的賬戶中,相當於做了一次鹽的公佈
2、口令何來?:就是我們設定的登陸密碼呀。這個在窗口辦理的時候需要我們設定U盾的密碼。並且我們在激活的時候可以改我們的密碼
有了上邊兩個,我們再進行操作,就可以進行我們的身份發送數據的安全性了。網銀的數據交換真的安全了...