JAVA实现AES加密

JAVA实现AES加密

1. 因子

上次介绍了 《JAVA实现AES加密》,中间提到近些年DES使用越来越少,原因就在于其使用56位密钥,比较容易被破解,近些年来逐渐被AES替代,AES已经变成目前对称加密中最流行算法之一;AES可以使用128、192、和256位密钥,并且用128位分组加密和解密数据。本文就简单介绍如何通过JAVA实现AES加密。

2. JAVA实现

闲话少许,掠过AES加密原理及算法,关于这些直接搜索专业网站吧,我们直接看JAVA的具体实现。

2.1 加密

代码有详细解释,不多废话。
  1. /**
  2. *加密
  3. *
  4. *@paramcontent需要加密的内容
  5. *@parampassword加密密码
  6. *@return
  7. */
  8. publicstaticbyte[]encrypt(Stringcontent,Stringpassword){
  9. try{
  10. KeyGeneratorkgen=KeyGenerator.getInstance("AES");
  11. kgen.init(128,newSecureRandom(password.getBytes()));
  12. SecretKeysecretKey=kgen.generateKey();
  13. byte[]enCodeFormat=secretKey.getEncoded();
  14. SecretKeySpeckey=newSecretKeySpec(enCodeFormat,"AES");
  15. Ciphercipher=Cipher.getInstance("AES");//创建密码器
  16. byte[]byteContent=content.getBytes("utf-8");
  17. cipher.init(Cipher.ENCRYPT_MODE,key);//初始化
  18. byte[]result=cipher.doFinal(byteContent);
  19. returnresult;//加密
  20. }catch(NoSuchAlgorithmExceptione){
  21. e.printStackTrace();
  22. }catch(NoSuchPaddingExceptione){
  23. e.printStackTrace();
  24. }catch(InvalidKeyExceptione){
  25. e.printStackTrace();
  26. }catch(UnsupportedEncodingExceptione){
  27. e.printStackTrace();
  28. }catch(IllegalBlockSizeExceptione){
  29. e.printStackTrace();
  30. }catch(BadPaddingExceptione){
  31. e.printStackTrace();
  32. }
  33. returnnull;
  34. }

2.2 解密

代码有详细注释,不多废话
注意:解密的时候要传入byte数组
  1. /**解密
  2. *@paramcontent待解密内容
  3. *@parampassword解密密钥
  4. *@return
  5. */
  6. publicstaticbyte[]decrypt(byte[]content,Stringpassword){
  7. try{
  8. KeyGeneratorkgen=KeyGenerator.getInstance("AES");
  9. kgen.init(128,newSecureRandom(password.getBytes()));
  10. SecretKeysecretKey=kgen.generateKey();
  11. byte[]enCodeFormat=secretKey.getEncoded();
  12. SecretKeySpeckey=newSecretKeySpec(enCodeFormat,"AES");
  13. Ciphercipher=Cipher.getInstance("AES");//创建密码器
  14. cipher.init(Cipher.DECRYPT_MODE,key);//初始化
  15. byte[]result=cipher.doFinal(content);
  16. returnresult;//加密
  17. }catch(NoSuchAlgorithmExceptione){
  18. e.printStackTrace();
  19. }catch(NoSuchPaddingExceptione){
  20. e.printStackTrace();
  21. }catch(InvalidKeyExceptione){
  22. e.printStackTrace();
  23. }catch(IllegalBlockSizeExceptione){
  24. e.printStackTrace();
  25. }catch(BadPaddingExceptione){
  26. e.printStackTrace();
  27. }
  28. returnnull;
  29. }

2.3 测试代码

  1. Stringcontent="test";
  2. Stringpassword="12345678";
  3. //加密
  4. System.out.println("加密前:"+content);
  5. byte[]encryptResult=encrypt(content,password);
  6. //解密
  7. byte[]decryptResult=decrypt(encryptResult,password);
  8. System.out.println("解密后:"+newString(decryptResult));
输出结果如下:
加密前:test
解密后:test

2.4 容易出错的地方

