10.1、DES

  • 已破解,不再安全,基本没有企业在用了
  • 是对称加密算法的基石,具有学习价值
  • 密钥长度56(JDK)、56/64(BC)

10.2、DESede(三重DES)

  • 早于AES出现来替代DES
  • 计算密钥时间太长、加密效率不高,所以也基本上不用
  • 密钥长度112/168(JDK)、128/192(BC)

10.3、AES

  • 最常用的对称加密算法
  • 密钥建立时间短、灵敏性好、内存需求低(不管怎样,反正就是好)
  • 实际使用中,使用工作模式为CTR(最好用BC去实现),此工作模式需要引入IV参数(16位的字节数组)
  • 密钥长度128/192/256,其中192与256需要配置无政策限制权限文件(JDK6)
  • 填充模式最常用的两种PKCS5Padding和PKCS7Padding,其中后者只有BC独有。

10.4、IDEA

  • 常用的电子邮件加密算法
  • 工作模式只有ECB
  • 密钥长度128位

10.5、PBE

  • 综合了消息摘要算法和对称加密算法,最常见的是PBEWithMD5AndDES
  • 工作模式只有CBC(已丧失安全性,不推荐使用),所以PBE也不推荐使用了

7.1、对称加密算法

特点:

  • 加密与解密使用同一个密钥
  • 是使用最广的算法

常见对称加密算法:

  • DES(已被破解,但是是其他对称算法的基石)
  • DESede(处理速度慢、加密耗时,也不常用)
  • AES(DES的替代者,最常用)
  • IDEA(目前常用的电子邮件加密算法)
  • PBE(对已知对称加密进行包装)

7.2、DES(已破解,基本不用)

实现方式:

  • JDK(提供56位密钥,提供PKCS5Padding的填充模式)
  • Bouncy Castle(提供64位密钥,提供PKCS7Padding的填充模式)

由于DES已被破解,现在企业基本已不再使用,此处只列出基于JDK实现的代码。

