加密与编码
Java加密的常用的加密算法类型有三种
1单向加密:也就是不可逆的加密,例如MD5,SHA,HMAC
2对称加密:也就是加密方和解密方利用同一个秘钥对数据进行加密和解密,例如DES,PBE等等
3非对称加密:非对称加密分为公钥和秘钥,二者是非对称的,例如用私钥加密的内容需要使用公钥来解密,使用公钥加密的内容需要用私钥来解密,DSA,RSA...
而keyGenerator,KeyPairGenerator,SecretKeyFactory的三种使用方法刚好和这三种加密算法类型对上
keyGenerator:秘钥生成器,也就是更具算法类型随机生成一个秘钥,例如HMAC,所以这个大部分用在非可逆的算法中
SecretKeyFactory:秘密秘钥工厂,言外之意就是需要根据一个秘密(password)去生成一个秘钥,例如DES,PBE,所以大部分使用在对称加密中
KeyPairGenerator:秘钥对生成器,也就是可以生成一对秘钥,也就是公钥和私钥,所以大部分使用在非对称加密中
SecretKeyFactory类
SecretKeyFactory表示秘密密钥的工厂。类声明:public class SecretKeyFactory extends Object
例子:
try { // 获取密钥工厂类对象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); byte[] DESkey = "abcdefghijk".getBytes("UTF-8");// 设置密钥 DESKeySpec keySpec = new DESKeySpec(DESkey);// 设置密钥参数 Key key = keyFactory.generateSecret(keySpec);// 得到密钥对象 } catch (Exception e) { e.printStackTrace(); }
详见:https://blog.csdn.net/u010142437/article/details/17767809
对称加密算法-DES以及DESede算法
对称加密算法就是能将数据加解密。加密的时候用密钥对数据进行加密,解密的时候使用同样的密钥对数据进行解密。
1、des算法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.ca.test; 2 import java.security.Key; 3 import javax.crypto.Cipher; 4 import javax.crypto.KeyGenerator; 5 import javax.crypto.SecretKey; 6 import javax.crypto.SecretKeyFactory; 7 import javax.crypto.spec.DESKeySpec; 8 import org.apache.commons.codec.binary.Base64; 9 /** 10 * DES对称加密算法 11 * @author kongqz 12 * */ 13 public class DESCoder { 14 /** 15 * 密钥算法 16 * java支持56位密钥,bouncycastle支持64位 17 * */ 18 public static final String KEY_ALGORITHM="DES"; 19 20 /** 21 * 加密/解密算法/工作模式/填充方式 22 * */ 23 public static final String CIPHER_ALGORITHM="DES/ECB/PKCS5Padding"; 24 25 /** 26 * 27 * 生成密钥,java6只支持56位密钥,bouncycastle支持64位密钥 28 * @return byte[] 二进制密钥 29 * */ 30 public static byte[] initkey() throws Exception{ 31 32 //实例化密钥生成器 33 KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM); 34 //初始化密钥生成器 35 kg.init(56); 36 //生成密钥 37 SecretKey secretKey=kg.generateKey(); 38 //获取二进制密钥编码形式 39 return secretKey.getEncoded(); 40 } 41 /** 42 * 转换密钥 43 * @param key 二进制密钥 44 * @return Key 密钥 45 * */ 46 public static Key toKey(byte[] key) throws Exception{ 47 //实例化Des密钥 48 DESKeySpec dks=new DESKeySpec(key); 49 //实例化密钥工厂 50 SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(KEY_ALGORITHM); 51 //生成密钥 52 SecretKey secretKey=keyFactory.generateSecret(dks); 53 return secretKey; 54 } 55 56 /** 57 * 加密数据 58 * @param data 待加密数据 59 * @param key 密钥 60 * @return byte[] 加密后的数据 61 * */ 62 public static byte[] encrypt(byte[] data,byte[] key) throws Exception{ 63 //还原密钥 64 Key k=toKey(key); 65 //实例化 66 Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); 67 //初始化,设置为加密模式 68 cipher.init(Cipher.ENCRYPT_MODE, k); 69 //执行操作 70 return cipher.doFinal(data); 71 } 72 /** 73 * 解密数据 74 * @param data 待解密数据 75 * @param key 密钥 76 * @return byte[] 解密后的数据 77 * */ 78 public static byte[] decrypt(byte[] data,byte[] key) throws Exception{ 79 //欢迎密钥 80 Key k =toKey(key); 81 //实例化 82 Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); 83 //初始化,设置为解密模式 84 cipher.init(Cipher.DECRYPT_MODE, k); 85 //执行操作 86 return cipher.doFinal(data); 87 } 88 /** 89 * @param args 90 * @throws Exception 91 */ 92 public static void main(String[] args) throws Exception { 93 String str="DES"; 94 System.out.println("原文:"+str); 95 //初始化密钥 96 byte[] key=DESCoder.initkey(); 97 System.out.println("密钥:"+Base64.encodeBase64String(key)); 98 //加密数据 99 byte[] data=DESCoder.encrypt(str.getBytes(), key); 100 System.out.println("加密后:"+Base64.encodeBase64String(data)); 101 //解密数据 102 data=DESCoder.decrypt(data, key); 103 System.out.println("解密后:"+new String(data)); 104 } 105 } 106 控制台输出结果: 107 原文:DES 108 密钥:ocewbYVbtmE= 109 加密后:w6KsVSkLV3Q= 110 解密后:DES
2、desede算法演示
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.ca.test; 2 import java.security.Key; 3 import javax.crypto.Cipher; 4 import javax.crypto.KeyGenerator; 5 import javax.crypto.SecretKey; 6 import javax.crypto.SecretKeyFactory; 7 import javax.crypto.spec.DESedeKeySpec; 8 import org.apache.commons.codec.binary.Base64; 9 /** 10 * DESede对称加密算法演示 11 * @author kongqz 12 * */ 13 public class DESedeCoder { 14 /** 15 * 密钥算法 16 * */ 17 public static final String KEY_ALGORITHM="DESede"; 18 19 /** 20 * 加密/解密算法/工作模式/填充方式 21 * */ 22 public static final String CIPHER_ALGORITHM="DESede/ECB/PKCS5Padding"; 23 24 /** 25 * 26 * 生成密钥 27 * @return byte[] 二进制密钥 28 * */ 29 public static byte[] initkey() throws Exception{ 30 31 //实例化密钥生成器 32 KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM); 33 //初始化密钥生成器 34 kg.init(168); 35 //生成密钥 36 SecretKey secretKey=kg.generateKey(); 37 //获取二进制密钥编码形式 38 return secretKey.getEncoded(); 39 } 40 /** 41 * 转换密钥 42 * @param key 二进制密钥 43 * @return Key 密钥 44 * */ 45 public static Key toKey(byte[] key) throws Exception{ 46 //实例化Des密钥 47 DESedeKeySpec dks=new DESedeKeySpec(key); 48 //实例化密钥工厂 49 SecretKeyFactory keyFactory=SecretKeyFactory.getInstance(KEY_ALGORITHM); 50 //生成密钥 51 SecretKey secretKey=keyFactory.generateSecret(dks); 52 return secretKey; 53 } 54 55 /** 56 * 加密数据 57 * @param data 待加密数据 58 * @param key 密钥 59 * @return byte[] 加密后的数据 60 * */ 61 public static byte[] encrypt(byte[] data,byte[] key) throws Exception{ 62 //还原密钥 63 Key k=toKey(key); 64 //实例化 65 Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); 66 //初始化,设置为加密模式 67 cipher.init(Cipher.ENCRYPT_MODE, k); 68 //执行操作 69 return cipher.doFinal(data); 70 } 71 /** 72 * 解密数据 73 * @param data 待解密数据 74 * @param key 密钥 75 * @return byte[] 解密后的数据 76 * */ 77 public static byte[] decrypt(byte[] data,byte[] key) throws Exception{ 78 //欢迎密钥 79 Key k =toKey(key); 80 //实例化 81 Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); 82 //初始化,设置为解密模式 83 cipher.init(Cipher.DECRYPT_MODE, k); 84 //执行操作 85 return cipher.doFinal(data); 86 } 87 /** 88 * 进行加解密的测试 89 * @throws Exception 90 */ 91 public static void main(String[] args) throws Exception { 92 String str="DESede"; 93 System.out.println("原文:/t"+str); 94 //初始化密钥 95 byte[] key=DESedeCoder.initkey(); 96 System.out.println("密钥:/t"+Base64.encodeBase64String(key)); 97 //加密数据 98 byte[] data=DESedeCoder.encrypt(str.getBytes(), key); 99 System.out.println("加密后:/t"+Base64.encodeBase64String(data)); 100 //解密数据 101 data=DESedeCoder.decrypt(data, key); 102 System.out.println("解密后:/t"+new String(data)); 103 } 104 } 105 控制台输出结果: 106 原文: DESede 107 密钥: BBDmwTjBsF7IwTIyGWt1bmFntRyUgMQL 108 加密后: FM/DsEv3KgM= 109 解密后: DESede
base64
Base64是一种用64个字符来表示任意二进制数据的方法。
原理:
Base64的原理很简单,首先,准备一个包含64个字符的数组:
['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']
然后,对二进制数据进行处理,每3个字节一组,一共是3x8=24
bit,划为4组,每组正好6个bit:
这样我们得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串。
所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,好处是编码后的文本数据可以在邮件正文、网页等直接显示。
如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?Base64用\x00
字节在末尾补足后,再在编码的末尾加上1个或2个=
号,表示补了多少字节,解码的时候,会自动去掉。
使用:Base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。
java中使用:
1 import java.util.Base64; 2 对于标准的Base64: 3 加密为字符串使用Base64.getEncoder().encodeToString(); 4 加密为字节数组使用Base64.getEncoder().encode(); 5 解密使用Base64.getDecoder().decode(); 6 对于URL安全或MIME的Base64,只需将上述getEncoder()getDecoder()更换为getUrlEncoder()getUrlDecoder() 7 或getMimeEncoder()和getMimeDecoder()即可。
URLEncoder
客户端在进行网页请求的时候,网址中可能会包含非ASCII码形式的内容,比如中文。
而直接把中文放到网址中请求是不允许的,所以需要用URLEncoder编码地址,
将网址中的非ASCII码内容转换成可以传输的字符
不会被编码的内容
1.大写字母A-Z
2.小写字母a-z
3.数字 0-9
4.标点符 - _ . ! ~ * ' (和 ,)
编码原理
1、将需要转换的内容(ASCII码形式之外的内容),用十六进制表示法转换出来,并在之前加上%开头
eg: 0x9c URLEncoder --> %9c
2、内容中的空格‘ ’ ,全部用+代替
3、注:与Hex不同,Hex是将所有的字符转换为16进制表示,而URLEncoder是将ASCII码集之外的转换为%加上相应的16进制,而ASCII码集内的字符不进行处理
应用场景
1、所有的GET请求
2、网址中有中文等情况
3、POST请求,所有的Key和Value在提交之前都要经过URLEncoder
示例代码:
try { String a = URLEncoder.encode("a", "UTF-8"); Log.i("encode","a 进行URLEncoder编码后-->"+a ); String b = URLEncoder.encode("a中", "UTF-8"); Log.i("encode","a中 进行URLEncoder编码后-->"+b ); String decode = nURLDecoder.decode("a%E4%B8%AD", "UTF-8"); Log.i("encode","a%E4%B8%AD 进行URLDecoder解码后-->"+decode); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }
运行结果:
10-17 07:33:14.357 1012-1012/com.xqx.encrypsthow I/encode﹕ a 进行URLEncoder编码后-->a 10-17 07:33:14.367 1012-1012/com.xqx.encrypsthow I/encode﹕ a中 进行URLEncoder编码后-->a%E4%B8%AD 10-17 07:33:14.377 1012-1012/com.xqx.encrypsthow I/encode﹕ a%E4%B8%AD 进行URLDecoder解码后-->a中
可以看出 字符'a' 并没有编码 而 中文 '中' 进行了编码
与URLEncoder编码对应的是URLDecoder解码
可以看出 "a中"--编码-->"a%E4%B8%AD"--解码-->"a中"