我找到了很多有关如何在C#中进行加密的示例,也找到了一些Android示例,但我特别想找一种在Android中处理加密(使用AES、TripleDES等)并最终在C#中解密的方法。我在Android中找到了一个编码AES的示例,在C#中发现了编码/解码AES的代码,但不确定它们是否兼容(C#需要一个IV,在Android示例中没有指定)。此外,推荐一种用于通过HTTP传输加密字符串的编码方式(Base64?)会很有帮助。谢谢。
我找到了很多有关如何在C#中进行加密的示例,也找到了一些Android示例,但我特别想找一种在Android中处理加密(使用AES、TripleDES等)并最终在C#中解密的方法。我在Android中找到了一个编码AES的示例,在C#中发现了编码/解码AES的代码,但不确定它们是否兼容(C#需要一个IV,在Android示例中没有指定)。此外,推荐一种用于通过HTTP传输加密字符串的编码方式(Base64?)会很有帮助。谢谢。
我从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);
}
}
}
我真心希望这能帮助到其他人!
Base64
是在API级别8中引入的,该级别是在此答案发布三个月后发布的。 - JessEncoding.ASCII.GetString(newClearData);
UTF-8是Android的默认编码方式,因此加密字符串(尤其是非ASCII字符,例如中文)将作为UTF-8传递到C#。如果使用ASCII编码解码回字符串,文本将变得混乱不堪。下面是更好的方法:
Encoding.UTF8.GetString(newClearData);
谢谢!
没问题,只要密钥长度相同-128位AES和正确的块密码模式(CBC)。 你可能会遇到填充问题,但这应该很容易解决。 我最近在Java和Python中遇到了这些问题,但最终一切都解决了。 在HTTP上使用Base64进行编码应该没问题。 祝好运!
如果你在两端正确实现了相同的密码(如AES)和模式(如CTR,CFB,CCM等),则来自一端的密文可以被另一端解密,而不考虑平台。
你链接的Android示例似乎使用了ECB模式,因此对于你的目的来说并不安全。选择块模式的影响非常重要,你必须理解这一点。在这个层面上很容易出现加密错误,导致系统的安全性不如你想象的那么高。
编辑:我撤回之前的说法,它没有使用ECB,但它生成IV的方式并不实用。无论如何,我的观点是要理解块模式的影响。
你可以从wikipedia文章开始学习。Bruce Schneier的书“Practical Cryptography”对于任何实施加密安全的人都非常有价值。
至于编码字符串,如果你必须将字符串转换为ASCII文本,则Base64是一个不错的选择,但我建议你调查使用HTTP PUT或POST来避免这一额外步骤。