Java aes加密C#解密的取巧方法
项目开发过程中遇到一个棘手的问题:A系统使用java开发,通过AES加密数据,B系统使用C#开发,需要从A系统获取数据,但在AES解密的时候遇到麻烦。Java的代码和C#的代码无法互通。
Java代码:
- /**
- *加密
- *
- *@paramcontent需要加密的内容
- *@parampassword加密密钥
- *@return
- */
- publicstaticStringencrypt(Stringcontent,Stringpassword){
- try{
- //如下代码用于根据原始的password生成加密的key,这段代码C#是没有对应的实现的
- KeyGeneratorkgen=KeyGenerator.getInstance("AES");
- java.security.SecureRandomrandom=java.security.SecureRandom.getInstance("SHA1PRNG");
- random.setSeed(password.getBytes());
- kgen.init(128,random);
- SecretKeysecretKey=kgen.generateKey();
- byte[]enCodeFormat=secretKey.getEncoded();
- //如下代码是标准的AES加密处理,C#可以实现
- SecretKeySpeckey=newSecretKeySpec(enCodeFormat,"AES");
- Ciphercipher=Cipher.getInstance("AES");
- byte[]byteContent=content.getBytes("utf-8");
- cipher.init(Cipher.ENCRYPT_MODE,key);
- returnCodec.encodeBASE64(cipher.doFinal(byteContent));
- }catch(Exceptione){
- Logger.error(e,"AES加密异常");
- }
- returnnull;
- }
网上找了一些资料,没有找到满意的解决方案,于是尝试了一种取巧的方法,具体实现如下:
1)将Java中key的处理代码抽取出来,写成一个简单的工具类,类名为TestGenAESByteKey。
TestGenAESByteKey将原始的password转换为AES加密需要的字节,然后Base64编码,得到字符串
2)将以上步骤得到的字符串通过人工的方式拷贝到C#的代码中,作为秘钥解密
具体代码如下:
TestGenAESByteKey(Java语言)
- packageapi;
- importjava.io.UnsupportedEncodingException;
- importjava.security.NoSuchAlgorithmException;
- importjavax.crypto.KeyGenerator;
- importjavax.crypto.SecretKey;
- importsun.misc.BASE64Encoder;
- publicclassTestGenAESByteKey{
- /**
- *@paramargs
- *@throwsUnsupportedEncodingException
- *@throwsNoSuchAlgorithmException
- */
- publicstaticvoidmain(String[]args)throwsUnsupportedEncodingException,NoSuchAlgorithmException{
- KeyGeneratorkgen=KeyGenerator.getInstance("AES");
- java.security.SecureRandomrandom=java.security.SecureRandom.getInstance("SHA1PRNG");
- random.setSeed(args[0].getBytes());
- kgen.init(128,random);
- SecretKeysecretKey=kgen.generateKey();
- byte[]enCodeFormat=secretKey.getEncoded();
- BASE64Encodercoder=newBASE64Encoder();
- System.out.println(coder.encode(enCodeFormat));
- }
- }
C#的解密代码:
- publicstaticstringdecrypt(stringtoDecrypt,stringkey)
- {
- byte[]keyArray=Convert.FromBase64String(key);//将TestGenAESByteKey类输出的字符串转为byte数组
- byte[]toEncryptArray=Convert.FromBase64String(toDecrypt);
- RijndaelManagedrDel=newRijndaelManaged();
- rDel.Key=keyArray;
- rDel.Mode=CipherMode.ECB;//必须设置为ECB
- rDel.Padding=PaddingMode.PKCS7;//必须设置为PKCS7
- ICryptoTransformcTransform=rDel.CreateDecryptor();
- byte[]resultArray=cTransform.TransformFinalBlock(toEncryptArray,0,toEncryptArray.Length);
- returnUTF8Encoding.UTF8.GetString(resultArray);
- }
例如:原始密码为123456,经过TestGenAESByteKey处理后,输出a7SDfrdDKRBe5FaN2n3Gfg==
将a7SDfrdDKRBe5FaN2n3Gfg==作为C#函数decrypt的key参数的值传进去,就可以正常解码了
需要注意几点:
1)C#默认运算模式为CBC,java默认为ECB,因此要将C#的加密方式改为ECB
2)C#的Padding方式要设置为PaddingMode.PKCS7,否则解密出来后结尾可能有乱码
浙公网安备 33010602011771号