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. Jmeter并发线程场景下共享变量错乱问题解决

    问题复现 问题描述 使用IF控制器获取前一个请求的后置脚本中设置的全局变量->并发线程下通过vars.get获取变量时,第一个线程和第二个线程获取的变量值一样->导致不同基础数据的请求入参 ...

  2. 域渗透之初识LM&NTLM认证过程

    目录 前言 LM Hash NTLM Hash Windows本地认证 LSASS进程 Mimikatz抓取明文密码 Windows网络认证 Net NTLM NTLMv1 & NTLMv2 ...

  3. vue-elementui中el-table跨页选择和v-if导致列错乱/选择框无法显示

    在vue-elementui中使用el-table,当type="selection"的时候,分页数据进行不同页跳转选择 需要这种功能的时候我们需要在el-table的标签上为每个 ...

  4. Java基础总结大纲(一)

    1.JVM.JRE.和JDK的区别: JVM(Java Virtual Machine):java虚拟机,用于保证java的跨平台的特性.说明:java是跨平台的而JVM不是跨平台的,正对的不同的语言 ...

  5. highcharts中的环形图

    环形图如下效果: 代码: that.options = { chart: { type: 'pie', backgroundColor: 'transparent', color: '#fff', / ...

  6. PythonDay6Advance

    PythonDay6Advance 模块.类与对象 模块 内置模块 time, random, os, json 第三方模块 requests, pandas, numpy,.... 自定义模块 xx ...

  7. 通过加密的方式做身份鉴权—Demo设计

    目录 鉴权方式 账号+密码 账号+短信验证码 第三方渠道鉴权--微信 Reference 本文只是一个Demo设计,仅供学习思路,并不能用于真实的线上业务,因为有很多漏洞. 一般线上应用都需要对用户身 ...

  8. 一图一知-vue强大的slot

    vue常用的slot知识点记录

  9. PM-软件最难的不是开发程序,而是需求

    最近几个月,关于人工智能的惊人文章在互联网泛滥.这也引发了很多人的担心--软件开发人员可能很快就会失业,被人工智能取代.他们想象所有的企业高管和产品研究人员将绕过大多数或所有的软件开发人员,直接要求人 ...

  10. 中电金信新捷报:银行客户资源管理领域No.1

    春暖花开,捷报频传 近日,中电金信 客户关系管理系统(CRM) 接连中标 让我们共同见证这波喜讯 01 中电金信凭借优秀的解决方案和丰富的服务案例经验,成功中标某全国性股份制银行同业CRM实施服务采购 ...