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

         Java刚学不久,很多东西都不知道,走了很多弯路。

         最近项目要用AES加密算法,服务端是Java,客户端是Delphi。网上找了很多AES算法的代码,单独加密和解密都可以,一旦交互加密解密就不行了,例如:Java加密,用Delphi就解密不了。

网上找到的Java端AES代码如下:

[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. }  


java端结果如下:

[java]  view plain  copy
  1. 加密前:test  
  2. 加密后:73C58BAFE578C59366D8C995CD0B9D6D  
  3. 解密后:test  


网上找到的delphi端AES代码就很少了,主要是用ELAES.pas来加解密的,以128bit加密为例:

[delphi]  view plain  copy
  1. {  --  字符串加密函数 默认按照 128 位密匙加密 --  }  
  2. function EncryptString(Value: string; Key: string;  
  3.   KeyBit: TKeyBit = kb128): string;  
  4. var  
  5.   SS, DS: TStringStream;  
  6.   Size: Int64;  
  7.   AESKey128: TAESKey128;  
  8.   AESKey192: TAESKey192;  
  9.   AESKey256: TAESKey256;  
  10. begin  
  11.   Result := '';  
  12.   SS := TStringStream.Create(Value);  
  13.   DS := TStringStream.Create('');  
  14.   try  
  15.     Size := SS.Size;  
  16.     DS.WriteBuffer(Size, SizeOf(Size));  
  17.     {  --  128 位密匙最大长度为 16 个字符 --  }  
  18.     if KeyBit = kb128 then  
  19.     begin  
  20.       FillChar(AESKey128, SizeOf(AESKey128), 0 );  
  21.       Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));  
  22.       EncryptAESStreamECB(SS, 0, AESKey128, DS);  
  23.     end;  
  24.     {  --  192 位密匙最大长度为 24 个字符 --  }  
  25.     if KeyBit = kb192 then  
  26.     begin  
  27.       FillChar(AESKey192, SizeOf(AESKey192), 0 );  
  28.       Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));  
  29.       EncryptAESStreamECB(SS, 0, AESKey192, DS);  
  30.     end;  
  31.     {  --  256 位密匙最大长度为 32 个字符 --  }  
  32.     if KeyBit = kb256 then  
  33.     begin  
  34.       FillChar(AESKey256, SizeOf(AESKey256), 0 );  
  35.       Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));  
  36.       EncryptAESStreamECB(SS, 0, AESKey256, DS);  
  37.     end;  
  38.     Result := StrToHex(DS.DataString);  
  39.   finally  
  40.     SS.Free;  
  41.     DS.Free;  
  42.   end;  
  43. end;  
  44.   
  45. {  --  字符串解密函数 默认按照 128 位密匙解密 --  }  
  46. function DecryptString(Value: string; Key: string;  
  47.   KeyBit: TKeyBit = kb128): string;  
  48. var  
  49.   SS, DS: TStringStream;  
  50.   Size: Int64;  
  51.   AESKey128: TAESKey128;  
  52.   AESKey192: TAESKey192;  
  53.   AESKey256: TAESKey256;  
  54. begin  
  55.   Result := '';  
  56.   SS := TStringStream.Create(HexToStr(Value));  
  57.   DS := TStringStream.Create('');  
  58.   try  
  59.     Size := SS.Size;  
  60.     SS.ReadBuffer(Size, SizeOf(Size));  
  61.     {  --  128 位密匙最大长度为 16 个字符 --  }  
  62.     if KeyBit = kb128 then  
  63.     begin  
  64.       FillChar(AESKey128, SizeOf(AESKey128), 0 );  
  65.       Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));  
  66.       DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey128, DS);  
  67.     end;  
  68.     {  --  192 位密匙最大长度为 24 个字符 --  }  
  69.     if KeyBit = kb192 then  
  70.     begin  
  71.       FillChar(AESKey192, SizeOf(AESKey192), 0 );  
  72.       Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));  
  73.       DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey192, DS);  
  74.     end;  
  75.     {  --  256 位密匙最大长度为 32 个字符 --  }  
  76.     if KeyBit = kb256 then  
  77.     begin  
  78.       FillChar(AESKey256, SizeOf(AESKey256), 0 );  
  79.       Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));  
  80.       DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey256, DS);  
  81.     end;  
  82.     Result := DS.DataString;  
  83.   finally  
  84.     SS.Free;  
  85.     DS.Free;  
  86.   end;  
  87. end;  
delphi结果如下:

[delphi]  view plain  copy
  1. 加密前:test  
  2. 加密后:0400000000000000C83DC726BB173EA77305C62E92892F51  
  3. 解密后:test  
通过以上结果对比,同样的“明文”和“密钥”,加密后的密文不一样,密文不一样,当然不能互相加密解密。