1 package com.util.des;
2
3 import java.io.UnsupportedEncodingException;
4 import java.security.InvalidKeyException;
5 import java.security.Key;
6 import java.security.NoSuchAlgorithmException;
7 import java.security.spec.InvalidKeySpecException;
8
9 import javax.crypto.BadPaddingException;
10 import javax.crypto.Cipher;
11 import javax.crypto.IllegalBlockSizeException;
12 import javax.crypto.KeyGenerator;
13 import javax.crypto.NoSuchPaddingException;
14 import javax.crypto.SecretKey;
15 import javax.crypto.SecretKeyFactory;
16 import javax.crypto.spec.DESKeySpec;
17
18 import org.apache.commons.codec.binary.Base64;
19
20 /**
21 * 基于JDK的DES算法
22 */
23 public class DESJDK {
24 private static final String ENCODING = "UTF-8";
25 private static final String KEY_ALGORITHM = "DES";//产生密钥的算法
26 private static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";//加解密算法 格式:算法/工作模式/填充模式
27
28 /**
29 * 产生密钥
30 */
31 public static byte[] getKey() throws NoSuchAlgorithmException{
32 KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
33 keyGenerator.init(56);//初始化密钥长度
34 SecretKey key =keyGenerator.generateKey();//产生密钥
35 return key.getEncoded();
36 }
37
38 /**
39 * 还原密钥:二进制字节数组转换为十六进制字符串
40 */
41 public static Key toKey(byte[] keyByte) throws InvalidKeyException,
42 NoSuchAlgorithmException,
43 InvalidKeySpecException{
44 DESKeySpec desKeySpec = new DESKeySpec(keyByte);
45 return SecretKeyFactory.getInstance(KEY_ALGORITHM).generateSecret(desKeySpec);
46 }
47
48 /**
49 * DES加密
50 * @param data 带加密数据
51 * @param keyByte 密钥
52 */
53 public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException,
54 NoSuchAlgorithmException,
55 InvalidKeySpecException,
56 NoSuchPaddingException,
57 IllegalBlockSizeException,
58 BadPaddingException,
59 UnsupportedEncodingException{
60 Key key = toKey(keyByte);//还原密钥
61 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
62 cipher.init(Cipher.ENCRYPT_MODE, key);//设置加密模式并且初始化key
63 return cipher.doFinal(data.getBytes(ENCODING));
64 }
65
66 /**
67 * DES加密,并转为16进制字符串或Base64编码字符串
68 */
69 public static String encryptDESHex(String data, byte[] keyByte) throws InvalidKeyException,
70 NoSuchAlgorithmException,
71 InvalidKeySpecException,
72 NoSuchPaddingException,
73 IllegalBlockSizeException,
74 BadPaddingException,
75 UnsupportedEncodingException {
76 byte[] encodedByte = encrypt(data, keyByte);
77 //return new String(Hex.encode(encodedByte));//借助BC
78 //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
79 return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
80 }
81
82 /**
83 * DES解密
84 * @param data 待解密数据为字节数组
85 * @param keyByte 密钥
86 */
87 public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException,
88 NoSuchAlgorithmException,
89 InvalidKeySpecException,
90 NoSuchPaddingException,
91 IllegalBlockSizeException,
92 BadPaddingException,
93 UnsupportedEncodingException {
94 Key key = toKey(keyByte);//还原密钥
95 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
96 cipher.init(Cipher.DECRYPT_MODE, key);//设置解密模式(这是加解密的唯一不同的地方)并且初始化key
97 return cipher.doFinal(data);
98 }
99
100 /**
101 * DES解密
102 * @param data 待解密数据为字符串
103 * @param keyByte 密钥
104 */
105 public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException,
106 NoSuchAlgorithmException,
107 InvalidKeySpecException,
108 NoSuchPaddingException,
109 IllegalBlockSizeException,
110 BadPaddingException,
111 UnsupportedEncodingException {
112 Key key = toKey(keyByte);//还原密钥
113 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
114 cipher.init(Cipher.DECRYPT_MODE, key);//设置解密模式(这是加解密的唯一不同的地方)并且初始化key
115 return cipher.doFinal(Base64.decodeBase64(data));//注意data不可以直接采用data.getByte()方法转化为字节数组,否则会抛异常
116 }
117
118 /**
119 * 测试
120 */
121 public static void main(String[] args) throws NoSuchAlgorithmException,
122 InvalidKeyException,
123 InvalidKeySpecException,
124 NoSuchPaddingException,
125 IllegalBlockSizeException,
126 BadPaddingException,
127 UnsupportedEncodingException {
128 String data = "找一个好姑娘做老婆是我的梦 想!";
129 /*************测试encode()**************/
130 System.out.println("原文-->"+data);
131 byte[] keyByte = DESJDK.getKey();
132 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
133 byte[] encodedByte = DESJDK.encrypt(data, keyByte);
134 System.out.println("加密后-->"+encodedByte);
135 byte[] encodedByte2 = DESJDK.encrypt(data, keyByte);
136 System.out.println("加密后-->"+encodedByte2);
137 byte[] decodedByte = DESJDK.decrypt(encodedByte, keyByte);
138 System.out.println("解密后-->"+decodedByte);
139 for(int i=0;i<encodedByte.length;i++){
140 System.out.println(encodedByte[i]==encodedByte2[i]);
141 }
142 /*************测试encodeHmacMD5Hex()**************/
143 System.out.println("原文-->"+data);
144 byte[] keyByte3 = DESJDK.getKey();
145 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
146 String encodedStr = DESJDK.encryptDESHex(data, keyByte3);
147 System.out.println("加密后-->"+encodedStr);
148 String encodedByte4 = DESJDK.encryptDESHex(data, keyByte3);
149 System.out.println("加密后-->"+encodedByte4);
150 byte[] decodedByte3 = DESJDK.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
151 System.out.println("解密Byte[]后-->"+decodedByte3);
152 byte[] decodedByte4 = DESJDK.decrypt(encodedStr, keyByte3);
153 System.out.println("解密String后-->"+decodedByte4);
154 }
155 }

注意点:

  • 整个算法的过程与Hmac系列算法一样,都是发送方先生成一个密钥(二进制的字节数组),然后发送方将密钥通过安全的途径传给接收方。加解密过程:还原密钥(将二进制的字节数组还原成Java对象),然后根据密钥与待加解密数据进行加解密。
  • 加解密算法常量CIPHER_ALGORITHM是一个组合常量,其中的工作模式常用的是ECB和CTR(AES最常用的工作模式)填充模式一般采用PKCS5Padding即可,或者使用BC的PKCS7Padding,具体的工作模式与填充模式的介绍自己去查吧,至于JDK和BC均支持那些工作模式与填充模式直接去查本文最上边的书籍附录即可。
  • 初始化密钥长度的时候指定为56(JDK提供56位的密钥,采用BC可以产生64位的密钥)
  • 还原密钥的时候没有使用通用的方式SecretKey key = new SecretKeySpec(keyByte, ALGORITHM)来还原(当然也可以使用),而是使用了DES自己的还原类,这是DES的推荐做法,但是在AES中推荐使用通用的方式来还原密钥
  • 实际使用中,加密的密文会采用二进制来存储,密钥会采用Base64编码来存储;但是在演示的时候我会提供转化为字符串的密文(转化方法:BC的十六进制转化类 ;CC的十六进制转化类;CC的Base64编码)
  • 在解密过程中,如果传入的待解密数据data是String的,在使用dofinal()方法进行加密时,不可以直接使用doFinal(data.getByte()),否则会抛异常;可以使用doFinal(Base64.decodeBase64(data))
  • 同一段数据使用统一个密钥无论加密多少次,加密后的密文都相同

