【问题标题】:Which AES Encryption I am using?我正在使用哪种 AES 加密?
【发布时间】:2013-11-23 00:09:16
【问题描述】:

我正在尝试在 android 设备上的文件上使用 AES256,并在 c# 中解码。这是我第一次尝试这个,所以我真的很困惑。我阅读了很多信息,但我得到的重要信息是用于加密的密钥将确定使用哪种加密。 我从这里得到这些课程:

Encryption compatible between Android and C#

我做了一些修改,效果非常好,但我对此有疑问。

  1. 这是 AES256 还是 AES128?

  2. 它是否显示了使用 AES 的正确方法?

  3. 方法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


【解决方案1】:

实际上,您的 C# 代码是错误的。 256 / 8 = 32 字节。您提供了 16 个字节作为 AES 密钥 (byte[] rawSecretKey)。我认为Android也是如此。它会给你一个编译错误。

【讨论】:

  • 它们工作得很好,我没有收到任何错误。如果我在 android 类上设置 32 个字节,我会得到一个错误,说 IV 参数应该是 16 个字节长,而在 c# 类上我得到:指定的初始化向量 (IV) 与此算法的块大小不匹配。跨度>
  • IV 应该始终是 CBC 的块大小,对于 16 字节的 AES。但我在 prime6669 的答案中没有看到任何提及 IV,我只看到提及 key size
  • 在这一行 rijndaelDecryptor = rijndael.CreateDecryptor(passwordKey, rawSecretKey) 我需要传递 KEY 和 IV
猜你喜欢
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 2016-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多