由于delphi关于AES可用代码太少,就先从java下手,首先要了解Java默认的AES加密模式和填充模式是哪一种?

[plain]  view plain  copy
  1. AES加密模式和填充方式()  
  2. 01 算法/模式/填充                16字节加密后数据长度        不满16字节加密后长度  
  3. 02 AES/CBC/NoPadding             16                          不支持  
  4. 03 AES/CBC/PKCS5Padding          32                          16  
  5. 04 AES/CBC/ISO10126Padding       32                          16  
  6. 05 AES/CFB/NoPadding             16                          原始数据长度  
  7. 06 AES/CFB/PKCS5Padding          32                          16  
  8. 07 AES/CFB/ISO10126Padding       32                          16  
  9. 08 AES/ECB/NoPadding             16                          不支持  
  10. 09 AES/ECB/PKCS5Padding          32                          16  
  11. 10 AES/ECB/ISO10126Padding       32                          16  
  12. 11 AES/OFB/NoPadding             16                          原始数据长度  
  13. 12 AES/OFB/PKCS5Padding          32                          16  
  14. 13 AES/OFB/ISO10126Padding       32                          16  
  15. 14 AES/PCBC/NoPadding            16                          不支持  
  16. 15 AES/PCBC/PKCS5Padding         32                          16  
  17. 16 AES/PCBC/ISO10126Padding      32                          16  
  18. 更多关于加密模式内容:http://blog.sina.com.cn/s/blog_679daa6b0100zmpp.html  
此处参考地址: http://www.2cto.com/kf/201211/165570.html
由于java刚学不久,很多东西不知道,加了好几个java群和算法群,都没人搭理我,没办法,笨人笨办法,直接看与AES算法有关的java源码了,主要的jar包是javax.crypto和com.sun.crypto.provider。推荐一个网站,这个网站能在线看源码: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/com/sun/crypto/provider/AESCipher.java?av=f

表示很笨,看了很久,才知道AES默认的加密和填充模式是AES/ECB/PKCS5Padding

后来自己也测试了一下

[java]  view plain  copy
  1. Cipher cipher = Cipher.getInstance("AES");// 创建密码器  
[java]  view plain  copy
  1. Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器  
这二者加密出来的结果一样。

继续查找资料,发现了一个AES在线加密网站:http://www.seacha.com/tools/aes.html?src=test&mode=ECB&keylen=128&key=12345678&iv=&bpkcs=pkcs5padding&session=5jusjIojNQIZIKIGNBV4&aes=ec354375b36ae7401c19d4bdb5cb8822&encoding=hex&type=0

心想,在线加密网站应该是标准的AES算法,就开始向网站靠拢。

我用使用的加密方式是128bit的,由于不知道在线网站密钥的填充方式,就直接把密钥定位1234567812345678,正好128bit,这样就不会有密钥填充了。

明文:test

密钥:1234567812345678

网站加密后的结果是

[plain]  view plain  copy
  1. ba572c602f340fd8be26038a0b79f107  

 

Java加密后的结果是

[plain]  view plain  copy
  1. 加密前:test  
  2. 加密后:B4598BD96E21C84575FB86FB6CB64D19  
  3. 解密后:test</span>  
    

和java端还是不一样,继续看java代码,查找资料。网上找了好久,突然在csdn上看到这么一句话,Java中AES算法的实现肯定是标准的,要看看加密模式、填充模式、明文和密钥一不一样。一语惊醒梦中人,赶紧检查java代码,发现java端在生成密钥的时候,用了SecureRandom,加密前特地把密钥输出出来一看,果然和之前的不一样。坑爹啊!问题竟然出现在这儿,赶紧把这段代码屏蔽。

修正后的代码如下:

[java]  view plain  copy
  1. /** 
  2.      * 加密 
  3.      *  
  4.      * @param content 需要加密的内容 
  5.      * @param password  加密密码 
  6.      * @return 
  7.      */  
  8.     public static byte[] encrypt(String content, String password) {  
  9.             try {             
  10.                     /*KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
  11.                     kgen.init(128, new SecureRandom(password.getBytes())); 
  12.                     SecretKey secretKey = kgen.generateKey(); 
  13.                     byte[] enCodeFormat = secretKey.getEncoded(); 
  14.                     SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");*/  
  15.                     SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");  
  16.                     Cipher cipher = Cipher.getInstance("AES");// 创建密码器  
  17.                     byte[] byteContent = content.getBytes("utf-8");  
  18.                     cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化  
  19.                     byte[] result = cipher.doFinal(byteContent);  
  20.                     return result; // 加密  
  21.             } catch (NoSuchAlgorithmException e) {  
  22.                     e.printStackTrace();  
  23.             } catch (NoSuchPaddingException e) {  
  24.                     e.printStackTrace();  
  25.             } catch (InvalidKeyException e) {  
  26.                     e.printStackTrace();  
  27.             } catch (UnsupportedEncodingException e) {  
  28.                     e.printStackTrace();  
  29.             } catch (IllegalBlockSizeException e) {  
  30.                     e.printStackTrace();  
  31.             } catch (BadPaddingException e) {  
  32.                     e.printStackTrace();  
  33.             }  
  34.             return null;  
  35.     }  
  36.       
  37.     /**解密 
  38.      * @param content  待解密内容 
  39.      * @param password 解密密钥 
  40.      * @return 
  41.      */  
  42.     public static byte[] decrypt(byte[] content, String password) {  
  43.             try {  
  44.                      /*KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
  45.                      kgen.init(128, new SecureRandom(password.getBytes())); 
  46.                      SecretKey secretKey = kgen.generateKey(); 
  47.                      byte[] enCodeFormat = secretKey.getEncoded(); 
  48.                      SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");*/   
  49.                      SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");  
  50.                      Cipher cipher = Cipher.getInstance("AES");// 创建密码器  
  51.                     cipher.init(Cipher.DECRYPT_MODE, key);// 初始化  
  52.                     byte[] result = cipher.doFinal(content);  
  53.                     return result; // 加密  
  54.             } catch (NoSuchAlgorithmException e) {  
  55.                     e.printStackTrace();  
  56.             } catch (NoSuchPaddingException e) {  
  57.                     e.printStackTrace();  
  58.             } catch (InvalidKeyException e) {  
  59.                     e.printStackTrace();  
  60.             } catch (IllegalBlockSizeException e) {  
  61.                     e.printStackTrace();  
  62.             } catch (BadPaddingException e) {  
  63.                     e.printStackTrace();  
  64.             }  
  65.             return null;  
  66.     }  

加密后的结果:

[java]  view plain  copy
  1. 加密前:test  
  2. 加密后:BA572C602F340FD8BE26038A0B79F107  
  3. 解密后:test  

终于和网站加密的结果一样了,感觉这几天的努力没白费啊,终于有点小成果,看到胜利的曙光了。

搞定Java后,开始研究Delphi,delphi关于AES的代码好少,基本上都是AES.pas和ELAES.pas,资料只有多了,只能自己摸索了。

首先,delphi加密出来的密文长度比java加密出来的长,这肯定是不正常的,查看AES.pas发现加解密的时候,把明文的长度也写进去了,把这句代码屏蔽。

修改后的代码如下:

[delphi]  view plain  copy
  1. {  --  字符串加密函数 默认按照 128 位密匙加密 --  }  
  2. function EncryptString(Value: string; Key: string;  
  3.   KeyBit: TKeyBit = kb128): string;  
  4. var  
  5.   SS, DS: TStringStream;  
  6.   Size: Int64;  
  7.   AESKey128: TAESKey128;  
  8.   AESKey192: TAESKey192;  
  9.   AESKey256: TAESKey256;  
  10. begin  
  11.   Result := '';  
  12.   SS := TStringStream.Create(Value);  
  13.   DS := TStringStream.Create('');  
  14.   try  
  15.     //Size := SS.Size;  
  16.     //DS.WriteBuffer(Size, SizeOf(Size));  
  17.     {  --  128 位密匙最大长度为 16 个字符 --  }  
  18.     if KeyBit = kb128 then  
  19.     begin  
  20.       FillChar(AESKey128, SizeOf(AESKey128), 0 );  
  21.       Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));  
  22.       EncryptAESStreamECB(SS, 0, AESKey128, DS);  
  23.     end;  
  24.     {  --  192 位密匙最大长度为 24 个字符 --  }  
  25.     if KeyBit = kb192 then  
  26.     begin  
  27.       FillChar(AESKey192, SizeOf(AESKey192), 0 );  
  28.       Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));  
  29.       EncryptAESStreamECB(SS, 0, AESKey192, DS);  
  30.     end;  
  31.     {  --  256 位密匙最大长度为 32 个字符 --  }  
  32.     if KeyBit = kb256 then  
  33.     begin  
  34.       FillChar(AESKey256, SizeOf(AESKey256), 0 );  
  35.       Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));  
  36.       EncryptAESStreamECB(SS, 0, AESKey256, DS);  
  37.     end;  
  38.     Result := StrToHex(DS.DataString);  
  39.   finally  
  40.     SS.Free;  
  41.     DS.Free;  
  42.   end;  
  43. end;  
  44.   
  45. {  --  字符串解密函数 默认按照 128 位密匙解密 --  }  
  46. function DecryptString(Value: string; Key: string;  
  47.   KeyBit: TKeyBit = kb128): string;  
  48. var  
  49.   SS, DS: TStringStream;  
  50.   Size: Int64;  
  51.   AESKey128: TAESKey128;  
  52.   AESKey192: TAESKey192;  
  53.   AESKey256: TAESKey256;  
  54. begin  
  55.   Result := '';  
  56.   SS := TStringStream.Create(HexToStr(Value));  
  57.   DS := TStringStream.Create('');  
  58.   try  
  59.    // Size := SS.Size;  
  60.    // SS.ReadBuffer(Size, SizeOf(Size));  
  61.     {  --  128 位密匙最大长度为 16 个字符 --  }  
  62.     if KeyBit = kb128 then  
  63.     begin  
  64.       FillChar(AESKey128, SizeOf(AESKey128), 0 );  
  65.       Move(PChar(Key)^, AESKey128, Min(SizeOf(AESKey128), Length(Key)));  
  66.       DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey128, DS);  
  67.     end;  
  68.     {  --  192 位密匙最大长度为 24 个字符 --  }  
  69.     if KeyBit = kb192 then  
  70.     begin  
  71.       FillChar(AESKey192, SizeOf(AESKey192), 0 );  
  72.       Move(PChar(Key)^, AESKey192, Min(SizeOf(AESKey192), Length(Key)));  
  73.       DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey192, DS);  
  74.     end;  
  75.     {  --  256 位密匙最大长度为 32 个字符 --  }  
  76.     if KeyBit = kb256 then  
  77.     begin  
  78.       FillChar(AESKey256, SizeOf(AESKey256), 0 );  
  79.       Move(PChar(Key)^, AESKey256, Min(SizeOf(AESKey256), Length(Key)));  
  80.       DecryptAESStreamECB(SS, SS.Size - SS.Position, AESKey256, DS);  
  81.     end;  
  82.     Result := DS.DataString;  
  83.   finally  
  84.     SS.Free;  
  85.     DS.Free;  
  86.   end;  
  87. end;  