8.1、AES

特点:

  • 密钥建立时间短、灵敏性好、内存需求低(不管怎样,反正就是好)
  • 最常用的对称加密算法

8.2、实现方式

  • JDK(密钥长度有128,192,256三种选法,提供PKCS5Padding的填充模式)
  • Bouncy Castle(密钥长度有128,192,256三种选法,提供PKCS7Padding的填充模式)

8.2.1、基于JDK或BC的AES实现(工作模式为ECB)

1 package com.util.aes;
2
3 import java.io.UnsupportedEncodingException;
4 import java.security.InvalidAlgorithmParameterException;
5 import java.security.InvalidKeyException;
6 import java.security.Key;
7 import java.security.NoSuchAlgorithmException;
8 import java.security.NoSuchProviderException;
9 import java.security.Security;
10 import java.security.spec.InvalidKeySpecException;
11
12 import javax.crypto.BadPaddingException;
13 import javax.crypto.Cipher;
14 import javax.crypto.IllegalBlockSizeException;
15 import javax.crypto.KeyGenerator;
16 import javax.crypto.NoSuchPaddingException;
17 import javax.crypto.SecretKey;
18 import javax.crypto.spec.SecretKeySpec;
19
20 import org.apache.commons.codec.binary.Base64;
21 import org.bouncycastle.jce.provider.BouncyCastleProvider;
22
23 /**
24 * 基于JDK或BC的AES算法,工作模式采用ECB
25 */
26 public class AESJDK {
27 private static final String ENCODING = "UTF-8";
28 private static final String KEY_ALGORITHM = "AES";//产生密钥的算法
29 private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//加解密算法 格式:算法/工作模式/填充模式 注意:ECB不使用IV参数
30 /**
31 * 产生密钥
32 */
33 public static byte[] getKey() throws NoSuchAlgorithmException{
34 Security.addProvider(new BouncyCastleProvider());//在BC中用,JDK下去除
35 KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
36 keyGenerator.init(256);//初始化密钥长度,128,192,256(选用192和256的时候需要配置无政策限制权限文件--JDK6)
37 SecretKey key =keyGenerator.generateKey();//产生密钥
38 return key.getEncoded();
39 }
40
41 /**
42 * 还原密钥:二进制字节数组转换为Java对象
43 */
44 public static Key toKey(byte[] keyByte){
45 return new SecretKeySpec(keyByte, KEY_ALGORITHM);
46 }
47
48 /**
49 * AES加密
50 * @param data 带加密数据
51 * @param keyByte 密钥
52 */
53 public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException,
54 NoSuchAlgorithmException,
55 InvalidKeySpecException,
56 NoSuchPaddingException,
57 IllegalBlockSizeException,
58 BadPaddingException,
59 UnsupportedEncodingException,
60 NoSuchProviderException,
61 InvalidAlgorithmParameterException{
62 Key key = toKey(keyByte);//还原密钥
63 //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
64 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
65 cipher.init(Cipher.ENCRYPT_MODE, key);//设置加密模式并且初始化key
66 return cipher.doFinal(data.getBytes(ENCODING));
67 }
68
69 /**
70 * AES加密,并转为16进制字符串或Base64编码字符串
71 */
72 public static String encryptAESHex(String data, byte[] keyByte) throws InvalidKeyException,
73 NoSuchAlgorithmException,
74 InvalidKeySpecException,
75 NoSuchPaddingException,
76 IllegalBlockSizeException,
77 BadPaddingException,
78 UnsupportedEncodingException,
79 NoSuchProviderException,
80 InvalidAlgorithmParameterException {
81 byte[] encodedByte = encrypt(data, keyByte);
82 //return new String(Hex.encode(encodedByte));//借助BC
83 //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
84 return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
85 }
86
87 /**
88 * AES解密
89 * @param data 待解密数据为字节数组
90 * @param keyByte 密钥
91 */
92 public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException,
93 NoSuchAlgorithmException,
94 InvalidKeySpecException,
95 NoSuchPaddingException,
96 IllegalBlockSizeException,
97 BadPaddingException,
98 UnsupportedEncodingException,
99 NoSuchProviderException,
100 InvalidAlgorithmParameterException {
101 Key key = toKey(keyByte);//还原密钥
102 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
103 //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
104 cipher.init(Cipher.DECRYPT_MODE, key);
105 return cipher.doFinal(data);
106 }
107
108 /**
109 * AES解密
110 * @param data 待解密数据为字符串
111 * @param keyByte 密钥
112 */
113 public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException,
114 NoSuchAlgorithmException,
115 InvalidKeySpecException,
116 NoSuchPaddingException,
117 IllegalBlockSizeException,
118 BadPaddingException,
119 UnsupportedEncodingException,
120 NoSuchProviderException,
121 InvalidAlgorithmParameterException {
122 Key key = toKey(keyByte);//还原密钥
123 //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
124 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
125 cipher.init(Cipher.DECRYPT_MODE, key);
126 return cipher.doFinal(Base64.decodeBase64(data));//注意data不可以直接采用data.getByte()方法转化为字节数组,否则会抛异常
127 }
128
129 /**
130 * 测试
131 */
132 public static void main(String[] args) throws NoSuchAlgorithmException,
133 InvalidKeyException,
134 InvalidKeySpecException,
135 NoSuchPaddingException,
136 IllegalBlockSizeException,
137 BadPaddingException,
138 UnsupportedEncodingException,
139 NoSuchProviderException,
140 InvalidAlgorithmParameterException {
141 String data = "找一个好姑娘做老婆是我的梦 想!";
142 /*************测试encrypt()、decrypt()**************/
143 System.out.println("原文-->"+data);
144 byte[] keyByte = AESJDK.getKey();
145 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
146 byte[] encodedByte = AESJDK.encrypt(data, keyByte);
147 System.out.println("加密后-->"+encodedByte);
148 byte[] encodedByte2 = AESJDK.encrypt(data, keyByte);
149 System.out.println("加密后-->"+encodedByte2);
150 byte[] decodedByte = AESJDK.decrypt(encodedByte, keyByte);
151 System.out.println("解密后-->"+decodedByte);
152 for(int i=0;i<encodedByte.length;i++){
153 System.out.println(encodedByte[i]==encodedByte2[i]);
154 }
155 /*************测试encryptAESHex()、decrypt()**************/
156 System.out.println("原文-->"+data);
157 byte[] keyByte3 = AESJDK.getKey();
158 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
159 String encodedStr = AESJDK.encryptAESHex(data, keyByte3);
160 System.out.println("加密后-->"+encodedStr);
161 String encodedByte4 = AESJDK.encryptAESHex(data, keyByte3);
162 System.out.println("加密后-->"+encodedByte4);
163 byte[] decodedByte3 = AESJDK.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
164 System.out.println("解密Byte[]后-->"+decodedByte3);
165 byte[] decodedByte4 = AESJDK.decrypt(encodedStr, keyByte3);
166 System.out.println("解密String后-->"+decodedByte4);
167 }
168 }

