一、簡述
對稱加密算法就是能將數(shù)據(jù)加解密。加密的時候用密鑰對數(shù)據(jù)進(jìn)行加密棺妓,解密的時候使用同樣的密鑰對數(shù)據(jù)進(jìn)行解密薪寓。
DES是美國國家標(biāo)準(zhǔn)研究所提出的算法亡资。因?yàn)榧咏饷艿臄?shù)據(jù)安全性和密鑰長度成正比。des的56位的密鑰已經(jīng)形成安全隱患向叉,在1998年之后就很少被采用锥腻。但是一些老舊的系統(tǒng)還在使用。因?yàn)檫@個des算法并沒有被美國標(biāo)準(zhǔn)委員會公布全部算法母谎,大家一致懷疑被留了后門瘦黑。所以慢慢就被淘汰掉了。
后來針對des算法進(jìn)行了改進(jìn)奇唤,有了三重des算法(DESede)幸斥。針對des算法的密鑰長度較短以及迭代次數(shù)偏少問題做了相應(yīng)改進(jìn),提高了安全強(qiáng)度咬扇。不過desede算法處理速度較慢甲葬,密鑰計算時間較長,加密效率不高問題使得對稱加密算法的發(fā)展不容樂觀懈贺。
二经窖、交互模型
1.消息傳遞雙方約定密鑰坡垫,通常由消息發(fā)送方(甲方)構(gòu)建密鑰通知消息接收方(乙方)
2.甲方使用密鑰對數(shù)據(jù)記性加密,然后將加密后的數(shù)據(jù)通過網(wǎng)絡(luò)傳送給乙方
3.乙方接收到數(shù)據(jù)画侣,然后使用約定的密鑰對數(shù)據(jù)進(jìn)行解密
整個模型很像hmac的數(shù)據(jù)交互過程葛虐,都是一個密鑰的概念,而且密鑰都是雙方知道的棉钧。但是hmac算法是信息摘要的獲取屿脐。這邊是對數(shù)據(jù)進(jìn)行加解密
三、java6和bouncycastle針對des算法的數(shù)據(jù)加密支持還是不同的宪卿。體現(xiàn)在密鑰長度的诵,工作模式以及填充方式上。這里bouncycastle的密鑰長度是64位佑钾。不過在DESede算法上bouncy castle也是密鑰長度比java6的密鑰長度要長西疤。
不過所有的對稱加密算法的實(shí)現(xiàn)還是類似的⌒萑埽可以參看如下的代碼:
1.des算法
package com.ca.test;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* DES對稱加密算法
* @author kongqz
* */
public class DESCoder {
/**
* 密鑰算法
* java支持56位密鑰代赁,bouncycastle支持64位
* */
public static final String KEY_ALGORITHM="DES";
/**
* 加密/解密算法/工作模式/填充方式
* */
public static final String CIPHER_ALGORITHM="DES/ECB/PKCS5Padding";
/**
*
* 生成密鑰,java6只支持56位密鑰兽掰,bouncycastle支持64位密鑰
* @return byte[] 二進(jìn)制密鑰
* */
public static byte[] initkey() throws Exception{
//實(shí)例化密鑰生成器
KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM);
//初始化密鑰生成器
kg.init(56);
//生成密鑰
SecretKey secretKey=kg.generateKey();
//獲取二進(jìn)制密鑰編碼形式
return secretKey.getEncoded();
}
/**
* 轉(zhuǎn)換密鑰
* @param key 二進(jìn)制密鑰
* @return Key 密鑰
* */
public static Key toKey(byte[] key) throws Exception{
//實(shí)例化Des密鑰
DESKeySpec dks=new DESKeySpec(key);
//實(shí)例化密鑰工廠
SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(KEY_ALGORITHM);
//生成密鑰
SecretKey secretKey=keyFactory.generateSecret(dks);
return secretKey;
}
/**
* 加密數(shù)據(jù)
* @param data 待加密數(shù)據(jù)
* @param key 密鑰
* @return byte[] 加密后的數(shù)據(jù)
* */
public static byte[] encrypt(byte[] data,byte[] key) throws Exception{
//還原密鑰
Key k=toKey(key);
//實(shí)例化
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
//初始化芭碍,設(shè)置為加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
//執(zhí)行操作
return cipher.doFinal(data);
}
/**
* 解密數(shù)據(jù)
* @param data 待解密數(shù)據(jù)
* @param key 密鑰
* @return byte[] 解密后的數(shù)據(jù)
* */
public static byte[] decrypt(byte[] data,byte[] key) throws Exception{
//歡迎密鑰
Key k =toKey(key);
//實(shí)例化
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
//初始化,設(shè)置為解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
//執(zhí)行操作
return cipher.doFinal(data);
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String str="DES";
System.out.println("原文:"+str);
//初始化密鑰
byte[] key=DESCoder.initkey();
System.out.println("密鑰:"+Base64.encodeBase64String(key));
//加密數(shù)據(jù)
byte[] data=DESCoder.encrypt(str.getBytes(), key);
System.out.println("加密后:"+Base64.encodeBase64String(data));
//解密數(shù)據(jù)
data=DESCoder.decrypt(data, key);
System.out.println("解密后:"+new String(data));
}
}
控制臺輸出結(jié)果:
原文:DES
密鑰:ocewbYVbtmE=
加密后:w6KsVSkLV3Q=
解密后:DES
2.desede算法演示
package com.ca.test;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* DESede對稱加密算法演示
* @author kongqz
* */
public class DESedeCoder {
/**
* 密鑰算法
* */
public static final String KEY_ALGORITHM="DESede";
/**
* 加密/解密算法/工作模式/填充方式
* */
public static final String CIPHER_ALGORITHM="DESede/ECB/PKCS5Padding";
/**
*
* 生成密鑰
* @return byte[] 二進(jìn)制密鑰
* */
public static byte[] initkey() throws Exception{
//實(shí)例化密鑰生成器
KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM);
//初始化密鑰生成器
kg.init(168);
//生成密鑰
SecretKey secretKey=kg.generateKey();
//獲取二進(jìn)制密鑰編碼形式
return secretKey.getEncoded();
}
/**
* 轉(zhuǎn)換密鑰
* @param key 二進(jìn)制密鑰
* @return Key 密鑰
* */
public static Key toKey(byte[] key) throws Exception{
//實(shí)例化Des密鑰
DESedeKeySpec dks=new DESedeKeySpec(key);
//實(shí)例化密鑰工廠
SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(KEY_ALGORITHM);
//生成密鑰
SecretKey secretKey=keyFactory.generateSecret(dks);
return secretKey;
}
/**
* 加密數(shù)據(jù)
* @param data 待加密數(shù)據(jù)
* @param key 密鑰
* @return byte[] 加密后的數(shù)據(jù)
* */
public static byte[] encrypt(byte[] data,byte[] key) throws Exception{
//還原密鑰
Key k=toKey(key);
//實(shí)例化
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
//初始化孽尽,設(shè)置為加密模式
cipher.init(Cipher.ENCRYPT_MODE, k);
//執(zhí)行操作
return cipher.doFinal(data);
}
/**
* 解密數(shù)據(jù)
* @param data 待解密數(shù)據(jù)
* @param key 密鑰
* @return byte[] 解密后的數(shù)據(jù)
* */
public static byte[] decrypt(byte[] data,byte[] key) throws Exception{
//歡迎密鑰
Key k =toKey(key);
//實(shí)例化
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
//初始化窖壕,設(shè)置為解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
//執(zhí)行操作
return cipher.doFinal(data);
}
/**
* 進(jìn)行加解密的測試
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String str="DESede";
System.out.println("原文:/t"+str);
//初始化密鑰
byte[] key=DESedeCoder.initkey();
System.out.println("密鑰:/t"+Base64.encodeBase64String(key));
//加密數(shù)據(jù)
byte[] data=DESedeCoder.encrypt(str.getBytes(), key);
System.out.println("加密后:/t"+Base64.encodeBase64String(data));
//解密數(shù)據(jù)
data=DESedeCoder.decrypt(data, key);
System.out.println("解密后:/t"+new String(data));
}
}
控制臺輸出結(jié)果:
原文: DESede
密鑰: BBDmwTjBsF7IwTIyGWt1bmFntRyUgMQL
加密后: FM/DsEv3KgM=
解密后: DESede
四、總結(jié)
1.主要看設(shè)定密鑰的長度的變化杉女。同時瞻讽,bouncycastle支持更多的填充模式,在相同算法上比java6實(shí)現(xiàn)的版本的密鑰長度要長
2.java的api中僅僅提供了DES,DESede和PBE 3三種對稱加密算法密鑰材料實(shí)現(xiàn)類