AES For Delphi And Java, AES/ECB/PKCS5Padding(二)

上一篇文章里面,AES加密算法测试用的加密密钥是1234567812345678,正好是128bit的,如果密钥不是128bit呢,该怎么填充?

先看以下代码:

[java]  view plain  copy
  1. package encryption;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4. import java.security.InvalidKeyException;  
  5. import java.security.NoSuchAlgorithmException;  
  6. import java.security.SecureRandom;  
  7.   
  8. import javax.crypto.BadPaddingException;  
  9. import javax.crypto.Cipher;  
  10. import javax.crypto.IllegalBlockSizeException;  
  11. import javax.crypto.KeyGenerator;  
  12. import javax.crypto.NoSuchPaddingException;  
  13. import javax.crypto.SecretKey;  
  14. import javax.crypto.spec.SecretKeySpec;  
  15.   
  16. public class AESTest {  
  17.     public static void main(String args[]){  
  18.         String content = "test";  
  19.         String password = "12345678";  
  20.         //加密  
  21.         System.out.println("加密前:" + content);  
  22.         byte[] encryptResult = encrypt(content, password);  
  23.         System.out.println("加密后:" + parseByte2HexStr(encryptResult));  
  24.         //解密  
  25.         byte[] decryptResult = decrypt(encryptResult,password);  
  26.         System.out.println("解密后:" + new String(decryptResult));  
  27.     }  
  28.       
  29.     /** 
  30.      * 加密 
  31.      *  
  32.      * @param content 需要加密的内容 
  33.      * @param password  加密密码 
  34.      * @return 
  35.      */  
  36.     public static byte[] encrypt(String content, String password) {  
  37.             try {             
  38.                     KeyGenerator kgen = KeyGenerator.getInstance("AES");  
  39.                     kgen.init(128new SecureRandom(password.getBytes()));  
  40.                     SecretKey secretKey = kgen.generateKey();  
  41.                     byte[] enCodeFormat = secretKey.getEncoded();  
  42.                     SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");  
  43.                     Cipher cipher = Cipher.getInstance("AES");// 创建密码器  
  44.                     byte[] byteContent = content.getBytes("utf-8");  
  45.                     cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化  
  46.                     byte[] result = cipher.doFinal(byteContent);  
  47.                     return result; // 加密  
  48.             } catch (NoSuchAlgorithmException e) {  
  49.                     e.printStackTrace();  
  50.             } catch (NoSuchPaddingException e) {  
  51.                     e.printStackTrace();  
  52.             } catch (InvalidKeyException e) {  
  53.                     e.printStackTrace();  
  54.             } catch (UnsupportedEncodingException e) {  
  55.                     e.printStackTrace();  
  56.             } catch (IllegalBlockSizeException e) {  
  57.                     e.printStackTrace();  
  58.             } catch (BadPaddingException e) {  
  59.                     e.printStackTrace();  
  60.             }  
  61.             return null;  
  62.     }  
  63.       
  64.     /**解密 
  65.      * @param content  待解密内容 
  66.      * @param password 解密密钥 
  67.      * @return 
  68.      */  
  69.     public static byte[] decrypt(byte[] content, String password) {  
  70.             try {  
  71.                      KeyGenerator kgen = KeyGenerator.getInstance("AES");  
  72.                      kgen.init(128new SecureRandom(password.getBytes()));  
  73.                      SecretKey secretKey = kgen.generateKey();  
  74.                      byte[] enCodeFormat = secretKey.getEncoded();  
  75.                      SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");              
  76.                      Cipher cipher = Cipher.getInstance("AES");// 创建密码器  
  77.                     cipher.init(Cipher.DECRYPT_MODE, key);// 初始化  
  78.                     byte[] result = cipher.doFinal(content);  
  79.                     return result; // 加密  
  80.             } catch (NoSuchAlgorithmException e) {  
  81.                     e.printStackTrace();  
  82.             } catch (NoSuchPaddingException e) {  
  83.                     e.printStackTrace();  
  84.             } catch (InvalidKeyException e) {  
  85.                     e.printStackTrace();  
  86.             } catch (IllegalBlockSizeException e) {  
  87.                     e.printStackTrace();  
  88.             } catch (BadPaddingException e) {  
  89.                     e.printStackTrace();  
  90.             }  
  91.             return null;  
  92.     }  
  93.       
  94.     /**将二进制转换成16进制 
  95.      * @param buf 
  96.      * @return 
  97.      */  
  98.     public static String parseByte2HexStr(byte buf[]) {  
  99.             StringBuffer sb = new StringBuffer();  
  100.             for (int i = 0; i < buf.length; i++) {  
  101.                     String hex = Integer.toHexString(buf[i] & 0xFF);  
  102.                     if (hex.length() == 1) {  
  103.                             hex = '0' + hex;  
  104.                     }  
  105.                     sb.append(hex.toUpperCase());  
  106.             }  
  107.             return sb.toString();  
  108.     }  
  109.       
  110.     /**将16进制转换为二进制 
  111.      * @param hexStr 
  112.      * @return 
  113.      */  
  114.     public static byte[] parseHexStr2Byte(String hexStr) {  
  115.             if (hexStr.length() < 1)  
  116.                     return null;  
  117.             byte[] result = new byte[hexStr.length()/2];  
  118.             for (int i = 0;i< hexStr.length()/2; i++) {  
  119.                     int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);  
  120.                     int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);  
  121.                     result[i] = (byte) (high * 16 + low);  
  122.             }  
  123.             return result;  
  124.     }  
  125. }  
