【发布时间】:2013-11-23 00:09:16
【问题描述】:
我正在尝试在 android 设备上的文件上使用 AES256,并在 c# 中解码。这是我第一次尝试这个,所以我真的很困惑。我阅读了很多信息,但我得到的重要信息是用于加密的密钥将确定使用哪种加密。 我从这里得到这些课程:
Encryption compatible between Android and C#
我做了一些修改,效果非常好,但我对此有疑问。
这是 AES256 还是 AES128?
它是否显示了使用 AES 的正确方法?
方法
encodeDigest(String)的目的是什么?
此外,我对两个类的 encodeDigest(String) 方法进行了更改,因此它们返回大小为 32 的 byte[]。为什么?因为我在kgen.init(256)这一行中调试了android部分:这一行和接下来的几个返回一个大小为32的byte[]作为密钥。
我知道这不是一个好主意,但我让它发挥作用。我只是想把这件事做好,但现在我真的迷路了。
这就是我在 Android 中创建对象的方式:
AESEncryption aesEnc = new AESEncryption("asdfgasdfgasdfgasdfgasdfgasdfgas");
对于 Android,我使用这个类:
public class AESEncryption {
public static final String TAG = "AES";
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 AESEncryption(String passphrase) {
byte[] passwordKey = encodeDigest(passphrase);
// KeyGenerator kgen = null;
try {
aesCipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
//kgen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "No such algorithm " + CIPHER_ALGORITHM, e);
} catch (NoSuchPaddingException e) {
Log.e(TAG, "No such padding PKCS5", e);
}
//kgen.init(256); // 192 and 256 bits may not be available
// Generate the secret key specs.
//SecretKey skey = kgen.generateKey(); //Cantget 'test' in here...
//byte[] raw = skey.getEncoded();
//secretKey = new SecretKeySpec(raw, "AES");
secretKey = new SecretKeySpec(passwordKey, CIPHER_ALGORITHM);
ivParameterSpec = new IvParameterSpec(rawSecretKey);
}
public String encryptAsBase64(byte[] data) {
byte[] encryptedData = encrypt(data);
return Base64.encodeToString(encryptedData, Base64.DEFAULT);
}
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;
}
public byte[] dencrypt(byte[] clearData) {
try {
aesCipher.init(Cipher.DECRYPT_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[] dencryptedData;
try {
dencryptedData = 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 dencryptedData;
}
private byte[] encodeDigest(String text) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance(MESSAGEDIGEST_ALGORITHM);
//return digest.digest(text.getBytes());
return text.getBytes();
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "No such algorithm " + MESSAGEDIGEST_ALGORITHM, e);
}
return null;
}
}
对于 C#,这就是我创建对象的方式:
Crypto cr = new Crypto("asdfgasdfgasdfgasdfgasdfgasdfgas");
对于 C#,我使用这个类:
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);
//AesManaged as256 = new AesManaged();
//as256.CreateDecryptor(passwordKey, rawSecretKey);
RijndaelManaged rijndael = new RijndaelManaged();
rijndael.KeySize = 256;
rijndael.Mode = CipherMode.CBC;
rijndael.Padding = PaddingMode.PKCS7;
rijndaelDecryptor = rijndael.CreateDecryptor(passwordKey, rawSecretKey);
}
public byte[] Decrypt(byte[] encryptedData)
{
byte[] newClearData = rijndaelDecryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
// return Encoding.ASCII.GetString(newClearData);
return newClearData;
}
public string DecryptFromBase64(string encryptedBase64)
{
return null;// Decrypt(Convert.FromBase64String(encryptedBase64));
}
private byte[] encodeDigest(string text)
{
MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
return Encoding.ASCII.GetBytes(text);
//return x.ComputeHash(data);
}
}
【问题讨论】:
-
不要将密钥用作 IV。您需要为要加密的每条消息创建一个新的 IV,并将其与密文一起传输。无论密钥大小如何,IV 都必须为 16 字节。
标签: c# android encryption aes