1.流程
對稱式加密演算法就是能將資料加解密。加密的時候用金鑰組資料進行加密,解密的時候使用同樣的金鑰組資料進行解密。 DES是美國國家標準研究所提出的演算法。因為加解密的資料安全性和密鑰長度成正比。des的56位的密鑰已經形成安全隱患,在1998年之後就很少被採用。但是一些老舊的系統還在使用。因為這個des演算法並沒有被美國標準委員會公布全部演算法,大家一致懷疑被留了後門。所以慢慢就被淘汰掉了。 後來針對des演算法進行了改進,有了三重des演算法(DESede)。針對des演算法的密鑰長度較短以及迭代次數偏少問題做了相應改進,提高了安全強度。不過desede演算法處理速度較慢,密鑰計算時間較長,加密效率不高問題使得對稱式加密演算法的發展不容樂觀。
DES演算法提供CBC, OFB, CFB, ECB四種模式,MAC是基於ECB實現的。
【Java使用3DES加密解密的流程】 ①傳入共同約定的密鑰(keyBytes)以及演算法(Algorithm),來構建SecretKey金鑰組象 SecretKey deskey = new SecretKeySpec(keyBytes, Algorithm); ②根據演算法執行個體化Cipher對象。它負責加密/解密 Cipher c1 = Cipher.getInstance(Algorithm); ③傳入加密/解密模式以及SecretKey金鑰組象,執行個體化Cipher對象 c1.init(Cipher.ENCRYPT_MODE, deskey); ④傳入位元組數組,調用Cipher.doFinal()方法,實現加密/解密,並返回一個byte位元組數組 c1.doFinal(src);
2.代碼
DES類型加密解密:
package com.tianxin.itfin.core.helper;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;import javax.crypto.spec.DESedeKeySpec;import javax.crypto.spec.IvParameterSpec;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.security.Key;import java.security.SecureRandom;/** * 3DES加密工具類 */public class EncryptUtils { // 密鑰(DES加密和解密過程中,密鑰長度都必須是8的倍數) private final static String secretKey = "ucserver"; // 加解密統一使用的編碼方式 private final static String encoding = "utf-8"; /** * 3DES加密 * * @param plainText 普通文本 * @return * @throws Exception */ public static String encode(String plainText) throws Exception { // DES演算法要求有一個可信任的隨機數源 SecureRandom sr = new SecureRandom(); // 從原始密鑰資料建立DESKeySpec對象 DESKeySpec dks = new DESKeySpec(secretKey.getBytes()); // 建立一個密匙工廠,然後用它把DESKeySpec轉換成 // 一個SecretKey對象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");//DES加密和解密過程中,密鑰長度都必須是8的倍數 SecretKey secretKey = keyFactory.generateSecret(dks); // using DES in ECB mode Cipher cipher = Cipher.getInstance("DES/ECB/pkcs5padding"); // 用密匙初始化Cipher對象 cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr); // 執行加密操作 byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding)); return Base64.encode(encryptData); } /** * 3DES解密 * * @param encryptText 加密文本 * @return * @throws Exception */ public static String decode(String encryptText) throws Exception { // DES演算法要求有一個可信任的隨機數源 SecureRandom sr = new SecureRandom(); // 從原始密匙資料建立一個DESKeySpec對象 DESKeySpec dks = new DESKeySpec(secretKey.getBytes()); // 建立一個密匙工廠,然後用它把DESKeySpec對象轉換成 // 一個SecretKey對象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey secretKey = keyFactory.generateSecret(dks); // using DES in ECB mode Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); // 用密匙初始化Cipher對象 cipher.init(Cipher.DECRYPT_MODE, secretKey, sr); // 正式執行解密操作 byte[] decryptData = cipher.doFinal(Base64.decode(encryptText)); return new String(decryptData, encoding); } public static String padding(String str) { byte[] oldByteArray; try { oldByteArray = str.getBytes("UTF8"); int numberToPad = 8 - oldByteArray.length % 8; byte[] newByteArray = new byte[oldByteArray.length + numberToPad]; System.arraycopy(oldByteArray, 0, newByteArray, 0, oldByteArray.length); for (int i = oldByteArray.length; i < newByteArray.length; ++i) { newByteArray[i] = 0; } return new String(newByteArray, "UTF8"); } catch (UnsupportedEncodingException e) { System.out.println("Crypter.padding UnsupportedEncodingException"); } return null; } /** * Base64編碼工具類 */ public static class Base64 { private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".toCharArray(); public static String encode(byte[] data) { int start = 0; int len = data.length; StringBuffer buf = new StringBuffer(data.length * 3 / 2); int end = len - 3; int i = start; int n = 0; while (i <= end) { int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 0x0ff) << 8) | (((int) data[i + 2]) & 0x0ff); buf.append(legalChars[(d >> 18) & 63]); buf.append(legalChars[(d >> 12) & 63]); buf.append(legalChars[(d >> 6) & 63]); buf.append(legalChars[d & 63]); i += 3; if (n++ >= 14) { n = 0; buf.append(" "); } } if (i == start + len - 2) { int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 255) << 8); buf.append(legalChars[(d >> 18) & 63]); buf.append(legalChars[(d >> 12) & 63]); buf.append(legalChars[(d >> 6) & 63]); buf.append("="); } else if (i == start + len - 1) { int d = (((int) data[i]) & 0x0ff) << 16; buf.append(legalChars[(d >> 18) & 63]); buf.append(legalChars[(d >> 12) & 63]); buf.append("=="); } return buf.toString(); } private static int decode(char c) { if (c >= 'A' && c <= 'Z') return ((int) c) - 65; else if (c >= 'a' && c <= 'z') return ((int) c) - 97 + 26; else if (c >= '0' && c <= '9') return ((int) c) - 48 + 26 + 26; else switch (c) { case '-': return 62; case '_': return 63; case '=': return 0; default: throw new RuntimeException("unexpected code: " + c); } } /** * Decodes the given Base64 encoded String to a new byte array. The byte array holding the decoded data is returned. */ public static byte[] decode(String s) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { decode(s, bos); } catch (IOException e) { throw new RuntimeException(); } byte[] decodedBytes = bos.toByteArray(); try { bos.close(); bos = null; } catch (IOException ex) { System.err.println("Error while decoding BASE64: " + ex.toString()); } return decodedBytes; } private static void decode(String s, OutputStream os) throws IOException { int i = 0; int len = s.length(); while (true) { while (i < len && s.charAt(i) <= ' ') i++; if (i == len) break; int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + (decode(s.charAt(i + 3))); os.write((tri >> 16) & 255); if (s.charAt(i + 2) == '=') break; os.write((tri >> 8) & 255); if (s.charAt(i + 3) == '=') break; os.write(tri & 255); i += 4; } } } public static void main(String[] args) throws Exception { String plainText = "[{\"user\":\"402892ee59b6e6930159b6e849740000\",\"mobile\":\"18205189527\"}]"; String encryptText = EncryptUtils.encode(plainText).replace(" ", ""); System.out.println(encryptText); System.out.println(EncryptUtils.decode(encryptText)); }}
運行結果:
PJfT-1k_8t9aiBlrLJWO1Iiy3P55yGMorPdxdb4JEv2fxQwzvuMxFyj4mfyX BbtSdWDpTQ2tTavYR3q5CSBIteC94ZFGC8Mn[{"user":"402892ee59b6e6930159b6e849740000","mobile":"18205189527"}]
desede類型加密解密只需要修改encode/decode方法即可:
public class EncryptUtils2 { // 密鑰 private final static String secretKey = "thismy3desdemotestsecretKey"; // 向量 private final static String iv = "01234567"; // 加解密統一使用的編碼方式 private final static String encoding = "utf-8"; /** * 3DES加密 * * @param plainText 普通文本 * @return * @throws Exception */ public static String encode(String plainText) throws Exception { Key deskey = null; DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes()); SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); deskey = keyfactory.generateSecret(spec); Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding"); IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, deskey, ips); byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding)); return Base64.encode(encryptData); } /** * 3DES解密 * * @param encryptText 加密文本 * @return * @throws Exception */ public static String decode(String encryptText) throws Exception { Key deskey = null; DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes()); SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); deskey = keyfactory.generateSecret(spec); Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding"); IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); cipher.init(Cipher.DECRYPT_MODE, deskey, ips); byte[] decryptData = cipher.doFinal(Base64.decode(encryptText)); return new String(decryptData, encoding); } }
參考:
3DES加密—java/OC
在JAVA中使用DES演算法
線上3DES加密解密、3DES線上加密解密