这两天做项目需要和.net 平台做通信,他们使用的加密是3DES,互联网上比较常见的一些算法,J2EE平台无法公用,只有自己写一个,给有需要的朋友一个参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
package com.uninf.video.util.encryption;
 
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
/**
 * 3DES 加密解密算法,用于拓荒族通信 http://www.tuohuangzu.com
 * 
 * @author zhangwei
 * 
 * 
 * @time 2013-1-29 上午8:53:23
 * 
 */
public class DES3Tools {
	Logger log = LoggerFactory.getLogger(DES3Tools.class);
 
	byte[] encryptKey;
	DESedeKeySpec spec;
	SecretKeyFactory keyFactory;
	SecretKey theKey;
	Cipher cipher;
	IvParameterSpec IvParameters;
 
	/**
	 * 字符串转换为byte数组
	 * 
	 * @param str
	 * @return
	 */
	public byte[] StringToByte(String str) {
		char[] ch = str.toUpperCase().toCharArray();
		byte[] newBytes = new byte[str.length() / 2];
		for (int i = 0; i < newBytes.length; i++) {
			newBytes[i] = (byte) (Char2Hex(ch[i * 2]) * (0x10) + Char2Hex(ch[i * 2 + 1]));
		}
		return newBytes;
	}
 
	/**
	 * 字符与16进制转换
	 * 
	 * @param chr
	 * @return
	 */
	private byte Char2Hex(char chr) {
		switch (chr) {
		case '0':
			return 0x00;
		case '1':
			return 0x01;
		case '2':
			return 0x02;
		case '3':
			return 0x03;
		case '4':
			return 0x04;
		case '5':
			return 0x05;
		case '6':
			return 0x06;
		case '7':
			return 0x07;
		case '8':
			return 0x08;
		case '9':
			return 0x09;
		case 'A':
			return 0x0a;
		case 'B':
			return 0x0b;
		case 'C':
			return 0x0c;
		case 'D':
			return 0x0d;
		case 'E':
			return 0x0e;
		case 'F':
			return 0x0f;
		}
		return 0x00;
	}
 
	/**
	 * 初始化3des加密工具类
	 */
	public DES3Tools() {
		try {
			// 检测是否有 TripleDES 加密的供应程序
			// 如无,明确地安装SunJCE 供应程序
			try {
				cipher = Cipher.getInstance("DESede");
			} catch (Exception e) {
				log.error("Installling SunJCE provider.");
				Provider sunjce = new com.sun.crypto.provider.SunJCE();
				Security.addProvider(sunjce);
			}
			// 创建一个密钥 24位以上的Key
			encryptKey = StringToByte(EncryptConfig.DES3_KEY);
			// 为上一密钥创建一个指定的 DESSede key
			spec = new DESedeKeySpec(encryptKey);
			// 得到 DESSede keys
			keyFactory = SecretKeyFactory.getInstance("DESede");
			// 生成一个 DESede 密钥对象
			theKey = keyFactory.generateSecret(spec);
 
			// 创建一个 DESede 密码
			cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
 
			// 为 CBC 模式创建一个用于初始化的 vector 对象
			IvParameters = new IvParameterSpec(
					StringToByte(EncryptConfig.DES3_IV));
		} catch (Exception exc) {
			// 记录加密或解密操作错误
			log.error("Constructor error :" + exc.getMessage());
		}
	}
 
	/**
	 * 加密算法
	 * 
	 * @param arg
	 *            等待加密的密码
	 * @return 加密以后的密码
	 * @throws Exception
	 */
	public byte[] encrypt(String arg) {
		String encrypted_args = null;
		byte[] encrypted_argb = null;
 
		try {
			// 以加密模式初始化密钥
			cipher.init(Cipher.ENCRYPT_MODE, theKey, IvParameters);
			// 加密前的密码(旧)
			byte[] plainttext = arg.getBytes();
			// 加密密码
			encrypted_argb = cipher.doFinal(plainttext);
			// 转成字符串,得到加密后的密码(新)
			encrypted_args = new String(encrypted_argb);
		} catch (Exception ex) {
			// 记录加密错误
			log.error("encrypt error : " + ex.getMessage());
		}
		return encrypted_argb;
	}
 
	/**
	 * 解密算法
	 * 
	 * @param argb
	 *            加过密的密码
	 * @return 解密后的密码
	 */
	public String decrypt(byte[] argb) {
		String decrypted_args = null;
		try {
			// 以解密模式初始化密钥
			cipher.init(Cipher.DECRYPT_MODE, theKey, IvParameters);
			// 构造解密前的密码
			byte[] decryptedPassword = argb;
			// 解密密码
			byte[] decrypted_pwd = cipher.doFinal(decryptedPassword);
			// 得到结果
			decrypted_args = new String(decrypted_pwd);
		} catch (Exception ex) {
			// 记录解密错误
		}
		return decrypted_args;
	}
 