修正后,长度正常了,加密结果还是不一样,继续查找delphi关于AES/ECB/PKCS5Padding的资料,找到很久没找到。不过想起之前同事跟我说过的一句话,他那儿有delphi和java下通用的DES算法,AES算是DES算法的升级版啊,对照着看看,应该会有灵感。网上搜了搜,资料还挺好找的,使用的加密和填充方式是DES/ECB/PKCS5Padding,填充方式是PKCS5Padding?正好是我想找的,下载源码,找到了delphi下PKCS5Padding的实现。

PKCS5Padding的实现代码如下:

[delphi]  view plain  copy
  1. type  
  2.   TKeyBit = (kb128, kb192, kb256);  
  3.   TPaddingType = (PKCS5Padding,PKCS7Padding);  
[delphi]  view plain  copy
  1. function StrPadding(SourceStr:string;paddingType:TPaddingType = PKCS5Padding):string;  
  2. var  
  3.  DestStr:string;  
  4.  strRemainder,i:Integer;  
  5. begin  
  6.   DestStr := SourceStr;  
  7.   if paddingType = PKCS5Padding then  
  8.   begin  
  9.     strRemainder :=Length(DestStr) mod 16;  
  10.     strRemainder := 16 - strRemainder;  
  11.     for i:= 1 to strRemainder do  
  12.     begin  
  13.       DestStr := DestStr + Chr(strRemainder);  
  14.     end;  
  15.   end;  
  16.   Result := DestStr;  
  17. end;  
  18.   
  19. function StrDelPadding(SourceStr:string;paddingType:TPaddingType = PKCS5Padding):string;  
  20. var  
  21.  DestStr:string;  
  22.  PaddingLen:Integer;  
  23. begin  
  24.   DestStr := SourceStr;  
  25.   if paddingType = PKCS5Padding then  
  26.   begin  
  27.     PaddingLen :=  Ord(DestStr[Length(DestStr)]);  
  28.     DestStr := Copy(DestStr,1,Length(DestStr)-PaddingLen);  
  29.   end;  
  30.   Result := DestStr;  
  31. end;  
从DES转移到AES的过程中间还有个小插曲,DES的加密块长度是64位,AES是128位,所以填充的时候就发生问题了。

AES的PKCS5Padding的填充规则就是,填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。字符串后面缺多少位,就补多少位所缺字符串的长度。

以test为例,只有4个byte,要补齐到16byte,就要填充12个12。

test补齐前:[116, 101, 115, 116,]

test补齐后:[116, 101, 115, 116, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12]

搞定delphi的PKCS5Padding填充规则之后,运行测试程序,结果如下:

[java]  view plain  copy
  1. 加密前:test  
  2. 加密后:BA572C602F340FD8BE26038A0B79F107  
  3. 解密后:test  

呜呜呜,终于搞定了,测试了一下和java加解密,都能成功。真的搞定了吗?如果密钥不是16位呢,该怎么填充?请看下一篇。

附上这次的Java和Delphi代码,下载地址http://download.csdn.net/detail/kunlun122/7465045

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值