1 /** 2 * Copyright By Grandsoft Company Limited. 3 * 2014年3月18日 上午10:31:11 4 */ 5 package gboat2.base.bridge.util.security; 6 import java.security.Key; 7 import java.security.NoSuchAlgorithmException; 8 import java.security.SecureRandom; 9 import java.util.Arrays; 10 11 import javax.crypto.KeyGenerator; 12 import javax.crypto.SecretKey; 13 import javax.crypto.SecretKeyFactory; 14 import javax.crypto.spec.DESKeySpec; 15 import javax.crypto.spec.SecretKeySpec; 16 17 import org.apache.commons.codec.binary.Base64; 18 import org.apache.commons.lang3.StringUtils; 19 /** 20 * DES 加密、解密工具类,支持 DES、DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR) 21 * 等加密算法。 22 * <pre> 23 * DES key size must be equal to 56 24 * DESede(TripleDES) key size must be equal to 112 or 168 25 * AES key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available 26 * Blowfish key size must be multiple of 8, and can only range from 32 to 448 (inclusive) 27 * RC2 key size must be between 40 and 1024 bits 28 * RC4(ARCFOUR) key size must be between 40 and 1024 bits 29 * 30 * 31 * Java 和 .NET 程序进行 3DES 加解密数据交互的示例: 32 * <code> 33 * String data = "hemw, 你好!"; 34 * String key = "F8-DC-2F-AA-C8-A6-82-E3-EB-35-2A-E2-DC-EA-38-FD"; 35 * 36 * System.out.println("加密前:" + data); 37 * System.out.println(" 密钥:" + key); 38 * 39 * Key k = DESUtil.getSecretKey(key, DESUtil.DESEDE, true); 40 * String encryptedText = DESUtil.encrypt(data, k, DESUtil.DESEDE_WITH_DOTNET); 41 * System.out.println("加密后:" + encryptedText); // .NET 可以直接对该密文进行解密 42 * 43 * // encryptedText 为 .NET 加密后的密文 44 * String decryptedText = DESUtil.decrypt(encryptedText, k, DESUtil.DESEDE_WITH_DOTNET); 45 * System.out.println("解密后:" + decryptedText); 46 * </code> 47 * </pre> 48 * 在使用该工具类进行加密、解密操作时,一定要注意不同加密算法对密钥的长度要求。更多内容请参考 49 * <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html" target ="_blank"> 50 * http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html 51 * </a> 52 * 53 * @author <a href="mailto:[email protected]">何明旺</a> 54 * @since 3.0 55 * @date 2014年3月18日 56 */ 57 public class DESUtil { 58 59 /** key size must be equal to 56, default key size is 56 bits */ 60 public static final String DES = "DES"; 61 62 /** 63 * (TripleDES) key size must be equal to 112 or 168, default key size is 168 bits<br> 64 * A keysize of 112 will generate a Triple DES key with 2 intermediate keys, 65 * and a keysize of 168 will generate a Triple DES key with 3 intermediate 66 * keys.<br> 67 * Due to the "Meet-In-The-Middle" problem, even though 112 or 168 bits of 68 * key material are used, the effective keysize is 80 or 112 bits 69 * respectively. 70 */ 71 public static final String DESEDE = "DESede"; 72 73 /** key size must be equal to 128, 192 or 256,but 192 and 256 bits, may not be available, default key size is 128 bits */ 74 public static final String AES = "AES"; 75 76 /** key size must be multiple of 8, and can only range from 32 to 448 (inclusive), default key size is 128 bits */ 77 public static final String BLOWFISH = "Blowfish"; 78 79 /** key size must be between 40 and 1024 bits (inclusive), default key size is 128 bits */ 80 public static final String RC2 = "RC2"; 81 82 /** (ARCFOUR) Keysize must range between 40 and 1024 bits (inclusive), default key size is 128 bits */ 83 public static final String RC4 = "RC4"; 84 85 /** .NET 默认的 3DES 加密的算法模型,值为 {@value} */ 86 public static final String DESEDE_WITH_DOTNET = "DESede/ECB/PKCS5Padding"; 87 88 /** 89 * 生成 DES 密钥 90 * 91 * @return 92 */ 93 public static String generateKey() { 94 return generateKey(null); 95 } 96 97 /** 98 * 生成 DES 密钥 99 * 100 * @param seed 种子 101 * @return 经过 BASE64 编码的密钥字符串 102 */ 103 public static String generateKey(String seed) { 104 return generateKey(seed, DES); 105 } 106 107 /** 108 * 生成密钥 109 * 110 * @param seed 种子 111 * @param algorithm 加密算法名称,支持的算法: {@link #DES}、 {@link #DESEDE}、{@link #AES}、 112 * {@link #BLOWFISH}、{@link #RC2}、 {@link #RC4} 113 * @return 经过 BASE64 编码的密钥字符串 114 */ 115 public static String generateKey(String seed, String algorithm) { 116 SecureRandom secureRandom = (seed == null) ? new SecureRandom() : new SecureRandom(Base64.decodeBase64(seed)); 117 KeyGenerator kg = Encryptor.getKeyGenerator(algorithm); 118 kg.init(secureRandom); 119 SecretKey secretKey = kg.generateKey(); 120 return Base64.encodeBase64String(secretKey.getEncoded()); 121 } 122 123 /** 124 * 将 DES 密钥字符串转换为密钥实例对象 125 * @param desKey 经过 BASE64 编码的密钥字符串 126 * @return 密钥实例对象 127 */ 128 public static SecretKey getSecretKey(String desKey){ 129 return getSecretKey(desKey, DES); 130 } 131 132 /** 133 * 将密钥字符串转换为密钥实例对象 134 * @param desKey 经过 BASE64 编码的密钥字符串 135 * @param algorithm 加密算法名称,支持的算法: {@link #DES}、 {@link #DESEDE}、{@link #AES}、 136 * {@link #BLOWFISH}、{@link #RC2}、 {@link #RC4} 137 * @return 密钥实例对象 138 */ 139 public static SecretKey getSecretKey(String desKey, String algorithm) { 140 if(StringUtils.isBlank(desKey)) 141 throw new IllegalArgumentException("密钥不能为空。"); 142 return getSecretKey(Base64.decodeBase64(desKey), algorithm); 143 } 144 145 /** 146 * 将密钥字符串转换为密钥实例对象 147 * 148 * @param key 密钥字符串 149 * @param algorithm 加密算法名称,支持的算法: {@link #DES}、 {@link #DESEDE}、{@link #AES}、 150 * {@link #BLOWFISH}、{@link #RC2}、 {@link #RC4} 151 * @param md5 密钥字符串是否需要经过 MD5 加密,如果为 true,则会对 key 进行加密处理,如果值为 false,则对 key 152 * 进行 BASE64 解码处理。.NET 进行 3DES 加密时,默认会对 key 进行 MD5 加密处理,所以与 .NET 153 * 程序进行 3DES 加解密数据交互时,需要将该参数值高为 ture。 154 * @return 密钥实例对象 155 */ 156 public static SecretKey getSecretKey(String key, String algorithm, boolean md5) { 157 if(StringUtils.isBlank(key)) 158 throw new IllegalArgumentException("密钥不能为空。"); 159 160 byte[] keyBytes = null; 161 if(md5) { 162 final byte[] digestOfKey = Encryptor.digest(key, Encryptor.MD5); 163 keyBytes = Arrays.copyOf(digestOfKey, 24); 164 for (int j = 0, k = 16; j < 8;) { 165 keyBytes[k++] = keyBytes[j++]; 166 } 167 } else { 168 keyBytes = Base64.decodeBase64(key); 169 } 170 171 return getSecretKey(keyBytes, algorithm); 172 } 173 174 /** 175 * 将密钥字符串转换为密钥实例对象 176 * 177 * @param desKey 密钥 178 * @param algorithm 加密算法名称,支持的算法: {@link #DES}、 {@link #DESEDE}、{@link #AES}、 179 * {@link #BLOWFISH}、{@link #RC2}、 {@link #RC4} 180 * @return 181 */ 182 public static SecretKey getSecretKey(byte[] desKey, String algorithm) { 183 if(DES.equalsIgnoreCase(algorithm)) { 184 try { 185 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm); 186 DESKeySpec dks = new DESKeySpec(desKey); 187 return keyFactory.generateSecret(dks); 188 } catch (NoSuchAlgorithmException e) { 189 throw new GboatSecurityException("算法 [" + algorithm + "] 不存在,或当前 JDK 不支持该算法。", e); 190 } catch (Exception e) { 191 throw new IllegalArgumentException("将密钥字符串转换为密钥实例对象失败。", e); 192 } 193 } 194 195 return new SecretKeySpec(desKey, algorithm); 196 } 197 198 /** 199 * 对数据进行 DES 加密 200 * @param data 要加密的数据 201 * @param key 经过 BASE64 编码的密钥字符串 202 * @return 经过 BASE64 编码的密文 203 */ 204 public static String encrypt(String data, String key) { 205 byte[] entryptBytes = encrypt(data.getBytes(), key); 206 return Base64.encodeBase64String(entryptBytes); 207 } 208 209 /** 210 * 对数据进行 DES 加密 211 * @param data 要加密的数据 212 * @param key 经过 BASE64 编码的密钥字符串 213 * @return 密文 214 */ 215 public static byte[] encrypt(byte[] data, String key) { 216 return encrypt(data, key, DES); 217 } 218 219 /** 220 * 对数据进行加密 221 * 222 * @param data 要加密的明文数据 223 * @param key 经过 BASE64 编码的密钥字符串 224 * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g., 225 * DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank" 226 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> 227 * Java Cryptography Architecture Reference Guide</a> for information about standard transformation names. 228 * <pre> 229 * The following table lists cipher algorithms available in the SunJCE provider: 230 * AlgorithmName Modes Paddings 231 * AES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB, OFB8..OFB128 NOPADDING, PKCS5PADDING, ISO10126PADDING 232 * Blowfish ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 233 * DES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 234 * DESede ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 235 * RC2 ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 236 * ARCFOUR ECB NOPADDING 237 * </pre> 238 * 239 * @return 密文 240 */ 241 public static byte[] encrypt(byte[] data, String key, String transformation) { 242 Key k = getSecretKey(key, Encryptor.getAlgorithmFromTransformation(transformation)); 243 return Encryptor.encrypt(data, k, transformation); 244 } 245 246 /** 247 * 对数据进行加密 248 * 249 * @param data 要加密的明文数据 250 * @param key 经过 BASE64 编码的密钥字符串 251 * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g., 252 * DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank" 253 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> 254 * Java Cryptography Architecture Reference Guide</a> for information about standard transformation names. 255 * <pre> 256 * The following table lists cipher algorithms available in the SunJCE provider: 257 * AlgorithmName Modes Paddings 258 * AES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB, OFB8..OFB128 NOPADDING, PKCS5PADDING, ISO10126PADDING 259 * Blowfish ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 260 * DES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 261 * DESede ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 262 * RC2 ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 263 * ARCFOUR ECB NOPADDING 264 * </pre> 265 * 266 * @return 经过 BASE64 编码的密文字符串 267 */ 268 public static String encrypt(String data, String key, String transformation) { 269 Key k = getSecretKey(key, Encryptor.getAlgorithmFromTransformation(transformation)); 270 return encrypt(data, k, transformation); 271 } 272 273 /** 274 * 对数据进行加密 275 * 276 * @param data 要加密的明文数据 277 * @param key 密钥 278 * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g., 279 * DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank" 280 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> 281 * Java Cryptography Architecture Reference Guide</a> for information about standard transformation names. 282 * <pre> 283 * The following table lists cipher algorithms available in the SunJCE provider: 284 * AlgorithmName Modes Paddings 285 * AES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB, OFB8..OFB128 NOPADDING, PKCS5PADDING, ISO10126PADDING 286 * Blowfish ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 287 * DES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 288 * DESede ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 289 * RC2 ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 290 * ARCFOUR ECB NOPADDING 291 * </pre> 292 * 293 * @return 经过 BASE64 编码的密文字符串 294 */ 295 public static String encrypt(String data, Key key, String transformation) { 296 byte[] entryptBytes = Encryptor.encrypt(data.getBytes(), key, transformation); 297 return Base64.encodeBase64String(entryptBytes); 298 } 299 300 301 /** 302 * 对数据进行 DES 解密 303 * @param data 要解密的数据 304 * @param key 经过 BASE64 编码的密钥字符串 305 * @return 经过 BASE64 编码的密文 306 */ 307 public static String decrypt(String data, String key) { 308 byte[] entryptBytes = decrypt(data.getBytes(), key); 309 return Base64.encodeBase64String(entryptBytes); 310 } 311 312 /** 313 * 对数据进行 DES 解密 314 * @param data 要解密的数据 315 * @param key 经过 BASE64 编码的密钥字符串 316 * @return 密文 317 */ 318 public static byte[] decrypt(byte[] data, String key) { 319 return decrypt(data, key, DES); 320 } 321 322 /** 323 * 对数据进行解密 324 * 325 * @param data 要解密的明文数据 326 * @param key 经过 BASE64 编码的密钥字符串 327 * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g., 328 * DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank" 329 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> 330 * Java Cryptography Architecture Reference Guide</a> for information about standard transformation names. 331 * <pre> 332 * The following table lists cipher algorithms available in the SunJCE provider: 333 * AlgorithmName Modes Paddings 334 * AES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB, OFB8..OFB128 NOPADDING, PKCS5PADDING, ISO10126PADDING 335 * Blowfish ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 336 * DES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 337 * DESede ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 338 * RC2 ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 339 * ARCFOUR ECB NOPADDING 340 * </pre> 341 * 342 * @return 密文 343 */ 344 public static byte[] decrypt(byte[] data, String key, String transformation) { 345 Key k = getSecretKey(key, Encryptor.getAlgorithmFromTransformation(transformation)); 346 return Encryptor.decrypt(data, k, transformation); 347 } 348 349 /** 350 * 对数据进行解密 351 * 352 * @param data 要解密的明文数据 353 * @param key 经过 BASE64 编码的密钥字符串 354 * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g., 355 * DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank" 356 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> 357 * Java Cryptography Architecture Reference Guide</a> for information about standard transformation names. 358 * <pre> 359 * The following table lists cipher algorithms available in the SunJCE provider: 360 * AlgorithmName Modes Paddings 361 * AES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB, OFB8..OFB128 NOPADDING, PKCS5PADDING, ISO10126PADDING 362 * Blowfish ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 363 * DES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 364 * DESede ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 365 * RC2 ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 366 * ARCFOUR ECB NOPADDING 367 * </pre> 368 * 369 * @return 经过 BASE64 编码的密文字符串 370 */ 371 public static String decrypt(String data, String key, String transformation) { 372 Key k = getSecretKey(key, Encryptor.getAlgorithmFromTransformation(transformation)); 373 return decrypt(data, k, transformation); 374 } 375 376 /** 377 * 对数据进行解密 378 * 379 * @param data 要解密的明文数据 380 * @param key 密钥 381 * @param transformation the name of the transformation, format is "Algorithm/Modes/Paddings", e.g., 382 * DES/CBC/PKCS5Padding. See Appendix A in the <a target="_blank" 383 * href="http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#AppA"> 384 * Java Cryptography Architecture Reference Guide</a> for information about standard transformation names. 385 * <pre> 386 * The following table lists cipher algorithms available in the SunJCE provider: 387 * AlgorithmName Modes Paddings 388 * AES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB128, OFB, OFB8..OFB128 NOPADDING, PKCS5PADDING, ISO10126PADDING 389 * Blowfish ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 390 * DES ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 391 * DESede ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 392 * RC2 ECB, CBC, PCBC, CTR, CTS, CFB, CFB8..CFB64, OFB, OFB8..OFB64 NOPADDING, PKCS5PADDING, ISO10126PADDING 393 * ARCFOUR ECB NOPADDING 394 * </pre> 395 * 396 * @return 经过 BASE64 编码的密文字符串 397 */ 398 public static String decrypt(String data, Key key, String transformation) { 399 byte[] dataBytes = Base64.decodeBase64(data); 400 byte[] decryptedBytes = Encryptor.decrypt(dataBytes, key, transformation); 401 return new String(decryptedBytes); 402 } 403 404 }