注意点:

  • 本文JDK版本采用的是1.6(也是当下企业常用的版本)
  • 基于JDK或是基于BC去实现查看代码中注释即可
  • 想使用BC下,需要在生成密钥的地方加上Security.addProvider(new BouncyCastleProvider());(这与书中不同,可能JDK7不需要加)
  • 密钥初始化长度可以为128,192,256,其中在选用192和256的时候需要配置无政策限制权限文件,具体方法文末会讲。(这与书中不同,可能JDK7下192不需要配置那个文件)

8.2.2、基于BC的AES实现(工作模式为CTR)(这个类在我后边的使用中有点问题,以后有时间再来解决,如果要用AES算法的话,用上边那种就好)

 1 package com.util.aes;
2
3 import java.io.UnsupportedEncodingException;
4 import java.security.InvalidAlgorithmParameterException;
5 import java.security.InvalidKeyException;
6 import java.security.Key;
7 import java.security.NoSuchAlgorithmException;
8 import java.security.NoSuchProviderException;
9 import java.security.Security;
10 import java.security.spec.InvalidKeySpecException;
11
12 import javax.crypto.BadPaddingException;
13 import javax.crypto.Cipher;
14 import javax.crypto.IllegalBlockSizeException;
15 import javax.crypto.KeyGenerator;
16 import javax.crypto.NoSuchPaddingException;
17 import javax.crypto.SecretKey;
18 import javax.crypto.spec.IvParameterSpec;
19 import javax.crypto.spec.SecretKeySpec;
20
21 import org.apache.commons.codec.binary.Base64;
22 import org.bouncycastle.jce.provider.BouncyCastleProvider;
23
24 /**
25 * 基于BC的AES算法,工作模式采用CTR
26 */
27 public class AESBC {
28 private static final String ENCODING = "UTF-8";
29 private static final String KEY_ALGORITHM = "AES";//产生密钥的算法
30 private static final String CIPHER_ALGORITHM = "AES/CTR/PKCS7Padding";//加解密算法 格式:算法/工作模式/填充模式 注意:ECB不使用IV参数,CTR使用
31 private static final byte[] IV = "zhaojigangzhaoji".getBytes();//注意:这里需要是十六个字符,用于CTR
32 /**
33 * 产生密钥
34 */
35 public static byte[] getKey() throws NoSuchAlgorithmException{
36 Security.addProvider(new BouncyCastleProvider());//加入BCProvider
37 KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
38 keyGenerator.init(256);//初始化密钥长度,128,192,256(选用192和256的时候需要配置无政策限制权限文件--JDK6)
39 SecretKey key =keyGenerator.generateKey();//产生密钥
40 return key.getEncoded();
41 }
42
43 /**
44 * 还原密钥:二进制字节数组转换为Java对象
45 */
46 public static Key toKey(byte[] keyByte){
47 return new SecretKeySpec(keyByte, KEY_ALGORITHM);
48 }
49
50 /**
51 * AES加密
52 * @param data 带加密数据
53 * @param keyByte 密钥
54 */
55 public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException,
56 NoSuchAlgorithmException,
57 InvalidKeySpecException,
58 NoSuchPaddingException,
59 IllegalBlockSizeException,
60 BadPaddingException,
61 UnsupportedEncodingException,
62 NoSuchProviderException,
63 InvalidAlgorithmParameterException{
64 Key key = toKey(keyByte);//还原密钥
65 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//使用BC
66 cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
67 return cipher.doFinal(data.getBytes(ENCODING));
68 }
69
70 /**
71 * AES加密,并转为16进制字符串或Base64编码字符串
72 */
73 public static String encryptAESHex(String data, byte[] keyByte) throws InvalidKeyException,
74 NoSuchAlgorithmException,
75 InvalidKeySpecException,
76 NoSuchPaddingException,
77 IllegalBlockSizeException,
78 BadPaddingException,
79 UnsupportedEncodingException,
80 NoSuchProviderException,
81 InvalidAlgorithmParameterException {
82 byte[] encodedByte = encrypt(data, keyByte);
83 //return new String(Hex.encode(encodedByte));//借助BC
84 //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
85 return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
86 }
87
88 /**
89 * AES解密
90 * @param data 待解密数据为字节数组
91 * @param keyByte 密钥
92 */
93 public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException,
94 NoSuchAlgorithmException,
95 InvalidKeySpecException,
96 NoSuchPaddingException,
97 IllegalBlockSizeException,
98 BadPaddingException,
99 UnsupportedEncodingException,
100 NoSuchProviderException,
101 InvalidAlgorithmParameterException {
102 Key key = toKey(keyByte);//还原密钥
103 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");
104 cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
105 return cipher.doFinal(data);
106 }
107
108 /**
109 * AES解密
110 * @param data 待解密数据为字符串
111 * @param keyByte 密钥
112 */
113 public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException,
114 NoSuchAlgorithmException,
115 InvalidKeySpecException,
116 NoSuchPaddingException,
117 IllegalBlockSizeException,
118 BadPaddingException,
119 UnsupportedEncodingException,
120 NoSuchProviderException,
121 InvalidAlgorithmParameterException {
122 Key key = toKey(keyByte);//还原密钥
123 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");
124 cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
125 return cipher.doFinal(Base64.decodeBase64(data));
126 }
127
128 /**
129 * 测试
130 */
131 public static void main(String[] args) throws NoSuchAlgorithmException,
132 InvalidKeyException,
133 InvalidKeySpecException,
134 NoSuchPaddingException,
135 IllegalBlockSizeException,
136 BadPaddingException,
137 UnsupportedEncodingException,
138 NoSuchProviderException,
139 InvalidAlgorithmParameterException {
140 String data = "找一个好姑娘做老婆是我的梦 想!";
141 /*************测试encrypt()、decrypt()**************/
142 System.out.println("原文-->"+data);
143 byte[] keyByte = AESBC.getKey();
144 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
145 byte[] encodedByte = AESBC.encrypt(data, keyByte);
146 System.out.println("加密后-->"+encodedByte);
147 byte[] encodedByte2 = AESBC.encrypt(data, keyByte);
148 System.out.println("加密后-->"+encodedByte2);
149 byte[] decodedByte = AESBC.decrypt(encodedByte, keyByte);
150 System.out.println("解密后-->"+decodedByte);
151 for(int i=0;i<encodedByte.length;i++){
152 System.out.println(encodedByte[i]==encodedByte2[i]);
153 }
154 /*************测试encryptAESHex()、decrypt()**************/
155 System.out.println("原文-->"+data);
156 byte[] keyByte3 = AESBC.getKey();
157 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
158 String encodedStr = AESBC.encryptAESHex(data, keyByte3);
159 System.out.println("加密后-->"+encodedStr);
160 String encodedByte4 = AESBC.encryptAESHex(data, keyByte3);
161 System.out.println("加密后-->"+encodedByte4);
162 byte[] decodedByte3 = AESBC.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
163 System.out.println("解密Byte[]后-->"+decodedByte3);
164 byte[] decodedByte4 = AESBC.decrypt(encodedStr, keyByte3);
165 System.out.println("解密String后-->"+decodedByte4);
166 }
167 }

