在日常设计及开发中,为确保数据传输和数据存储的安全,可通过特定的算法,将数据明文加密成复杂的密文。目前主流加密手段大致可分为单向加密和双向加密。
单向加密:通过对数据进行摘要计算生成密文,密文不可逆推还原。算法代表: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