說明:上篇RSA是一種非對稱的加解密演算法,今天這種是一種對稱的加解密演算法DESDES演算法的入口引數有三個:Key、Data、Mode。其中Key為7個位元組共56位,是DES演算法的工作金鑰;Data為8個位元組64位,是要被加密或被解密的資料;Mode為DES的工作方式,有兩種:加密或解密。Java裡封裝了很多種對稱加密演算法的使用,這裡以DES為例。
一、什麼是對稱演算法
對稱密碼演算法有時又叫傳統密碼演算法,就是加密金鑰能夠從解密金鑰中推算出來,反過來也成立。加密與解密互逆,在大多數對稱演算法中,加密解密金鑰是相同的。
圖 1優點:效率高(加/解密速度能達到數十兆/秒或更多),演算法簡單,系統開銷小,適合加密大量資料。 缺點:進行安全通訊前需要以安全方式進行金鑰交換,安全得不到有效保證,規模旁雜。
二、金鑰的機制
DES金鑰初始化的長度是64位,而實際可用的位置是56位,因為DES演算法規定,第8、16、……64位是奇偶校驗位,不參與DES運算。
1、初始序化Key的長度
圖 2所以這裡最好不要去指定長度了,預設的就是56了。
2、如果指定的key超過64位有啥影響
圖 3 圖 4通過上面圖3、圖4對比可知(加密後序列一樣,大家可以直接把生成key序列16進位制打出來更直觀),初始的key序列超過8位元組64位,會自動擷取掉,後面多餘長度不參與key生成。
3、不同的加密序列加密後結果一樣
圖 5 參考圖3、圖5將位元組陣列中的18->19,發現加密後的序列完全一樣。啥原因呢?在上面已經提到過,DES實現中第8、16、32... 64位為校驗位,相當於只是用每個位元組中的前7位進行生成;將18、19轉化為二進位制為00010010 、00010011 然後去掉最後一位,可以發現前7位是一樣的。所以這樣解釋了為什麼有時候加密序列不同,加密後的內容卻是完全一樣。
三、完整的DEMO
如果讓Base64具有加解密的功能,至少要一部分是變化的;這裡可以通過變化標準序列的方式;建議大家用到的時候,可以先看一下第3部分中標出那個類的原始碼(沒幾行程式碼);這個變化的序列可以根據時間、根據UUID、根據一切可以變換的東西來生成,這裡是根據UUID來隨機生成序列。 1、生成隨機序列
package c.d.des;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
public class DesTest {
Cipher cipher = null;
public DesTest() {
init();
}
public void init() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56);
cipher = Cipher.getInstance("DES");
} catch (Exception e) {
e.printStackTrace();
}
}
// 二進位制轉換字串
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
// 獲取Key
public Key getKey(byte[] passKey) {
Key convertSecretKey = null;
try {
DESKeySpec deSedeKeySpec = new DESKeySpec(passKey);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
convertSecretKey = factory.generateSecret(deSedeKeySpec);
} catch (Exception e) {
e.printStackTrace();
}
return convertSecretKey;
}
// 加密
public byte[] encode(byte[] source, Key key) throws Exception {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encodeSource = cipher.doFinal(source);
return encodeSource;
}
// 解密
public String decode(byte[] encodeSource, Key key) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decodeRes = cipher.doFinal(encodeSource);
return new String(decodeRes, "UTF-8");
}
public static void main(String[] args) throws Exception {
DesTest dt = new DesTest();
byte[] passKey = new byte[] {11, 12, 13, 14, 15, 16, 17,18,19,20 };
System.out.println(passKey.length);
Key key = dt.getKey(passKey);
String obj = "就先測試這句吧";
System.out.println("加密前:" + obj);
byte[] source = dt.encode(obj.getBytes("UTF-8"), key);
System.out.println("加密後:" + bytesToHexString(source));
String res = dt.decode(source, key);
System.out.println("解密後:" + res);
String s1 = "0815d22bf5ae0bdd9d37594cedd4be6c1fead86115544517";
String s2 = "0815d22bf5ae0bdd9d37594cedd4be6c1fead86115544517";
System.out.println(s1.equals(s2));
}
}
複製程式碼
四、後續
既然DES通過暴力一天便可破解,那麼3DES如何?大家可以自行研究一下,和DES類似。
持續更新中,可以關注........