Java aes加密C#解密的取巧方法

项目开发过程中遇到一个棘手的问题:A系统使用java开发,通过AES加密数据,B系统使用C#开发,需要从A系统获取数据,但在AES解密的时候遇到麻烦。Java的代码和C#的代码无法互通。

Java代码:

  1. /**
  2. *加密
  3. *
  4. *@paramcontent需要加密的内容
  5. *@parampassword加密密钥
  6. *@return
  7. */
  8. publicstaticStringencrypt(Stringcontent,Stringpassword){
  9. try{
  10. //如下代码用于根据原始的password生成加密的key,这段代码C#是没有对应的实现的
  11. KeyGeneratorkgen=KeyGenerator.getInstance("AES");
  12. java.security.SecureRandomrandom=java.security.SecureRandom.getInstance("SHA1PRNG");
  13. random.setSeed(password.getBytes());
  14. kgen.init(128,random);
  15. SecretKeysecretKey=kgen.generateKey();
  16. byte[]enCodeFormat=secretKey.getEncoded();
  17.  
  18. //如下代码是标准的AES加密处理,C#可以实现
  19. SecretKeySpeckey=newSecretKeySpec(enCodeFormat,"AES");
  20. Ciphercipher=Cipher.getInstance("AES");
  21. byte[]byteContent=content.getBytes("utf-8");
  22. cipher.init(Cipher.ENCRYPT_MODE,key);
  23. returnCodec.encodeBASE64(cipher.doFinal(byteContent));
  24. }catch(Exceptione){
  25. Logger.error(e,"AES加密异常");
  26. }
  27. returnnull;
  28. }

网上找了一些资料,没有找到满意的解决方案,于是尝试了一种取巧的方法,具体实现如下:

1)将Java中key的处理代码抽取出来,写成一个简单的工具类,类名为TestGenAESByteKey。

TestGenAESByteKey将原始的password转换为AES加密需要的字节,然后Base64编码,得到字符串

2)将以上步骤得到的字符串通过人工的方式拷贝到C#的代码中,作为秘钥解密

具体代码如下:

TestGenAESByteKey(Java语言)

  1. packageapi;
  2.  
  3. importjava.io.UnsupportedEncodingException;
  4. importjava.security.NoSuchAlgorithmException;
  5.  
  6. importjavax.crypto.KeyGenerator;
  7. importjavax.crypto.SecretKey;
  8.  
  9. importsun.misc.BASE64Encoder;
  10.  
  11. publicclassTestGenAESByteKey{
  12.  
  13. /**
  14. *@paramargs
  15. *@throwsUnsupportedEncodingException
  16. *@throwsNoSuchAlgorithmException
  17. */
  18. publicstaticvoidmain(String[]args)throwsUnsupportedEncodingException,NoSuchAlgorithmException{
  19. KeyGeneratorkgen=KeyGenerator.getInstance("AES");
  20. java.security.SecureRandomrandom=java.security.SecureRandom.getInstance("SHA1PRNG");
  21. random.setSeed(args[0].getBytes());
  22. kgen.init(128,random);
  23. SecretKeysecretKey=kgen.generateKey();
  24. byte[]enCodeFormat=secretKey.getEncoded();
  25. BASE64Encodercoder=newBASE64Encoder();
  26.  
  27. System.out.println(coder.encode(enCodeFormat));
  28. }
  29.  
  30. }

C#的解密代码:

  1. publicstaticstringdecrypt(stringtoDecrypt,stringkey)
  2. {
  3. byte[]keyArray=Convert.FromBase64String(key);//将TestGenAESByteKey类输出的字符串转为byte数组
  4. byte[]toEncryptArray=Convert.FromBase64String(toDecrypt);
  5. RijndaelManagedrDel=newRijndaelManaged();
  6. rDel.Key=keyArray;
  7. rDel.Mode=CipherMode.ECB;//必须设置为ECB
  8. rDel.Padding=PaddingMode.PKCS7;//必须设置为PKCS7
  9. ICryptoTransformcTransform=rDel.CreateDecryptor();
  10. byte[]resultArray=cTransform.TransformFinalBlock(toEncryptArray,0,toEncryptArray.Length);
  11. returnUTF8Encoding.UTF8.GetString(resultArray);
  12. }

例如:原始密码为123456,经过TestGenAESByteKey处理后,输出a7SDfrdDKRBe5FaN2n3Gfg==

将a7SDfrdDKRBe5FaN2n3Gfg==作为C#函数decrypt的key参数的值传进去,就可以正常解码了

需要注意几点:

1)C#默认运算模式为CBC,java默认为ECB,因此要将C#的加密方式改为ECB

2)C#的Padding方式要设置为PaddingMode.PKCS7,否则解密出来后结尾可能有乱码

posted on 2015-11-06 11:08  !无名之辈  阅读(2175)  评论(0)    收藏  举报