1. 程式人生 > >3DES加解密演算法

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即是設計用來提供一種相對簡單的方法,即通過增加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;
 11
import 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