小說網(wǎng)站自動(dòng)采集圖片百度搜索
1.對(duì)稱加密算法定義:數(shù)據(jù)發(fā)送方將原始數(shù)據(jù)和加密密鑰經(jīng)過特殊加密算法處理后,將加密密文發(fā)送出去。接收方收到密文后,需要使用加密用過的密鑰及相同算法的逆算法對(duì)密文進(jìn)行解密,才能使其恢復(fù)成可讀明文。
2.在對(duì)稱加密算法中,使用的密鑰只有一個(gè),雙方都使用這個(gè)密鑰對(duì)數(shù)據(jù)進(jìn)行加密和解密,
常用的對(duì)稱加密算法:DES、3DES(TripleDES)和AES
常用的加密模式是:ECB:電子密碼本模式、CBC:加密分組鏈接模式
常用的填充方式是:NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充
3.注意以下區(qū)別
3.1.不同的加密算法,其工作密鑰不同且產(chǎn)生密鑰工廠的算法名不同
DES有很多同胞兄弟,如DESede(TripleDES)、AES大同小異,
(1)密鑰長度不同
DES固定工作密鑰(為8個(gè)字節(jié)共64位)
AES固定工作密鑰為16/24/32bytes。
(2)在產(chǎn)生密鑰工廠時(shí)只要換掉ALGORITHM換成對(duì)應(yīng)的值就行SecretKey secretKey = new SecretKeySpec(key, ALGORITHM),
3.2加密模式不同,初始化的隨機(jī)也不同
ECB采用分組加密的方式,將明文按8字節(jié)(64位)分組分別加密。
? ? CBC的處理方式是先用初始向量IV對(duì)第一組加密,再用第一組的密文作為密鑰對(duì)第二組加密,然后依次完成整個(gè)加密操作。如果明文中有兩個(gè)分組的內(nèi)容相同,ECB會(huì)得到完全一樣的密文,但CBC則不會(huì)。
DES下的cbc模式下的pkcs5padding可以用初始向量IV加密也能用SecureRandom,但是aes必須用初始向量
在初始化向量參數(shù)時(shí)AES 為16bytes. DES 為8bytes.
3.3填充方式不同
如果沒有指定,默認(rèn)的方式就是PKCS5Padding
? ?大部分情況下,明文并非剛好64位的倍數(shù)。對(duì)于最后一個(gè)分組,如果長度小于64位,則需要用數(shù)據(jù)填充至64位。
? ?PKCS7Padding是缺幾個(gè)字節(jié)就補(bǔ)幾個(gè)字節(jié)的0,
? ?PKCS5Padding是缺幾個(gè)字節(jié)就補(bǔ)充幾個(gè)字節(jié)的幾,好比缺6個(gè)字節(jié),就補(bǔ)充6個(gè)字節(jié)的6
4.有可能出現(xiàn)的錯(cuò)誤
(1)java.security.InvalidKeyException: Wrong key size工作密鑰(為8個(gè)字節(jié)共64位)
(2)javax.crypto.BadPaddingException: Given final block not properly padded
原因是Cipher cipher = Cipher.getInstance("DES");
5.主要步驟如下:
2.在對(duì)稱加密算法中,使用的密鑰只有一個(gè),雙方都使用這個(gè)密鑰對(duì)數(shù)據(jù)進(jìn)行加密和解密,
常用的對(duì)稱加密算法:DES、3DES(TripleDES)和AES
常用的加密模式是:ECB:電子密碼本模式、CBC:加密分組鏈接模式
常用的填充方式是:NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充
3.注意以下區(qū)別
3.1.不同的加密算法,其工作密鑰不同且產(chǎn)生密鑰工廠的算法名不同
DES有很多同胞兄弟,如DESede(TripleDES)、AES大同小異,
(1)密鑰長度不同
DES固定工作密鑰(為8個(gè)字節(jié)共64位)
AES固定工作密鑰為16/24/32bytes。
(2)在產(chǎn)生密鑰工廠時(shí)只要換掉ALGORITHM換成對(duì)應(yīng)的值就行SecretKey secretKey = new SecretKeySpec(key, ALGORITHM),
3.2加密模式不同,初始化的隨機(jī)也不同
ECB采用分組加密的方式,將明文按8字節(jié)(64位)分組分別加密。
? ? CBC的處理方式是先用初始向量IV對(duì)第一組加密,再用第一組的密文作為密鑰對(duì)第二組加密,然后依次完成整個(gè)加密操作。如果明文中有兩個(gè)分組的內(nèi)容相同,ECB會(huì)得到完全一樣的密文,但CBC則不會(huì)。
DES下的cbc模式下的pkcs5padding可以用初始向量IV加密也能用SecureRandom,但是aes必須用初始向量
在初始化向量參數(shù)時(shí)AES 為16bytes. DES 為8bytes.
3.3填充方式不同
如果沒有指定,默認(rèn)的方式就是PKCS5Padding
? ?大部分情況下,明文并非剛好64位的倍數(shù)。對(duì)于最后一個(gè)分組,如果長度小于64位,則需要用數(shù)據(jù)填充至64位。
? ?PKCS7Padding是缺幾個(gè)字節(jié)就補(bǔ)幾個(gè)字節(jié)的0,
? ?PKCS5Padding是缺幾個(gè)字節(jié)就補(bǔ)充幾個(gè)字節(jié)的幾,好比缺6個(gè)字節(jié),就補(bǔ)充6個(gè)字節(jié)的6
4.有可能出現(xiàn)的錯(cuò)誤
(1)java.security.InvalidKeyException: Wrong key size工作密鑰(為8個(gè)字節(jié)共64位)
(2)javax.crypto.BadPaddingException: Given final block not properly padded
原因是Cipher cipher = Cipher.getInstance("DES");
等同于Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding")一樣,填充方式錯(cuò)誤,加密的時(shí)候會(huì)得到16長度的字節(jié)數(shù)組。
/*簡單Des算法加密解密使用ECB/NoPadding主要參數(shù)有:工作密鑰(為8個(gè)字節(jié)共64位)數(shù)據(jù)(為8個(gè)字節(jié)共64位)指定工作方式(ECB/NoPadding)且隨機(jī)數(shù)用new SecureRandom()*/
public class DesEcbNopaddingSafety {public static void main(String[] args) {String data = "12345678";String key = "12345678";byte[] encryData = encrydata(data, key);String encryD = new Base64().encodeAsString(encryData);System.out.println("加密后的數(shù)據(jù)是:" + encryD);byte[] decodeD = new Base64().decode(encryD);byte[] descryData = bytedecryData(decodeD, key);String d = new String(descryData);System.out.println("解密后的數(shù)據(jù)是:" + d);}private static byte[] bytedecryData(byte[] decodeD, String key) {// TODO Auto-generated method stubbyte[] deData = null;try {SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");DESKeySpec dks = new DESKeySpec(key.getBytes());SecretKey securekey = keyFactory.generateSecret(dks);Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");SecureRandom random = new SecureRandom();cipher.init(Cipher.ENCRYPT_MODE, securekey, random);deData = cipher.doFinal(decodeD);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return deData;}private static byte[] encrydata(String data, String key) {// TODO Auto-generated method stubbyte[] encryData = null;try {// 創(chuàng)建一個(gè)密鑰工廠SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DES");// 根據(jù)原始密鑰數(shù)據(jù)創(chuàng)建密鑰對(duì)象DESKeySpec,使用 key 中的前 8 個(gè)字節(jié)作為 DES 密鑰的密鑰內(nèi)容DESKeySpec dks = new DESKeySpec(key.getBytes());// 在用密鑰工廠把DESKeySpec變成規(guī)范的密鑰對(duì)象SecretKeySecretKey securekey = keyfactory.generateSecret(dks);// 生成一個(gè)可信任的隨機(jī)數(shù)源SecureRandom random = new SecureRandom();// 通過Cipher.getInstance()工廠方法來實(shí)例化密碼對(duì)象。Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");// 用密鑰、算法參數(shù)和隨機(jī)源初始化此Cipher密碼對(duì)象cipher.init(Cipher.DECRYPT_MODE, securekey, random);// 執(zhí)行加密encryData = cipher.doFinal(data.getBytes());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return encryData;}
}<pre name="code" class="java">
加密后的數(shù)據(jù)是:9ejp64Hyi3M=
解密后的數(shù)據(jù)是:12345678
/*使用DES/CBC/PKCS5Padding加密且隨機(jī)數(shù)用new IvParameterSpec(iv1)*/
public class DesCbcPkcs5Safety {public static void main(String[] args) {String data = "1234578";String key = "12345678";byte[] encryData = encrydata(data, key);String encryD = new Base64().encodeAsString(encryData);System.out.println("加密后的數(shù)據(jù)是:" + encryD);byte[] decodeD = new Base64().decode(encryD);byte[] descryData = bytedecryData(decodeD, key);String d = new String(descryData);System.out.println("解密后的數(shù)據(jù)是:" + d);}private static byte[] bytedecryData(byte[] decodeD, String key) {// TODO Auto-generated method stubbyte[] deData = null;try {SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");DESKeySpec dks = new DESKeySpec(key.getBytes());SecretKey securekey = keyFactory.generateSecret(dks);Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");// 這里使用的是向量。采用此代碼中的IVParameterSpecIvParameterSpec iv = new IvParameterSpec(iv1);cipher.init(Cipher.DECRYPT_MODE, securekey, iv);deData = cipher.doFinal(decodeD);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return deData;}private static byte[] encrydata(String data, String key) {// TODO Auto-generated method stubbyte[] encryData = null;try {Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DES");SecretKey securekey = keyfactory.generateSecret(new DESKeySpec(key.getBytes()));// 注意這里使用的是向量IvParameterSpec iv = new IvParameterSpec(iv1);cipher.init(Cipher.ENCRYPT_MODE, securekey, iv);encryData = cipher.doFinal(data.getBytes());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return encryData;}private static byte[] iv1 = { (byte) 0x12, (byte) 0x34, (byte) 0x56,(byte) 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF };
}
加密后的數(shù)據(jù)是:DXCyuKP3IWQ=
解密后的數(shù)據(jù)是:1234578
5.主要步驟如下:
(1).利用SecretKeyFactory.getInstance("加密算法")創(chuàng)建密鑰工廠
(2).用new DESKeySpec(原始密鑰)產(chǎn)生密鑰對(duì)象
(3).用密鑰工廠的generateSecret(密鑰對(duì)象)方法把密鑰對(duì)象轉(zhuǎn)換成規(guī)范的密鑰對(duì)象
(4).用new SecureRandom()或者用 new IvParameterSpec(向量)生成一個(gè)可信任的隨機(jī)數(shù)源
(5).用Cipher.getInstance("加密算法/加密模式/填充模式")產(chǎn)生加密解密對(duì)象
(6).用cipher.init(加密解密模型,規(guī)范密鑰,隨機(jī)數(shù))初始化加密解密對(duì)象
(7).用cipher.doFinal(數(shù)據(jù))執(zhí)行加密解密操作