但是如果我们将测试代码修改一下,如下:
  1. Stringcontent="test";
  2. Stringpassword="12345678";
  3. //加密
  4. System.out.println("加密前:"+content);
  5. byte[]encryptResult=encrypt(content,password);
  6. try{
  7. StringencryptResultStr=newString(encryptResult,"utf-8");
  8. //解密
  9. byte[]decryptResult=decrypt(encryptResultStr.getBytes("utf-8"),password);
  10. System.out.println("解密后:"+newString(decryptResult));
  11. }catch(UnsupportedEncodingExceptione){
  12. e.printStackTrace();
  13. }
则,系统会报出如下异常:
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进制
  1. /**将二进制转换成16进制
  2. *@parambuf
  3. *@return
  4. */
  5. publicstaticStringparseByte2HexStr(bytebuf[]){
  6. StringBuffersb=newStringBuffer();
  7. for(inti=0;i<buf.length;i++){
  8. Stringhex=Integer.toHexString(buf[i]&0xFF);
  9. if(hex.length()==1){
  10. hex='0'+hex;
  11. }
  12. sb.append(hex.toUpperCase());
  13. }
  14. returnsb.toString();
  15. }
2.4.2 将16进制转换为二进制
  1. /**将16进制转换为二进制
  2. *@paramhexStr
  3. *@return
  4. */
  5. publicstaticbyte[]parseHexStr2Byte(StringhexStr){
  6. if(hexStr.length()<1)
  7. returnnull;
  8. byte[]result=newbyte[hexStr.length()/2];
  9. for(inti=0;i<hexStr.length()/2;i++){
  10. inthigh=Integer.parseInt(hexStr.substring(i*2,i*2+1),16);
  11. intlow=Integer.parseInt(hexStr.substring(i*2+1,i*2+2),16);
  12. result[i]=(byte)(high*16+low);
  13. }
  14. returnresult;
  15. }
然后,我们再修订以上测试代码,如下:
  1. Stringcontent="test";
  2. Stringpassword="12345678";
  3. //加密
  4. System.out.println("加密前:"+content);
  5. byte[]encryptResult=encrypt(content,password);
  6. StringencryptResultStr=parseByte2HexStr(encryptResult);
  7. System.out.println("加密后:"+encryptResultStr);
  8. //解密
  9. byte[]decryptFrom=parseHexStr2Byte(encryptResultStr);
  10. byte[]decryptResult=decrypt(decryptFrom,password);
  11. System.out.println("解密后:"+newString(decryptResult));
测试结果如下:
加密前:test
加密后:73C58BAFE578C59366D8C995CD0B9D6D
解密后:test

2.5 另外一种加密方式

还有一种加密方式,大家可以参考如下:
  1. /**
  2. *加密
  3. *
  4. *@paramcontent需要加密的内容
  5. *@parampassword加密密码
  6. *@return
  7. */
  8. publicstaticbyte[]encrypt2(Stringcontent,Stringpassword){
  9. try{
  10. SecretKeySpeckey=newSecretKeySpec(password.getBytes(),"AES");
  11. Ciphercipher=Cipher.getInstance("AES/ECB/NoPadding");
  12. byte[]byteContent=content.getBytes("utf-8");
  13. cipher.init(Cipher.ENCRYPT_MODE,key);//初始化
  14. byte[]result=cipher.doFinal(byteContent);
  15. returnresult;//加密
  16. }catch(NoSuchAlgorithmExceptione){
  17. e.printStackTrace();
  18. }catch(NoSuchPaddingExceptione){
  19. e.printStackTrace();
  20. }catch(InvalidKeyExceptione){
  21. e.printStackTrace();
  22. }catch(UnsupportedEncodingExceptione){
  23. e.printStackTrace();
  24. }catch(IllegalBlockSizeExceptione){
  25. e.printStackTrace();
  26. }catch(BadPaddingExceptione){
  27. e.printStackTrace();
  28. }
  29. returnnull;
  30. }
这种加密方式有两种限制
  • 密钥必须是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*..)
要解决如上异常,可以通过补全传入加密内容等方式进行避免。

---------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值