3DES加解密演算法
在日常設計及開發中,為確保資料傳輸和資料儲存的安全,可通過特定的演算法,將資料明文加密成複雜的密文。目前主流加密手段大致可分為單向加密和雙向加密。
單向加密:通過對資料進行摘要計算生成密文,密文不可逆推還原。演算法代表:Base64,MD5,SHA;
雙向加密:與單向加密相反,可以把密文逆推還原成明文,雙向加密又分為對稱加密和非對稱加密。
對稱加密:指資料使用者必須擁有相同的金鑰才可以進行加密解密,就像彼此約定的一串暗號。演算法代表:DES,3DES,AES,IDEA,RC4,RC5;
非對稱加密:相對對稱加密而言,無需擁有同一組金鑰,非對稱加密是一種“資訊公開的金鑰交換協議”。非對稱加密需要公開金鑰和私有金鑰兩組金鑰,公開金鑰和私有金鑰是配對起來的,也就是說使用公開金鑰進行資料加密,只有對應的私有金鑰才能解密。這兩個金鑰是數學相關,用某使用者金鑰加密後的密文,只能使用該使用者的加密金鑰才能解密。如果知道了其中一個,並不能計算出另外一個。因此如果公開了一對金鑰中的一個,並不會危害到另外一個金鑰性質。這裡把公開的金鑰為公鑰,不公開的金鑰為私鑰。演算法代表:RSA,DSA。
======================================================
3DES演算法
3DES是三重資料加密,且可以逆推的一種演算法方案。但由於3DES的演算法是公開的,所以演算法本身沒有金鑰可言,主要依靠唯一金鑰來確保資料加解密的安全。到目前為止,仍沒有人能破解3DES。
3DES(或稱為Triple DES)是三重資料加密演算法(TDEA,Triple Data Encryption Algorithm)塊密碼的通稱。它相當於是對每個資料塊應用三次DES加密演算法。由於計算機運算能力的增強,原版DES密碼的金鑰
3DES加解密工具類
1 package tqx.demo; 2 3 4 5 import java.net.URLDecoder; 6 import java.net.URLEncoder; 7 import java.security.Key; 8 9 import javax.crypto.Cipher; 10 import javax.crypto.SecretKeyFactory; 11import javax.crypto.spec.DESedeKeySpec; 12 import javax.crypto.spec.IvParameterSpec; 13 14 import com.alibaba.fastjson.JSONObject; 15 16 /** 17 * 3DES加密工具類 18 * 19 */ 20 public class INITDES3Util { 21 // 金鑰 22 private static String SECRETKEY = "INbSvyvOTkSkcRNSc8HpHIat"; 23 // 向量 24 private static String IV = "drS66rwt"; 25 // 加解密統一使用的編碼方式 26 private final static String encoding = "utf-8"; 27 28 public INITDES3Util(String s,String v ){ 29 this.SECRETKEY=s; 30 this.IV=v; 31 } 32 33 /** 34 * 3DES加密 35 * 36 * @param plainText 37 * 普通文字 38 * @return 39 */ 40 public String encrypt(String plainText) throws Exception { 41 Key deskey = null; 42 DESedeKeySpec spec = new DESedeKeySpec(SECRETKEY.getBytes()); 43 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 44 deskey = keyfactory.generateSecret(spec); 45 46 Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding"); 47 IvParameterSpec ips = new IvParameterSpec(IV.getBytes()); 48 cipher.init(Cipher.ENCRYPT_MODE, deskey, ips); 49 byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding)); 50 return Base64.encode(encryptData); 51 } 52 53 /** 54 * 3DES解密 55 * 56 * @param encryptText 57 * 加密文字 58 * @return 59 */ 60 public String decrypt(String encryptText) throws Exception { 61 Key deskey = null; 62 DESedeKeySpec spec = new DESedeKeySpec(SECRETKEY.getBytes()); 63 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 64 deskey = keyfactory.generateSecret(spec); 65 Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding"); 66 IvParameterSpec ips = new IvParameterSpec(IV.getBytes()); 67 cipher.init(Cipher.DECRYPT_MODE, deskey, ips); 68 69 byte[] decryptData = cipher.doFinal(Base64.decode(encryptText)); 70 71 return new String(decryptData, encoding); 72 } 73 74 /** 75 * 3DES加密 76 * 77 * @param secretKey 78 * 祕鑰 79 * @param iv 80 * 偏移向量 81 * @param plainText 82 * 普通文字 83 * @return 84 * @throws Exception 85 */ 86 public static String encryptString(String secretKey, String iv, 87 String plainText) throws Exception { 88 Key deskey = null; 89 DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes()); 90 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 91 deskey = keyfactory.generateSecret(spec); 92 93 Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding"); 94 IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); 95 cipher.init(Cipher.ENCRYPT_MODE, deskey, ips); 96 byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding)); 97 return Base64.encode(encryptData); 98 } 99 100 /** 101 * 3DES解密 102 * 103 * @param secretKey 104 * 祕鑰 105 * @param iv 106 * 偏移向量 107 * @param encryptText 108 * 密文 109 * @return 110 * @throws Exception 111 */ 112 public static String decryptString(String secretKey, String iv, 113 String encryptText) throws Exception { 114 Key deskey = null; 115 DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes()); 116 SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede"); 117 deskey = keyfactory.generateSecret(spec); 118 Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding"); 119 IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); 120 cipher.init(Cipher.DECRYPT_MODE, deskey, ips); 121 122 byte[] decryptData = cipher.doFinal(Base64.decode(encryptText)); 123 124 return new String(decryptData, encoding); 125 } 126 127 /** 128 * 3DES解碼後解密 129 * 130 * @param secretKey 131 * 祕鑰 132 * @param iv 133 * 偏移向量 134 * @param encryptText 135 * 密文 136 * @return 137 * @throws Exception 138 */ 139 public static String decryptStringURLDecoder(String secretKey, String iv, 140 String encryptText) throws Exception { 141 String retJsonStr = decryptString(secretKey, iv, 142 URLDecoder.decode(encryptText)); 143 return retJsonStr; 144 } 145 146 /** 147 * URLEncoder編碼加密資訊 148 * 149 * @param secretKey 150 * @param iv 151 * @param plainText 152 * @return 153 * @throws Exception 154 */ 155 public static String encryptStringURLEncoder(String secretKey, String iv, 156 String plainText) throws Exception { 157 String base64Str = encryptString(secretKey, iv, plainText); 158 return URLEncoder.encode(base64Str); 159 } 160 161 162 public static void main(String[] args) throws Exception { 163 String result=""; 164 INITDES3Util desSource=new INITDES3Util("INbSvyvOTkSkcRNSc8HpHIat","drS66rwt"); 165 //JSONObject outData = new JSONObject(); 166 //JSONObject resultOutData = new JSONObject(); 167 String outputStr="123456"; 168 String para=desSource.encrypt(outputStr);//加密json串 169 System.out.println(para); 170 String decryptString = INITDES3Util.encryptString("INbSvyvOTkSkcRNSc8HpHIat","drS66rwt", "sysadmin"); 171 System.out.println(decryptString); 172 173 } 174 175 }
URLDecoder類包含一個decode(String s,String charcter)靜態方法,它可以將看上去亂碼的特殊字串轉換成普通字串
URLEncoder類包含一個encode(String s,String charcter)靜態方法,它可以將普通字串轉換成application/x-www-form-urlencoded MIME字串
base64
1 package tqx.demo; 2 3 4 import java.io.ByteArrayOutputStream; 5 import java.io.IOException; 6 import java.io.OutputStream; 7 8 /** 9 * Base64編碼工具類 10 * 11 */ 12 public class Base64 { 13 private static final char[] legalChars = 14 15 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 16 .toCharArray(); 17 18 public static String encode(byte[] data) { 19 int start = 0; 20 int len = data.length; 21 StringBuffer buf = new StringBuffer(data.length * 3 / 22 23 2); 24 25 int end = len - 3; 26 int i = start; 27 int n = 0; 28 29 while (i <= end) { 30 int d = ((((int) data[i]) & 0x0ff) << 16) 31 | ((((int) data[i + 1]) & 0x0ff) 32 33 << 8) 34 | (((int) data[i + 2]) & 0x0ff); 35 36 buf.append(legalChars[(d >> 18) & 63]); 37 buf.append(legalChars[(d >> 12) & 63]); 38 buf.append(legalChars[(d >> 6) & 63]); 39 buf.append(legalChars[d & 63]); 40 41 i += 3; 42 43 if (n++ >= 14) { 44 n = 0; 45 buf.append(" "); 46 } 47 } 48 49 if (i == start + len - 2) { 50 int d = ((((int) data[i]) & 0x0ff) << 16) 51 | ((((int) data[i + 1]) & 255) 52 53 << 8); 54 55 buf.append(legalChars[(d >> 18) & 63]); 56 buf.append(legalChars[(d >> 12) & 63]); 57 buf.append(legalChars[(d >> 6) & 63]); 58 buf.append("="); 59 } else if (i == start + len - 1) { 60 int d = (((int) data[i]) & 0x0ff) << 16; 61 62 buf.append(legalChars[(d >> 18) & 63]); 63 buf.append(legalChars[(d >> 12) & 63]); 64 buf.append("=="); 65 } 66 67 return buf.toString(); 68 } 69 70 private static int decode(char c) { 71 if (c >= 'A' && c <= 'Z') 72 return ((int) c) - 65; 73 else if (c >= 'a' && c <= 'z') 74 return ((int) c) - 97 + 26; 75 else if (c >= '0' && c <= '9') 76 return ((int) c) - 48 + 26 + 26; 77 else 78 switch (c) { 79 case '+': 80 return 62; 81 case '/': 82 return 63; 83 case '=': 84 return 0; 85 default: 86 throw new RuntimeException("unexpectedcode: " + c); 87 } 88 } 89 90 /** 91 * Decodes the given Base64 encoded String to a new byte array. 92 93 The byte 94 * array holding the decoded data is returned. 95 */ 96 97 public static byte[] decode(String s) { 98 99 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 100 try { 101 decode(s, bos); 102 } catch (IOException e) { 103 throw new RuntimeException(); 104 } 105 byte[] decodedBytes = bos.toByteArray(); 106 try { 107 bos.close(); 108 bos = null; 109 } catch (IOException ex) { 110 System.err.println("Error while decoding BASE64:" + ex.toString()); 111 } 112 return decodedBytes; 113 } 114 115 private static void decode(String s, OutputStream os) throws 116 117 IOException { 118 int i = 0; 119 120 int len = s.length(); 121 122 while (true) { 123 while (i < len && s.charAt(i) <= ' ') 124 i++; 125 126 if (i == len) 127 break; 128 129 int tri = (decode(s.charAt(i)) << 18) 130 + (decode(s.charAt(i + 1)) << 131 132 12) 133 + (decode(s.charAt(i + 2)) << 6) 134 + (decode(s.charAt(i + 3))); 135 136 os.write((tri >> 16) & 255); 137 if (s.charAt(i + 2) == '=') 138 break; 139 os.write((tri >> 8) & 255); 140 if (s.charAt(i + 3) == '=') 141 break; 142 os.write(tri & 255); 143 144 i += 4; 145 } 146 } 147 }
測試
package tqx.demo; public class Demo3 { public static void main(String[] args) throws Exception { String encryptStringURLEncoder = INITDES3Util.encryptStringURLEncoder("INbSvyvOTkSkcRNSc8HpHIat", "drS66rwt", "123456"); System.out.println("電話加密後:"+encryptStringURLEncoder); String decryptStringURLDecoder = INITDES3Util.decryptStringURLDecoder("INbSvyvOTkSkcRNSc8HpHIat", "drS66rwt", encryptStringURLEncoder); System.out.println("電話解密後:"+decryptStringURLDecoder); String encryptStringURLEncoder1 = INITDES3Util.encryptStringURLEncoder("INbSvyvOTkSkcRNSc8HpHIat", "drS66rwt", "tqx"); System.out.println("24加密後:"+encryptStringURLEncoder1); String decryptStringURLDecoder1 = INITDES3Util.decryptStringURLDecoder("INbSvyvOTkSkcRNSc8HpHIat", "drS66rwt", encryptStringURLEncoder1); System.out.println("24解密後:"+decryptStringURLDecoder1); String encryptStringURLEncoder2 = INITDES3Util.encryptStringURLEncoder("INbSvyvOTkSkcRNSc8HpHIat", "drS66rwt", "512501197203035172"); System.out.println("身份證號加密後:"+encryptStringURLEncoder2); String decryptStringURLDecoder2 = INITDES3Util.decryptStringURLDecoder("INbSvyvOTkSkcRNSc8HpHIat", "drS66rwt", encryptStringURLEncoder2); System.out.println("身份證號解密後:"+decryptStringURLDecoder2); byte[] decode = Base64.decode("12345600"); System.out.println(decode.toString()); } }
針對特殊字元的處理 '+'
str.toString()).replaceAll("\\+", "%2B");
// 金鑰24位
private static String SECRETKEY = "INbSvyvOTkSkcRNSc8HpHIat";
// 向量6位
private static String IV = "drS66rwt";
生成方法
package tqx.demo; import java.util.Random; public class RandomUtil { public static final String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static final String LETTERCHAR = "abcdefghijkllmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static final String NUMBERCHAR = "0123456789"; /** * 返回一個定長的帶因子的固定的隨機字串(只包含大小寫字母、數字) * * @param length * 隨機字串長度 * @return 隨機字串 */ public static String generateStringByKey(int length, int channel) { StringBuffer sb = new StringBuffer(); Random random = new Random(channel); for (int i = 0; i < length; i++) { sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length()))); } return sb.toString(); } /** * 返回一個定長的隨機字串(只包含大小寫字母、數字) * * @param length * 隨機字串長度 * @return 隨機字串 */ public static String generateString(int length) { StringBuffer sb = new StringBuffer(); Random random = new Random(); for (int i = 0; i < length; i++) { sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length()))); } return sb.toString(); } /** * 返回一個定長的隨機純字母字串(只包含大小寫字母) * * @param length * 隨機字串長度 * @return 隨機字串 */ public static String generateMixString(int length) { StringBuffer sb = new StringBuffer(); Random random = new Random(); for (int i = 0; i < length; i++) { sb.append(ALLCHAR.charAt(random.nextInt(LETTERCHAR.length()))); } return sb.toString(); } /** * 返回一個定長的隨機純大寫字母字串(只包含大小寫字母) * * @param length * 隨機字串長度 * @return 隨機字串 */ public static String generateLowerString(int length) { return generateMixString(length).toLowerCase(); } /** * 返回一個定長的隨機純小寫字母字串(只包含大小寫字母) * * @param length * 隨機字串長度 * @return 隨機字串 */ public static String generateUpperString(int length) { return generateMixString(length).toUpperCase(); } /** * 生成一個定長的純0字串 * * @param length * 字串長度 * @return 純0字串 */ public static String generateZeroString(int length) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { sb.append('0'); } return sb.toString(); } /** * 根據數字生成一個定長的字串,長度不夠前面補0 * * @param num * 數字 * @param fixdlenth * 字串長度 * @return 定長的字串 */ public static String toFixdLengthString(long num, int fixdlenth) { StringBuffer sb = new StringBuffer(); String strNum = String.valueOf(num); if (fixdlenth - strNum.length() >= 0) { sb.append(generateZeroString(fixdlenth - strNum.length())); } else { throw new RuntimeException("將數字" + num + "轉化為長度為" + fixdlenth + "的字串發生異常!"); } sb.append(strNum); return sb.toString(); } /** * 每次生成的len位數都不相同 * * @param param * @return 定長的數字 */ public static int getNotSimple(int[] param, int len) { Random rand = new Random(); for (int i = param.length; i > 1; i--) { int index = rand.nextInt(i); int tmp = param[index]; param[index] = param[i - 1]; param[i - 1] = tmp; } int result = 0; for (int i = 0; i < len; i++) { result = result * 10 + param[i]; } return result; } public static void main(String[] args) { int channel = 555555;// 測試因子比生產因子少1 System.out.println("返回一個定長的帶因子的固定的隨機字串(只包含大小寫字母、數字):" + generateStringByKey(24, channel)); System.out.println("返回一個定長的隨機字串(只包含大小寫字母、數字):" + generateString(24)); System.out.println("返回一個定長的隨機純字母字串(只包含大小寫字母):" + generateMixString(6)); System.out.println("返回一個定長的隨機純大寫字母字串(只包含大小寫字母):" + generateLowerString(6)); System.out.println("返回一個定長的隨機純小寫字母字串(只包含大小寫字母):" + generateUpperString(6)); System.out.println("生成一個定長的純0字串:" + generateZeroString(6)); System.out.println("根據數字生成一個定長的字串,長度不夠前面補0:" + toFixdLengthString(123, 6)); int[] in = { 1, 2, 3, 4, 5, 6, 7 }; System.out.println("每次生成的len位數都不相同:" + getNotSimple(in, 3)); } }
返回一個定長的帶因子的固定的隨機字串(只包含大小寫字母、數字):MaigTil28hVETWTssFHGtYDx 返回一個定長的隨機字串(只包含大小寫字母、數字):6sBcIpRocWTyBLiKvyNAQ0Sd 返回一個定長的隨機純字母字串(只包含大小寫字母):LLQMLv 返回一個定長的隨機純大寫字母字串(只包含大小寫字母):mp6d7s 返回一個定長的隨機純小寫字母字串(只包含大小寫字母):MWYWIF 生成一個定長的純0字串:000000 根據數字生成一個定長的字串,長度不夠前面補0:000123 每次生成的len位數都不相同:651