Android 从 C# 到 Java 的 AES 加密
Android AES Encryption from C# to Java
我正在将我的 C# 加密代码转换为 Android。
我遇到了无法像 C# 那样加密文本的问题。
下面我复制粘贴这两个代码。
两者都是关于使用它的工作代码,您可以使用任何密码和任何纯文本。您会发现两者都有不同的输出。
C# 代码
System.security.Cryptography.RijndaelManaged AES = new System.Security.Cryptography.RijndaelManaged();
System.Security.Cryptography.MD5CryptoServiceProvider Hash_AES = new System.Security.Cryptography.MD5CryptoServiceProvider();
final MessageDigest Hash_AES = MessageDigest.getInstance("MD5");
String encrypted = "";
try {
byte[] hash = new byte[32];
byte[] temp = Hash_AES.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(pass));
final byte[] temp = Hash_AES.digest(pass.getBytes("US-ASCII"));
Array.Copy(temp, 0, hash, 0, 16);
Array.Copy(temp, 0, hash, 15, 16);
AES.Key = hash;
AES.Mode = System.Security.Cryptography.CipherMode.ECB;
System.Security.Cryptography.ICryptoTransform DESEncrypter = AES.CreateEncryptor();
byte[] Buffer = System.Text.ASCIIEncoding.ASCII.GetBytes(input);
encrypted = Convert.ToBase64String(DESEncrypter.TransformFinalBlock(Buffer, 0, Buffer.Length));
} catch (Exception ex) {
}
return encrypted;
这是我的 Android java 代码。
ANDROID JAVA 代码
private static String TRANSFORMATION = "AES/ECB/NoPadding";
private static String ALGORITHM = "AES";
private static String DIGEST = "MD5";
byte[] encryptedData;
public RijndaelCrypt(String password,String plainText) {
try {
//Encode digest
MessageDigest digest;
digest = MessageDigest.getInstance(DIGEST);
_password = new SecretKeySpec(digest.digest(password.getBytes()), ALGORITHM);
//Initialize objects
_cipher = Cipher.getInstance(TRANSFORMATION);
_cipher.init(Cipher.ENCRYPT_MODE, _password);
encryptedData = _cipher.doFinal(text);
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key (invalid encoding, wrong length, uninitialized, etc).", e);
return null;
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, "Invalid or inappropriate algorithm parameters for " + ALGORITHM, e);
return null;
} catch (IllegalBlockSizeException e) {
Log.e(TAG, "The length of data provided to a block cipher is incorrect", e);
return null;
} catch (BadPaddingException e) {
Log.e(TAG, "The input data but the data is not padded properly.", e);
return null;
}
return Base64.encodeToString(encryptedData,Base64.DEFAULT);
}
我应该在 pass 中使用 "US-ASCII" 还是需要它?
- 使用相同的操作模式:ECB 或 CBC
- 使用相同的字符集:最好坚持"UTF-8"
- 使用相同的密钥:在 C# 代码中,您将 128 位密钥加倍为 256 位
使用带有随机 IV 的 CBC 时,预期密文对于相同的明文是不同的。解密是决定你是否成功的操作。
请注意,ECB 在语义上并不安全。使用带有随机 IV 的 CBC。 IV 不必是秘密的,因此您可以将它添加到密文前面并在解密之前将其切掉。
最好使用像 GCM 或 EAX 这样的身份验证模式,或者如果它没有提供加密然后-MAC 方案。自己很难正确地实现它,所以坚持使用一些为你做这件事的库,比如 RNCryptor。
我正在将我的 C# 加密代码转换为 Android。
我遇到了无法像 C# 那样加密文本的问题。 下面我复制粘贴这两个代码。
两者都是关于使用它的工作代码,您可以使用任何密码和任何纯文本。您会发现两者都有不同的输出。
C# 代码
System.security.Cryptography.RijndaelManaged AES = new System.Security.Cryptography.RijndaelManaged();
System.Security.Cryptography.MD5CryptoServiceProvider Hash_AES = new System.Security.Cryptography.MD5CryptoServiceProvider();
final MessageDigest Hash_AES = MessageDigest.getInstance("MD5");
String encrypted = "";
try {
byte[] hash = new byte[32];
byte[] temp = Hash_AES.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(pass));
final byte[] temp = Hash_AES.digest(pass.getBytes("US-ASCII"));
Array.Copy(temp, 0, hash, 0, 16);
Array.Copy(temp, 0, hash, 15, 16);
AES.Key = hash;
AES.Mode = System.Security.Cryptography.CipherMode.ECB;
System.Security.Cryptography.ICryptoTransform DESEncrypter = AES.CreateEncryptor();
byte[] Buffer = System.Text.ASCIIEncoding.ASCII.GetBytes(input);
encrypted = Convert.ToBase64String(DESEncrypter.TransformFinalBlock(Buffer, 0, Buffer.Length));
} catch (Exception ex) {
}
return encrypted;
这是我的 Android java 代码。
ANDROID JAVA 代码
private static String TRANSFORMATION = "AES/ECB/NoPadding";
private static String ALGORITHM = "AES";
private static String DIGEST = "MD5";
byte[] encryptedData;
public RijndaelCrypt(String password,String plainText) {
try {
//Encode digest
MessageDigest digest;
digest = MessageDigest.getInstance(DIGEST);
_password = new SecretKeySpec(digest.digest(password.getBytes()), ALGORITHM);
//Initialize objects
_cipher = Cipher.getInstance(TRANSFORMATION);
_cipher.init(Cipher.ENCRYPT_MODE, _password);
encryptedData = _cipher.doFinal(text);
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key (invalid encoding, wrong length, uninitialized, etc).", e);
return null;
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, "Invalid or inappropriate algorithm parameters for " + ALGORITHM, e);
return null;
} catch (IllegalBlockSizeException e) {
Log.e(TAG, "The length of data provided to a block cipher is incorrect", e);
return null;
} catch (BadPaddingException e) {
Log.e(TAG, "The input data but the data is not padded properly.", e);
return null;
}
return Base64.encodeToString(encryptedData,Base64.DEFAULT);
}
我应该在 pass 中使用 "US-ASCII" 还是需要它?
- 使用相同的操作模式:ECB 或 CBC
- 使用相同的字符集:最好坚持"UTF-8"
- 使用相同的密钥:在 C# 代码中,您将 128 位密钥加倍为 256 位
使用带有随机 IV 的 CBC 时,预期密文对于相同的明文是不同的。解密是决定你是否成功的操作。
请注意,ECB 在语义上并不安全。使用带有随机 IV 的 CBC。 IV 不必是秘密的,因此您可以将它添加到密文前面并在解密之前将其切掉。
最好使用像 GCM 或 EAX 这样的身份验证模式,或者如果它没有提供加密然后-MAC 方案。自己很难正确地实现它,所以坚持使用一些为你做这件事的库,比如 RNCryptor。