Android和C#之间的encryption兼容

我已经发现了很多例子,如何在C#中进行encryption,还有一些适用于Android的encryption,但是我特别想find一种方法来处理来自Android的encryption(使用诸如AES,TripleDES等),最终结束在C#中解密。 我发现了一个在Android中编码AES和在C#中编码/解码AES的例子,但是我不确定它们是否兼容(C#需要IV,在Android例子中没有指定这个)。 此外,对编码encryptionstring以通过HTTP传输(Base64?)的好方法的build议将会有所帮助。 谢谢。

Solutions Collecting From Web of "Android和C#之间的encryption兼容"

http://oogifu.blogspot.com/2009/01/aes-in-java-and-c.html得到一些帮助。

这是我的Java类:

package com.neocodenetworks.smsfwd; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; import android.util.Log; public class Crypto { public static final String TAG = "smsfwd"; private static Cipher aesCipher; private static SecretKey secretKey; private static IvParameterSpec ivParameterSpec; private static String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding"; private static String CIPHER_ALGORITHM = "AES"; // Replace me with a 16-byte key, share between Java and C# private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; private static String MESSAGEDIGEST_ALGORITHM = "MD5"; public Crypto(String passphrase) { byte[] passwordKey = encodeDigest(passphrase); try { aesCipher = Cipher.getInstance(CIPHER_TRANSFORMATION); } catch (NoSuchAlgorithmException e) { Log.e(TAG, "No such algorithm " + CIPHER_ALGORITHM, e); } catch (NoSuchPaddingException e) { Log.e(TAG, "No such padding PKCS5", e); } secretKey = new SecretKeySpec(passwordKey, CIPHER_ALGORITHM); ivParameterSpec = new IvParameterSpec(rawSecretKey); } public String encryptAsBase64(byte[] clearData) { byte[] encryptedData = encrypt(clearData); return net.iharder.base64.Base64.encodeBytes(encryptedData); } public byte[] encrypt(byte[] clearData) { try { aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec); } catch (InvalidKeyException e) { Log.e(TAG, "Invalid key", e); return null; } catch (InvalidAlgorithmParameterException e) { Log.e(TAG, "Invalid algorithm " + CIPHER_ALGORITHM, e); return null; } byte[] encryptedData; try { encryptedData = aesCipher.doFinal(clearData); } catch (IllegalBlockSizeException e) { Log.e(TAG, "Illegal block size", e); return null; } catch (BadPaddingException e) { Log.e(TAG, "Bad padding", e); return null; } return encryptedData; } private byte[] encodeDigest(String text) { MessageDigest digest; try { digest = MessageDigest.getInstance(MESSAGEDIGEST_ALGORITHM); return digest.digest(text.getBytes()); } catch (NoSuchAlgorithmException e) { Log.e(TAG, "No such algorithm " + MESSAGEDIGEST_ALGORITHM, e); } return null; } } 

我使用http://iharder.sourceforge.net/current/java/base64/进行base64编码。

这是我的C#类:

 using System; using System.Text; using System.Security.Cryptography; namespace smsfwdClient { public class Crypto { private ICryptoTransform rijndaelDecryptor; // Replace me with a 16-byte key, share between Java and C# private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; public Crypto(string passphrase) { byte[] passwordKey = encodeDigest(passphrase); RijndaelManaged rijndael = new RijndaelManaged(); rijndaelDecryptor = rijndael.CreateDecryptor(passwordKey, rawSecretKey); } public string Decrypt(byte[] encryptedData) { byte[] newClearData = rijndaelDecryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length); return Encoding.ASCII.GetString(newClearData); } public string DecryptFromBase64(string encryptedBase64) { return Decrypt(Convert.FromBase64String(encryptedBase64)); } private byte[] encodeDigest(string text) { MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] data = Encoding.ASCII.GetBytes(text); return x.ComputeHash(data); } } } 

我真的希望这可以帮助别人!

在提供的c#源代码示例中,请注意以下行:

 Encoding.ASCII.GetString(newClearData); 

UTF-8是Android的默认编码,所以encryption的string(特别是非ASCII字符,如中文)将被传递给C#,并假定为UTF-8。 如果使用ASCII编码将其解码回string,则文本将变为混乱状态。 这是一个更好的,

 Encoding.UTF8.GetString(newClearData); 

谢谢!

是的,它应该没问题,只要我们的密钥大小相同 – 128位AES和正确的分组密码模式(CBC)。 你可能会遇到填充问题,但这应该很容易理解。 我最近遇到了Java和Python的这些问题,但最终都让一切工作。 用于编码的Base64应该可以通过HTTP进行处理。 祝你好运!

如果在两端正确实现了相同的密码(如AES)和模式(如CTR,CFB,CCM等),则不论平台如何,一端的密文都可以被另一端解密。

您链接到的Android示例似乎使用ECB模式,因此对于您的目的不安全。 了解所选模块模式的含义至关重要。 在这个级别上encryption是非常容易的,导致一个系统的安全性不如你想象的那么高。

编辑:我拿回来,它不使用欧洲央行,但它产生的方式是不实际的。 无论如何,我关于理解块模式的含义的观点是。

你可以从这个维基百科文章开始。 Bruce Schneier的书“ 实用密码学”对于任何实施密码安全的人来说都是非常有价值的。

至于编码的string,如果你必须将string转换成ASCII文本Base64是一样好的方式,但我build议你调查HTTP PUT或POST的使用,让你这个额外的步骤。

互联网上的大多数例子都是AES的弱执行。 对于一个强大的实现,应该随时使用IV,密钥应该被散列。

为了更安全(随机IV +散列键)跨平台(android,ios,c#)AES的实现,请参阅我的答案 – https://stackoverflow.com/a/24561148/2480840