这个代码里面,输入的“密钥”是12345678,依然还能加密和解密成功

12345678只有64位,AES的密钥不是最低要求128位吗,为什么依旧能加密功能呢?

原因就出在下面这段代码上:

[java]  view plain  copy
  1. KeyGenerator kgen = KeyGenerator.getInstance("AES");  
  2. kgen.init(128new SecureRandom(password.getBytes()));  
  3. SecretKey secretKey = kgen.generateKey();  
  4. byte[] enCodeFormat = secretKey.getEncoded();  
java里面每个加密算法都有一个keyGenerator ,里面主要是用来生成随机密钥的。

别的算法没有研究过,AES算法中SecureRandom使用的算法是SHA1PRNG

[java]  view plain  copy
  1.        System.out.println("KeyGenerator 结果:");  
  2.        try {  
  3.         KeyGenerator kgen = KeyGenerator.getInstance("AES");  
  4.         kgen.init(128new SecureRandom(password.getBytes()));  
  5.         SecretKey secretKey = kgen.generateKey();  
  6.         byte[] enCodeFormat = secretKey.getEncoded();  
  7.         for (int i = 0; i < enCodeFormat.length; i++) {  
  8.             System.out.print(" "+enCodeFormat[i]);  
  9.         }             
  10.     } catch (NoSuchAlgorithmException e) {  
  11.         // TODO Auto-generated catch block  
  12.         e.printStackTrace();  
  13.     }  
  14. System.out.println();  
  15. System.out.println("SecureRandom 结果:");  
  16. try {  
  17.         SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");  
  18.         sr.setSeed(password.getBytes());  
  19.         byte[] keyByte = new byte[16];  
  20.         sr.nextBytes(keyByte);  
  21.         for (int i = 0; i < keyByte.length; i++) {  
  22.             System.out.print(" "+keyByte[i]);  
  23.         }  
  24.     } catch (NoSuchAlgorithmException e) {  
  25.         // TODO Auto-generated catch block  
  26.         e.printStackTrace();  
  27.     }  
输出结果如下:

[java]  view plain  copy
  1. KeyGenerator 结果:  
  2.  -47 6 101 -53 -53 -88 -29 -12 68 -93 -1 -77 22 -102 87 23  
  3. SecureRandom 结果:  
  4.  -47 6 101 -53 -53 -88 -29 -12 68 -93 -1 -77 22 -102 87 23  

这说明AES就是调用了SecureRandom的nextBytes方法来实现密钥填充的。

用Delphi来实现SecureRandom,太过复杂,也没有必要,我们只要保证加密的时候密钥填充方式一致,加密的结果肯定也会一样的。

于是,Delphi和Java的密钥填充就都定为密钥不够就补零。

网上还有一些人说加密解密中文出现乱码,这个应该注意加密和解密的编码格式,我电脑上面java文件的编码格式是GBK,Delphi的版本是Delphi7,编码格式也是GBK,这样就没有中文乱码问题了。

java和Delphi通用的加密和解密,代码下载地址:http://download.csdn.net/detail/kunlun122/7539147

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值