读书人

转的JAVA兑现AES加密

发布时间: 2012-08-31 12:55:03 作者: rapoo

转的JAVA实现AES加密

?

JAVA实现AES加密

1. 因子???????上次介绍了《JAVA实现AES加密》,中间提到近些年DES使用越来越少,原因就在于其使用56位密钥,比较容易被破解,近些年来逐渐被AES替代,AES已经变成目前对称加密中最流行算法之一;AES可以使用128、192、和256位密钥,并且用128位分组加密和解密数据。本文就简单介绍如何通过JAVA实现AES加密。2. JAVA实现闲话少许,掠过AES加密原理及算法,关于这些直接搜索专业网站吧,我们直接看JAVA的具体实现。2.1 加密代码有详细解释,不多废话。view plain
  1. /**??*?加密?
  2. ?*???*?@param?content?需要加密的内容?
  3. ?*?@param?password??加密密码??*?@return?
  4. ?*/??public?static?byte[]?encrypt(String?content,?String?password)?{??
  5. ????????try?{?????????????????????????????KeyGenerator?kgen?=?KeyGenerator.getInstance("AES");??
  6. ????????????????kgen.init(128,?new?SecureRandom(password.getBytes()));??????????????????SecretKey?secretKey?=?kgen.generateKey();??
  7. ????????????????byte[]?enCodeFormat?=?secretKey.getEncoded();??????????????????SecretKeySpec?key?=?new?SecretKeySpec(enCodeFormat,?"AES");??
  8. ????????????????Cipher?cipher?=?Cipher.getInstance("AES");//?创建密码器??????????????????byte[]?byteContent?=?content.getBytes("utf-8");??
  9. ????????????????cipher.init(Cipher.ENCRYPT_MODE,?key);//?初始化??????????????????byte[]?result?=?cipher.doFinal(byteContent);??
  10. ????????????????return?result;?//?加密??????????}?catch?(NoSuchAlgorithmException?e)?{??
  11. ????????????????e.printStackTrace();??????????}?catch?(NoSuchPaddingException?e)?{??
  12. ????????????????e.printStackTrace();??????????}?catch?(InvalidKeyException?e)?{??
  13. ????????????????e.printStackTrace();??????????}?catch?(UnsupportedEncodingException?e)?{??
  14. ????????????????e.printStackTrace();??????????}?catch?(IllegalBlockSizeException?e)?{??
  15. ????????????????e.printStackTrace();??????????}?catch?(BadPaddingException?e)?{??
  16. ????????????????e.printStackTrace();??????????}??
  17. ????????return?null;??}??
2.2 解密代码有详细注释,不多废话注意:解密的时候要传入byte数组view plain
  1. /**解密??*?@param?content??待解密内容?
  2. ?*?@param?password?解密密钥??*?@return?
  3. ?*/??public?static?byte[]?decrypt(byte[]?content,?String?password)?{??
  4. ????????try?{???????????????????KeyGenerator?kgen?=?KeyGenerator.getInstance("AES");??
  5. ?????????????????kgen.init(128,?new?SecureRandom(password.getBytes()));???????????????????SecretKey?secretKey?=?kgen.generateKey();??
  6. ?????????????????byte[]?enCodeFormat?=?secretKey.getEncoded();???????????????????SecretKeySpec?key?=?new?SecretKeySpec(enCodeFormat,?"AES");??????????????
  7. ?????????????????Cipher?cipher?=?Cipher.getInstance("AES");//?创建密码器??????????????????cipher.init(Cipher.DECRYPT_MODE,?key);//?初始化??
  8. ????????????????byte[]?result?=?cipher.doFinal(content);??????????????????return?result;?//?加密??
  9. ????????}?catch?(NoSuchAlgorithmException?e)?{??????????????????e.printStackTrace();??
  10. ????????}?catch?(NoSuchPaddingException?e)?{??????????????????e.printStackTrace();??
  11. ????????}?catch?(InvalidKeyException?e)?{??????????????????e.printStackTrace();??
  12. ????????}?catch?(IllegalBlockSizeException?e)?{??????????????????e.printStackTrace();??
  13. ????????}?catch?(BadPaddingException?e)?{??????????????????e.printStackTrace();??
  14. ????????}??????????return?null;??
  15. }??
2.3 测试代码view plain
  1. String?content?=?"test";??String?password?=?"12345678";??
  2. //加密??System.out.println("加密前:"?+?content);??
  3. byte[]?encryptResult?=?encrypt(content,?password);??//解密??
  4. byte[]?decryptResult?=?decrypt(encryptResult,password);??System.out.println("解密后:"?+?new?String(decryptResult));??