注意点:

  • CTR是AES最常使用的工作模式
  • 在CTR模式下需要加入IV参数(必须是一个16位的自己数组,例如:byte[] IV = "zhaojigangzhaoji".getBytes()),这是ECB模式所不需要的。
  • IV参数用于cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV))

9.1、IDEA

特点:

  • 先于AES出来取代DES
  • 安全性极高
  • 常用于电子邮件加密算法

9.2、实现方式

  • Bouncy Castle(BC,工作模式只有ECB,密钥长度为128位)

9.2.1、基于BC实现的IDEA算法

1 package com.util.idea;
2
3 import java.io.UnsupportedEncodingException;
4 import java.security.InvalidAlgorithmParameterException;
5 import java.security.InvalidKeyException;
6 import java.security.Key;
7 import java.security.NoSuchAlgorithmException;
8 import java.security.NoSuchProviderException;
9 import java.security.Security;
10 import java.security.spec.InvalidKeySpecException;
11
12 import javax.crypto.BadPaddingException;
13 import javax.crypto.Cipher;
14 import javax.crypto.IllegalBlockSizeException;
15 import javax.crypto.KeyGenerator;
16 import javax.crypto.NoSuchPaddingException;
17 import javax.crypto.SecretKey;
18 import javax.crypto.spec.SecretKeySpec;
19
20 import org.apache.commons.codec.binary.Base64;
21 import org.bouncycastle.jce.provider.BouncyCastleProvider;
22
23 /**
24 * 基于BC的IDEA算法,工作模式只有ECB
25 */
26 public class IDEABC {
27 private static final String ENCODING = "UTF-8";
28 private static final String KEY_ALGORITHM = "IDEA";//产生密钥的算法
29 private static final String CIPHER_ALGORITHM = "IDEA/ECB/PKCS5Padding";//加解密算法 格式:算法/工作模式/填充模式
30 /**
31 * 产生密钥
32 */
33 public static byte[] getKey() throws NoSuchAlgorithmException{
34 Security.addProvider(new BouncyCastleProvider());//在BC中用,JDK下去除
35 KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
36 keyGenerator.init(128);//初始化密钥长度,128
37 SecretKey key =keyGenerator.generateKey();//产生密钥
38 return key.getEncoded();
39 }
40
41 /**
42 * 还原密钥:二进制字节数组转换为Java对象
43 */
44 public static Key toKey(byte[] keyByte){
45 return new SecretKeySpec(keyByte, KEY_ALGORITHM);
46 }
47
48 /**
49 * IDEA加密
50 * @param data 带加密数据
51 * @param keyByte 密钥
52 */
53 public static byte[] encrypt(String data, byte[] keyByte) throws NoSuchAlgorithmException,
54 NoSuchProviderException,
55 NoSuchPaddingException,
56 InvalidKeyException,
57 IllegalBlockSizeException,
58 BadPaddingException,
59 UnsupportedEncodingException {
60 Key key = toKey(keyByte);//还原密钥
61 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
62 cipher.init(Cipher.ENCRYPT_MODE, key);//设置加密模式并且初始化key
63 return cipher.doFinal(data.getBytes(ENCODING));
64 }
65
66 /**
67 * IDEA加密,并转为16进制字符串或Base64编码字符串
68 */
69 public static String encryptIDEAHex(String data, byte[] keyByte) throws NoSuchAlgorithmException,
70 NoSuchProviderException,
71 NoSuchPaddingException,
72 InvalidKeyException,
73 IllegalBlockSizeException,
74 BadPaddingException,
75 UnsupportedEncodingException {
76 byte[] encodedByte = encrypt(data, keyByte);
77 //return new String(Hex.encode(encodedByte));//借助BC
78 //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
79 return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
80 }
81
82 /**
83 * IDEA解密
84 * @param data 待解密数据为字节数组
85 * @param keyByte 密钥
86 */
87 public static byte[] decrypt(byte[] data, byte[] keyByte) throws NoSuchAlgorithmException,
88 NoSuchProviderException,
89 NoSuchPaddingException,
90 InvalidKeyException,
91 IllegalBlockSizeException,
92 BadPaddingException {
93 Key key = toKey(keyByte);//还原密钥
94 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
95 cipher.init(Cipher.DECRYPT_MODE, key);
96 return cipher.doFinal(data);
97 }
98
99 /**
100 * IDEA解密
101 * @param data 待解密数据为字符串
102 * @param keyByte 密钥
103 */
104 public static byte[] decrypt(String data, byte[] keyByte) throws NoSuchAlgorithmException,
105 NoSuchProviderException,
106 NoSuchPaddingException,
107 InvalidKeyException,
108 IllegalBlockSizeException,
109 BadPaddingException {
110 Key key = toKey(keyByte);//还原密钥
111 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
112 cipher.init(Cipher.DECRYPT_MODE, key);
113 return cipher.doFinal(Base64.decodeBase64(data));//注意data不可以直接采用data.getByte()方法转化为字节数组,否则会抛异常
114 }
115
116 /**
117 * 测试
118 */
119 public static void main(String[] args) throws NoSuchAlgorithmException,
120 InvalidKeyException,
121 InvalidKeySpecException,
122 NoSuchPaddingException,
123 IllegalBlockSizeException,
124 BadPaddingException,
125 UnsupportedEncodingException,
126 NoSuchProviderException,
127 InvalidAlgorithmParameterException {
128 String data = "找一个好姑娘做老婆是我的梦 想!";
129 /*************测试encrypt()、decrypt()**************/
130 System.out.println("原文-->"+data);
131 byte[] keyByte = IDEABC.getKey();
132 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
133 byte[] encodedByte = IDEABC.encrypt(data, keyByte);
134 System.out.println("加密后-->"+encodedByte);
135 byte[] encodedByte2 = IDEABC.encrypt(data, keyByte);
136 System.out.println("加密后-->"+encodedByte2);
137 byte[] decodedByte = IDEABC.decrypt(encodedByte, keyByte);
138 System.out.println("解密后-->"+decodedByte);
139 for(int i=0;i<encodedByte.length;i++){
140 System.out.println(encodedByte[i]==encodedByte2[i]);
141 }
142 /*************测试encryptIDEAHex()、decrypt()**************/
143 System.out.println("原文-->"+data);
144 byte[] keyByte3 = IDEABC.getKey();
145 System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
146 String encodedStr = IDEABC.encryptIDEAHex(data, keyByte3);
147 System.out.println("加密后-->"+encodedStr);
148 String encodedByte4 = IDEABC.encryptIDEAHex(data, keyByte3);
149 System.out.println("加密后-->"+encodedByte4);
150 byte[] decodedByte3 = IDEABC.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
151 System.out.println("解密Byte[]后-->"+decodedByte3);
152 byte[] decodedByte4 = IDEABC.decrypt(encodedStr, keyByte3);
153 System.out.println("解密String后-->"+decodedByte4);
154 }
155 }