	/**
	 * byte 数组返回字符串
	 * 
	 * @param arrB
	 * @return
	 */
	public String byteArr2HexStr(byte[] arrB) {
		int iLen = arrB.length;
		// 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
		StringBuffer sb = new StringBuffer(iLen * 2);
		for (int i = 0; i < iLen; i++) {
			int intTmp = arrB[i];
			// 把负数转换为正数
			while (intTmp < 0) {
				intTmp = intTmp + 256;
			}
			// 小于0F的数需要在前面补0
			if (intTmp < 16) {
				sb.append("0");
			}
			sb.append(Integer.toString(intTmp, 16));
		}
		return sb.toString();
	}
 
	/**
	 * 字符串转换byte数组
	 * 
	 * @param strIn
	 * @return
	 */
	public byte[] hexStr2ByteArr(String strIn) {
		byte[] arrB = strIn.getBytes();
		int iLen = arrB.length;
		// 两个字符表示一个字节,所以字节数组长度是字符串长度除以2
		byte[] arrOut = new byte[iLen / 2];
		for (int i = 0; i < iLen; i = i + 2) {
			String strTmp = new String(arrB, i, 2);
			arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
		}
		return arrOut;
	}
 
	/**
	 * base64 加密
	 * 
	 * @param argb
	 * @return
	 */
	public String base64Encode(byte[] argb) {
		return new BASE64Encoder().encode(argb);
	}
 
	/**
	 * base64 解密
	 * 
	 * @param args
	 * @return
	 * @throws IOException
	 */
	public byte[] base64DEcode(String args) {
		byte[] bytes = null;
		try {
			bytes = new BASE64Decoder().decodeBuffer(args);
		} catch (IOException e) {
			log.error("base64decoder error :" + e.getMessage());
		}
		return bytes;
	}
 
	/**
	 * 生成验证字符串
	 * 
	 * @param args
	 * @return
	 */
	public String getGarbleString(String args) {
		byte[] plainText = null;
		try {
			plainText = args.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		MessageDigest messageDigest = null;
		try {
			messageDigest = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		messageDigest.update(plainText);
		byte[] digest = messageDigest.digest();
		String newStr = base64Encode(digest);
		return newStr;
	}
 
	/**
	 * 验证字符串
	 * 
	 * @return
	 */
	public boolean verifyString(String[] args) {
		if (args.length != 2) {
			return false;
		} else {
			return getGarbleString(args[0]).equals(args[1]);
		}
	}
 
	/**
	 * 3des 通信最终加密工具
	 * 
	 * @param plainText
	 * @return
	 */
	public static final String finalEncode(String plainText) {
		DES3Tools des3 = new DES3Tools();
		String garbleText = plainText + "|" + des3.getGarbleString(plainText);
		return des3.base64Encode(des3.encrypt(garbleText));
	}
 
	/**
	 * 3des 通信最终解密工具
	 * 
	 * @param garbeText
	 * @return
	 */
	public static final String finalDEcode(String garbeText) {
		String plainText = null;
		DES3Tools des3 = new DES3Tools();
		byte[] tmpByte = des3.base64DEcode(garbeText);
		String tmpString = des3.decrypt(tmpByte);
		String[] tmpStrs = tmpString.split("\\|");
		if (des3.verifyString(tmpStrs)) {
			plainText = tmpStrs[0];
		} else {
 
		}
		return plainText;
	}
 
	public static void main(String[] args) {
		DES3Tools ed = new DES3Tools();
		String plainText = "2217";
		String garbleText = ed.getGarbleString(plainText);
		System.err
				.println("---------------------------------------------------------------------");
		System.out.println("生成明文混淆字符串 :" + garbleText);
		String[] strs = { plainText, garbleText };
		System.out.println("验证混淆字符串是否正确 :" + ed.verifyString(strs));
		byte[] temp = ed.encrypt(plainText + "|" + garbleText);
		String s = ed.byteArr2HexStr(temp);
		String newStr = ed.base64Encode(temp);
 
		System.out.println("加密后:" + s);
		System.out.println("解密后:" + ed.decrypt(ed.hexStr2ByteArr(s)));
		System.out.println("base64混淆后:" + newStr);
		System.out.println("base64混淆解密后:"
				+ ed.byteArr2HexStr(ed.base64DEcode(newStr)));
		System.err
				.println("=============================================================================");
		String pt = "2217";
		System.err.println("3des 加密工具使用 API 明文: " + pt);
		System.err.println("DES3Tools.finalEncode(明文参数字符串)结果:"
				+ DES3Tools.finalEncode(pt));
		String gt = "bclsmKghcNh1NLewhZFbLDl+9d2uTgHcXqA3fR4zrz8UHfg7nNzeHQ==";
		System.err.println("3des 解密工具使用 API 密文: " + gt);
		System.err.println("DES3Tools.finalDEcode(密文参数字符串)结果:"
				+ DES3Tools.finalDEcode(gt));
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.uninf.video.util.encryption;
 
import org.uninf.config.ConfigReader;
 
/**
 * 加密解密配置文件
 * 
 * @author zhangwei
 * 
 * 
 * @time 2013-1-29 上午8:50:23
 * 
 */
public class EncryptConfig {
	public static final String DES3_KEY = get("DES3_KEY");//替换你的密钥
	public static final String DES3_IV = get("DES3_IV");//替换你的IV
 
	private static String get(String name) {
		return ConfigReader.getConfigReader().get(name);
	}
}