输出结果如下:加密前:test
解密后:test2.4 容易出错的地方但是如果我们将测试代码修改一下,如下:view plain
  1. String?content?=?"test";??String?password?=?"12345678";??
  2. //加密??System.out.println("加密前:"?+?content);??
  3. byte[]?encryptResult?=?encrypt(content,?password);??try?{??
  4. ????????String?encryptResultStr?=?new?String(encryptResult,"utf-8");??????????//解密??
  5. ????????byte[]?decryptResult?=?decrypt(encryptResultStr.getBytes("utf-8"),password);??????????System.out.println("解密后:"?+?new?String(decryptResult));??
  6. }?catch?(UnsupportedEncodingException?e)?{??????????e.printStackTrace();??
  7. }??
则,系统会报出如下异常:javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
????????at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
????????at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
????????at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
????????at javax.crypto.Cipher.doFinal(DashoA13*..)这主要是因为加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示,主要有如下两个方法:2.4.1将二进制转换成16进制view plain
  1. /**将二进制转换成16进制??*?@param?buf?
  2. ?*?@return??*/??
  3. public?static?String?parseByte2HexStr(byte?buf[])?{??????????StringBuffer?sb?=?new?StringBuffer();??
  4. ????????for?(int?i?=?0;?i?<?buf.length;?i++)?{??????????????????String?hex?=?Integer.toHexString(buf[i]?&?0xFF);??
  5. ????????????????if?(hex.length()?==?1)?{??????????????????????????hex?=?'0'?+?hex;??
  6. ????????????????}??????????????????sb.append(hex.toUpperCase());??
  7. ????????}??????????return?sb.toString();??
  8. }??
2.4.2 将16进制转换为二进制view plain
  1. /**将16进制转换为二进制??*?@param?hexStr?
  2. ?*?@return??*/??
  3. public?static?byte[]?parseHexStr2Byte(String?hexStr)?{??????????if?(hexStr.length()?<?1)??
  4. ????????????????return?null;??????????byte[]?result?=?new?byte[hexStr.length()/2];??
  5. ????????for?(int?i?=?0;i<?hexStr.length()/2;?i++)?{??????????????????int?high?=?Integer.parseInt(hexStr.substring(i*2,?i*2+1),?16);??
  6. ????????????????int?low?=?Integer.parseInt(hexStr.substring(i*2+1,?i*2+2),?16);??????????????????result[i]?=?(byte)?(high?*?16?+?low);??
  7. ????????}??????????return?result;??
  8. }??
然后,我们再修订以上测试代码,如下:view plain
  1. String?content?=?"test";??String?password?=?"12345678";??
  2. //加密??System.out.println("加密前:"?+?content);??
  3. byte[]?encryptResult?=?encrypt(content,?password);??String?encryptResultStr?=?parseByte2HexStr(encryptResult);??
  4. System.out.println("加密后:"?+?encryptResultStr);??//解密??
  5. byte[]?decryptFrom?=?parseHexStr2Byte(encryptResultStr);??byte[]?decryptResult?=?decrypt(decryptFrom,password);??
  6. System.out.println("解密后:"?+?new?String(decryptResult));??
测试结果如下:加密前:test
加密后:73C58BAFE578C59366D8C995CD0B9D6D
解密后:test?2.5 另外一种加密方式还有一种加密方式,大家可以参考如下:view plain
  1. /**???????*?加密?
  2. ??????*???????*?@param?content?需要加密的内容?
  3. ??????*?@param?password??加密密码???????*?@return?
  4. ??????*/???????public?static?byte[]?encrypt2(String?content,?String?password)?{??
  5. ?????????????try?{???????????????????????SecretKeySpec?key?=?new?SecretKeySpec(password.getBytes(),?"AES");??
  6. ?????????????????????Cipher?cipher?=?Cipher.getInstance("AES/ECB/NoPadding");???????????????????????byte[]?byteContent?=?content.getBytes("utf-8");??
  7. ?????????????????????cipher.init(Cipher.ENCRYPT_MODE,?key);//?初始化???????????????????????byte[]?result?=?cipher.doFinal(byteContent);??
  8. ?????????????????????return?result;?//?加密???????????????}?catch?(NoSuchAlgorithmException?e)?{??
  9. ?????????????????????e.printStackTrace();???????????????}?catch?(NoSuchPaddingException?e)?{??
  10. ?????????????????????e.printStackTrace();???????????????}?catch?(InvalidKeyException?e)?{??
  11. ?????????????????????e.printStackTrace();???????????????}?catch?(UnsupportedEncodingException?e)?{??
  12. ?????????????????????e.printStackTrace();???????????????}?catch?(IllegalBlockSizeException?e)?{??
  13. ?????????????????????e.printStackTrace();???????????????}?catch?(BadPaddingException?e)?{??
  14. ?????????????????????e.printStackTrace();???????????????}??
  15. ?????????????return?null;???????}??
这种加密方式有两种限制密钥必须是16位的待加密内容的长度必须是16的倍数,如果不是16的倍数,就会出如下异常:javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes
????????at com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)
????????at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
????????at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
????????at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
????????at javax.crypto.Cipher.doFinal(DashoA13*..)要解决如上异常,可以通过补全传入加密内容等方式进行避免。

读书人网 >编程

热点推荐