在ECB模式(electronic codebook mode)中不須要IV,可是也所以會出現相同明文的區塊會產生相同密文而很容易被找到規律。因此不安全。
DES是標準的對稱加密算法,算法採用的密鑰長度能夠是8bit或者16bit。加密的結果不同,由於VI(初始向量)不一樣。
DES的起始VI是隨機的,因此加密結果不一樣。可是解密過程是相反的,解密到最後一組字節流的時候就獲得了VI,這個VI在解密完成後會被捨棄。因此兩種實現的加密的結果不一樣是沒有關係的,一樣能夠解密。java
最基本的des加密解密代碼:算法
package com.neusoft.si.simis.ws.faceRecognition.bean; import java.security.Key; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; import org.apache.axis.encoding.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class Des { public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding"; private static Log log = LogFactory.getLog(Des.class); /** * DES算法,加密 * * @param data * 待加密字符串 * @param key * 加密私鑰,長度不可以小於8位 * @return 加密後的字節數組,通常結合Base64編碼使用 * @throws CryptException * 異常 */ public static String encode(String key, String data) throws Exception { return encode(key, data.getBytes()); } /** * DES算法,加密 * * @param data * 待加密字符串 * @param key * 加密私鑰,長度不可以小於8位 * @return 加密後的字節數組,通常結合Base64編碼使用 * @throws CryptException * 異常 */ public static String encode(String key, byte[] data) throws Exception { try { DESKeySpec dks = new DESKeySpec(key.getBytes()); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); // key的長度不可以小於8位字節 Key secretKey = keyFactory.generateSecret(dks); Cipher cipher = Cipher.getInstance(ALGORITHM_DES); IvParameterSpec iv = new IvParameterSpec("********".getBytes()); AlgorithmParameterSpec paramSpec = iv; cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec); byte[] bytes = cipher.doFinal(data); return Base64.encode(bytes); } catch (Exception e) { throw new Exception(e); } } /** * DES算法,解密 * * @param data * 待解密字符串 * @param key * 解密私鑰,長度不可以小於8位 * @return 解密後的字節數組 * @throws Exception * 異常 */ public static byte[] decode(String key, byte[] data) throws Exception { try { SecureRandom sr = new SecureRandom(); DESKeySpec dks = new DESKeySpec(key.getBytes()); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); // key的長度不可以小於8位字節 Key secretKey = keyFactory.generateSecret(dks); Cipher cipher = Cipher.getInstance(ALGORITHM_DES); IvParameterSpec iv = new IvParameterSpec("********".getBytes()); AlgorithmParameterSpec paramSpec = iv; cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec); return cipher.doFinal(data); } catch (Exception e) { // e.printStackTrace(); throw new Exception(e); } } /** * 獲取編碼後的值 * * @param key * @param data * @return * @throws Exception * @throws Exception */ public static String decodeValue(String key, String data) throws Exception { byte[] datas; String value = null; datas = decode(key, Base64.decode(data)); value = new String(datas); if (value.equals("")) { throw new Exception(); } return value; } public static void main(String arg[]){ try { System.out.println("加密:"+encode("12345678","adfadsfasdf")); System.out.println("解密:"+decodeValue("12345678","09b+G8cW4Zqirv2eWerRng==")); } catch (Exception e) { e.printStackTrace(); } } }
des中cbc模式加密解密:apache
package com.neusoft.des.util; import java.util.Vector; public class CbcEn { private String algorithm;// 算法參數 private String keyStr;// 祕鑰字符串 private byte[] seed;// 種子 private byte[] plainText;// 欲加密字符串 private byte[] subText;// 對欲加密字符串的字節數組8字節1截取,存入此字節數組,進行加密 String iv;// 初始種子字符串 public CbcEn(String alg, String keyStr, String iv, byte[] msg) { algorithm = alg; this.keyStr = keyStr; this.iv = iv; seed = new byte[8]; for (int i = 0; i < 8; i++) seed[i] = 0; for (int i = 0; i < 8 & i < iv.length(); i++) seed[i] = iv.getBytes()[i]; subText = new byte[8]; plainText = msg; } // 加密函數 public byte[] CipherMsg() { byte[] cipherText;// 加密結果存入此字節數組 byte[] subCiper;// 每8字節加密,結果存入此字節數組 Vector<byte[]> cipherVector = new Vector<byte[]>();// 每8位加密結果的字節數組,存入此向量類,最後生成ciperText int loopTimes;// 判斷明文須要執行多少次循環加密 int plainLength = plainText.length; if (plainLength % 8 > 0) { loopTimes = plainLength / 8 + 1; } else loopTimes = plainLength / 8; for (int i = 0; i < loopTimes; i++) { for (int j = 0; j < 8; j++) subText[j] = 0; // 取子串 for (int m = 0; m < 8 & i * 8 + m < plainText.length; m++) subText[m] = plainText[i * 8 + m]; // 子串與種子異或 for (int n = 0; n < 8; n++) subText[n] ^= seed[n]; subCiper = new DesEn(algorithm, keyStr, subText).CipherMsg();// 對異或結果進行DES加密 cipherVector.add(subCiper);// 暫存子串加密結果 // 種子置爲上一次子串的加密結果 for (int k = 0; k < 8 & k < subCiper.length; k++) seed[k] = subCiper[k]; } // 合併加密結果 cipherText = new byte[8 * cipherVector.size()]; for (int i = 0; i < cipherVector.size(); i++) { subText = (byte[]) cipherVector.get(i); for (int j = i * 8; j < (i + 1) * 8; j++) { cipherText[j] = subText[j % 8]; } } return cipherText; } // 解密函數 public byte[] EncipherMsg(byte[] cipherText, String iv, String keyStr) { byte[] sourceText;// 解密明文存入此字節數組 byte[] subSourceText = new byte[8];// 對密文8字節一截取,存入此字節數組 byte[] subCipherText = new byte[8];// 8字節密文解密結果,存入此字節數組 Vector<byte[]> sourceTextVector = new Vector<byte[]>();// 8字節密文解密結果數組,存入此向量,最後存入sourceText int loopTimes = cipherText.length / 8;// 解密循環次數 // 種子初始化 for (int i = 0; i < 8; i++) seed[i] = 0; for (int i = 0; i < 8 & i < iv.length(); i++) seed[i] = iv.getBytes()[i]; for (int i = 0; i < loopTimes; i++) { // 對密文取8字節進行解密 for (int j = 0; j < 8; j++) subCipherText[j] = cipherText[i * 8 + j]; subSourceText = new DesEn(algorithm, keyStr, null).EncipherMsg( subCipherText, keyStr); // 解密結果與種子異或,得8字節明文子串字節數組 for (int m = 0; m < 8; m++) subSourceText[m] ^= seed[m]; sourceTextVector.add(subSourceText);// 暫存8字節明文子串字節數組 // 種子置爲8字節密文子串 for (int k = 0; k < 8 & k < subCipherText.length; k++) seed[k] = subCipherText[k]; } // 合併解密結果 sourceText = new byte[loopTimes * 8]; for (int i = 0; i < sourceTextVector.size(); i++) { subSourceText = (byte[]) sourceTextVector.get(i); for (int j = i * 8; j < (i + 1) * 8; j++) { sourceText[j] = subSourceText[j % 8]; } } return sourceText; } }
cfb模式:數組
package com.neusoft.des.util; import java.util.Vector; public class CfbEn { private String algorithm;// 算法參數 private String keyStr;// 祕鑰字符串 private byte[] seed;// 種子 private byte[] plainText;// 欲加密字符串 private byte subText = 0;// 對欲加密字符串的字符數組每字節1截取,存入進行加密 String iv;// 初始種子字符串 public CfbEn(String alg, String keyStr, String iv, byte[] msg) { algorithm = alg; this.keyStr = keyStr; this.iv = iv; seed = new byte[8]; for (int i = 0; i < 8; i++) seed[i] = 0; for (int i = 0; i < 8 & i < iv.length(); i++) seed[i] = iv.getBytes()[i]; plainText = msg; } // 加密函數 public byte[] CipherMsg() { byte[] cipherText;// 加密結果存入此字符數組 byte subCipher = 0;// 對每字節加密,結果存入此字節 byte[] seedTemp = new byte[8];// 種子左移1字節,暫存數組 Vector<Byte> cipherVector = new Vector<Byte>();// 暫存加密結果 int loopTimes = plainText.length;// 加密循環次數 for (int i = 0; i < loopTimes; i++) { subText = plainText[i]; subCipher = (new DesEn(algorithm, keyStr, seed).CipherMsg())[0];// 對seed進行DES加密,取首字節 subCipher ^= subText;// 首字節與欲加密原文字節異或,得加密字節 cipherVector.add(subCipher); // seed左移一字節,最後一字節存入本次加密結果 for (int j = 0; j < 7; j++) seedTemp[j] = seed[j + 1]; seedTemp[7] = subCipher; for (int k = 0; k < 8; k++) seed[k] = seedTemp[k]; } // 合併加密結果 cipherText = new byte[cipherVector.size()]; for (int i = 0; i < cipherVector.size(); i++) { subText = cipherVector.get(i).byteValue(); cipherText[i] = subText; } return cipherText; } // 解密函數 public byte[] EncipherMsg(byte[] cipherText, String iv, String keyStr) { byte[] sourceText;// 解密明文存入此字節數組 byte cipherSeed = 0;// 暫存對seed進行DES加密結果的首字節 byte subCipher = 0;// 密文取1字節進行解密 byte[] seedTemp = new byte[8];// 種子左移1字節,暫存數組 Vector<Byte> sourceTextVector = new Vector<Byte>(); int loopTimes = cipherText.length; for (int i = 0; i < 8; i++) seed[i] = 0; for (int i = 0; i < 8 & i < iv.length(); i++) seed[i] = iv.getBytes()[i]; for (int i = 0; i < loopTimes; i++) { subCipher = cipherText[i];// 取密文一個字節進行解密 cipherSeed = (new DesEn(algorithm, keyStr, seed).CipherMsg())[0];// 對seed進行DES加密,取首字節 sourceTextVector.add((byte) (subCipher ^ cipherSeed));// 首字節與密文字節異或,得解密字節,暫存 // seed左移1字節,最後一字節存入密文字節 for (int j = 0; j < 7; j++) seedTemp[j] = seed[j + 1]; seedTemp[7] = subCipher; for (int k = 0; k < 8; k++) seed[k] = seedTemp[k]; } // 合併解密結果 sourceText = new byte[sourceTextVector.size()]; for (int i = 0; i < sourceTextVector.size(); i++) { sourceText[i] = sourceTextVector.get(i).byteValue(); } return sourceText; } }
ofb模式:安全
package com.neusoft.des.util; import java.util.Vector; public class OfbEn { private String algorithm;// 算法參數 private String keyStr;// 祕鑰字符串 private byte[] seed;// 種子 private byte[] plainText;// 欲加密字符串 private byte subText = 0;// 對欲加密字符串的字符數組每字節1截取,存入進行加密 String iv;// 初始種子字符串 public OfbEn(String alg, String keyStr, String iv, byte[] msg) { algorithm = alg; this.keyStr = keyStr; this.iv = iv; seed = new byte[8]; for (int i = 0; i < 8; i++) seed[i] = 0; for (int i = 0; i < 8 & i < iv.length(); i++) seed[i] = iv.getBytes()[i]; plainText = msg; } // 加密函數 public byte[] CipherMsg() { byte[] cipherText;// 加密結果存入此字符數組 byte subCipher = 0;// 對每字節加密,結果存入此字節 byte[] seedTemp = new byte[8];// 種子左移1字節,暫存數組 Vector<Byte> cipherVector = new Vector<Byte>();// 暫存加密結果 int loopTimes = plainText.length;// 加密循環次數 for (int i = 0; i < loopTimes; i++) { subText = plainText[i]; subCipher = (new DesEn(algorithm, keyStr, seed).CipherMsg())[0];// 對seed進行DES加密,取首字節,爲加密密文 // seed左移1字節,最後一字節存入密文與明文異或的結果 for (int j = 0; j < 7; j++) seedTemp[j] = seed[j + 1]; seedTemp[7] = subCipher; for (int k = 0; k < 8; k++) seed[k] = seedTemp[k]; subCipher ^= subText; cipherVector.add(subCipher); } // 合併加密結果 cipherText = new byte[cipherVector.size()]; for (int i = 0; i < cipherVector.size(); i++) { subText = cipherVector.get(i).byteValue(); cipherText[i] = subText; } return cipherText; } // 解密函數 public byte[] EncipherMsg(byte[] cipherText, String iv, String keyStr) { byte[] sourceText;// 解密明文存入此字節數組 byte cipherSeed = 0;// 暫存對seed進行DES加密結果的首字節 byte subCipher = 0;// 密文取1字節進行解密 byte[] seedTemp = new byte[8];// 種子左移1字節,暫存數組 Vector<Byte> sourceTextVector = new Vector<Byte>(); int loopTimes = cipherText.length; for (int i = 0; i < 8; i++) seed[i] = 0; for (int i = 0; i < 8 & i < iv.length(); i++) seed[i] = iv.getBytes()[i]; for (int i = 0; i < loopTimes; i++) { subCipher = cipherText[i];// 取密文一個字節進行解密 cipherSeed = (new DesEn(algorithm, keyStr, seed).CipherMsg())[0];// 對seed進行DES加密,取首字節 sourceTextVector.add((byte) (subCipher ^ cipherSeed));// 首字節與密文字節異或,得解密字節,暫存 // seed左移1字節,最後一字節存入seed進行DES加密結果的首字節 for (int j = 0; j < 7; j++) seedTemp[j] = seed[j + 1]; seedTemp[7] = cipherSeed; for (int k = 0; k < 8; k++) seed[k] = seedTemp[k]; } // 合併解密結果 sourceText = new byte[sourceTextVector.size()]; for (int i = 0; i < sourceTextVector.size(); i++) { sourceText[i] = sourceTextVector.get(i).byteValue(); } return sourceText; } }
各類模式的用法背景和特色後續再表述。dom