注意:

  • 与基于BC实现的AES算法代码基本一样

 

第四章 对称加密算法--DES--AES--IDEA--PBE的更多相关文章

  1. 第七章 对称加密算法--DES

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第7章“初等加密算法--对称加密算法” 7.1.对称加密算法 特点: 加密与解密使用同一个密钥 是使用最广的算法 常见对称加密 ...

  2. 常用加密算法的Java实现总结(二) ——对称加密算法DES、3DES和AES

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  3. 对称加密算法DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES。

    对称加密算法:DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES. 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文 ...

  4. 对称加密算法DES、3DES和AES 原理总结(转载)

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  5. [转] 对称加密算法DES、3DES

    转自:http://www.blogjava.net/amigoxie/archive/2014/07/06/415503.html 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法, ...

  6. 对称加密算法 ~ Des

    一.对称加密 (Symmetric Key Encryption)  对称加密是最快速.最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret ...

  7. Atitit.加密算法 des  aes 各个语言不同的原理与解决方案java php c#

    Atitit.加密算法 des  aes 各个语言不同的原理与解决方案java php c# 1. 加密算法的参数::算法/模式/填充 1 2. 标准加密api使用流程1 2.1. Md5——16bi ...

  8. java-信息安全(二)-对称加密算法DES,3DES,AES,Blowfish,RC2,RC4

    概述 信息安全基本概念: DES(Data Encryption Standard,数据加密标准) 3DES(Triple DES,三重数据加密算法(TDEA,Triple Data Encrypti ...

  9. 加密算法(DES,AES,RSA,MD5,SHA1,Base64)比较和项目应用(转载)

    加密技术通常分为两大类:"对称式"和"非对称式". 对称性加密算法:对称式加密就是加密和解密使用同一个密钥.信息接收双方都需事先知道密匙和加解密算法且其密匙是相 ...

  10. 第九章 对称加密算法--IDEA

    注意:本节内容主要参考自<Java加密与解密的艺术(第2版)>第7章“初等加密算法--对称加密算法” 9.1.IDEA 特点: 先于AES出来取代DES 安全性极高 常用于电子邮件加密算法 ...

随机推荐

  1. 基于常量值提取浅析elf文件结构

    Elf(可执行和可链接文件)是一个永远也绕不开的话题,只要我们还在使用安卓手机/linux服务器,我们就需要了解elf的一些方方面面,现在就让我们从一个常量值提取的小需求出发,逐步解析elf文件结构吧 ...

  2. PCI-5565-反射内存RFM2G的学习与使用

    1.介绍 反射内存集成在反射内存卡上,我们使用的是PCI总线的反射内存卡PCI5565,还有PCIE和其它总线类型的反射内存卡,原理差不多.在两台计算机的PCI插槽插两块反射内存卡,然后通过光纤连接. ...

  3. NZOJ 模拟赛5

    T1 逃离遗迹 根据外星人的回信,在遗迹中有分布着三样道具.当三样道具都拿走后,遗迹就很快自动毁灭,所以必须要在最短时间内离开.遗迹可以看作是由N个房间(编号1..N)和N-1条长度不等通道所组成,并 ...

  4. 有经验的Java开发者和架构师容易犯的10个错误

    本文由 ImportNew - Andy.Song 翻译自 zeroturnaround.如需转载本文,请先参见文章末尾处的转载要求. 首先允许我们问一个严肃的问题?为什么Java初学者能够方便的从网 ...

  5. antlr的使用

    我从以下几个问题入手介绍ANTLR的相关知识. 1 ANTLR是什么? ANTLR, ANother Tool for Language Recognition, 是一个可以接受含有语法描述的语言描述 ...

  6. k8s之常用命令

    Minikube # 启动集群服务 minikube start # 查看集群服务状态 minikube status# 登录集群minikube ssh # 关闭,暂停,恢复,删除集群服务 mini ...

  7. MySQL8.0之特性

    MySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能.下面我们将简要介绍下 MySQL 8.0 中值得关注的 ...

  8. PHP之项目环境变量设置

    需求 在PHP开发中为了区分线上生产环境还是本地开发环境, 如果我们能通过判断$_SERVER['RUNTIME_ENVIROMENT']为 'DEV'还是'PRO'来区分该多好, 可惜的是$_SER ...

  9. 【架构】整理了一份通用的MVP框架示例代码

    最近回顾了一下MVP框架,结合阅读到的几篇不错的博客,自己整理了一份可用于实际工作的MVP框架示例代码,这里做个记录,也顺便和网友们分享一下. 代码示例演示的是一个输入员工号查询员工信息并显示的场景, ...

  10. require.js 笔记

    1.前言 随着网站功能逐渐丰富,网页中的js也变得越来越复杂和臃肿,原有通过script标签来导入一个个的js文件这种方式已经不能满足现在互联网开发模式,我们需要团队协作.模块复用.单元测试等等一系列 ...