4

多くの調査を行いましたが、私の問題に対する答えが見つかりませんでした。私は.NETでAES暗号化(Rijndaelブロックサイズ128ビット)を行い、Android(AES)で同じパスワード、ソルト、およびIVを使用して復号化を行っています。

C# 暗号化コード スニペット:

        byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector);
        byte[] saltValueBytes  = Encoding.ASCII.GetBytes(saltValue);

        byte[] plainTextBytes  = Encoding.UTF8.GetBytes(plainText);

        PasswordDeriveBytes password = new PasswordDeriveBytes(
                                                        passPhrase, 
                                                        saltValueBytes, 
                                                        hashAlgorithm, 
                                                        passwordIterations);

        byte[] keyBytes = password.GetBytes(keySize / 8);

        RijndaelManaged symmetricKey = new RijndaelManaged();

        symmetricKey.Padding = PaddingMode.PKCS7;

        symmetricKey.BlockSize = 128;  

        symmetricKey.Mode = CipherMode.CBC;        

        ICryptoTransform encryptor = symmetricKey.CreateEncryptor(
                                                            keyBytes, 
                                                            initVectorBytes);

        MemoryStream memoryStream = new MemoryStream();        

        CryptoStream cryptoStream = new CryptoStream(memoryStream, 
                                                        encryptor,
                                                        CryptoStreamMode.Write);
        cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);

        cryptoStream.FlushFinalBlock();

        byte[] cipherTextBytes = memoryStream.ToArray();

        memoryStream.Close();
        cryptoStream.Close();

        string cipherText = Convert.ToBase64String(cipherTextBytes);

Android 復号化コード スニペット:

    KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), iterationCount); 

    SecretKey key = SecretKeyFactory.getInstance( 
            "PBEWithSHA1And128BitAES-CBC-BC").generateSecret(keySpec);

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");

    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));

    byte[] decrypted = cipher.doFinal(encrypted);

cipher.doFinal 呼び出しは、次の例外をスローします。

「05-02 18:17:38.239: W/System.err(25547): javax.crypto.BadPaddingException: パッド ブロックが破損しています」

.NET と Android の両方でパディングを「PKCS7Padding」に設定し、暗号化ブロック サイズを 128 ビットに設定しました。

ただし、Android での暗号化と Android での復号化は正常に機能します。Encrypt in .NET と Decrypt in .NET も同様に正常に動作します。

サンプル テスト:

String PlainText            = "hello world";
String EncryptedDotNetblob  = "JyijoGEALMI25Zej7d+fMg==";
String EncryptedAndroidblob = "1HhuTQaLRJEK4zxI9FAO6A==";

上記のように、ブロブも異なります。

ここで何が問題なのか知っている人はいますか?

4

2 に答える 2

2

派生しているキーが異なるため、エラーが発生します (16 進文字列としてログに記録して確認してください)。PasswordDeriveBytes一方、PBKDF1 の変更されたバージョンを使用すると、SecretKeyFactory.getInstance("PBEWithSHA1And128BitAES-CBC-BC")PKCS#12 で指定されたキーを派生させるキー ファクトリが提供されます。これらは異なるアルゴリズムであり、異なるキーを生成します。Rfc2898DeriveBytes.NET で同じパラメーターを使用SecretKeyFactory .getInstance("PBKDF2WithHmacSHA1")して、同じキーを取得します。

于 2012-05-07T04:13:31.527 に答える
-1

これは C# の例です。IterationCount が必要です。

protected void Page_Load(object sender, EventArgs e)
{
    string value = "";
    string password = "";
    string salt = "";
    string iv = "";


    byte[] vectorBytes = Convert.FromBase64String(Server.UrlDecode(iv)); 
    byte[] cipherText = Convert.FromBase64String(Server.UrlDecode(value));

    Rfc2898DeriveBytes key1 = new Rfc2898DeriveBytes(password, StringToByteArray(salt)); //same as PBKDF2WithHmacSHA1
    key1.IterationCount = 32;
    byte[] keyBytes = key1.GetBytes(16);

    string Answer = DecryptDataAES(cipherText, keyBytes, vectorBytes); //vectorBytes is good

    //litAnswer.Text = Answer;
}

public static string DecryptDataAES(byte[] cipherText, byte[] key, byte[] iv)
{
    string plaintext = null;

    using (Rijndael rijndael = Rijndael.Create())
    {
        rijndael.Key = key;
        rijndael.IV = iv;
        rijndael.Padding = PaddingMode.None;

        ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);

        // Create the streams used for decryption. 
        using (MemoryStream msDecrypt = new MemoryStream(cipherText))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                {
                    plaintext = srDecrypt.ReadToEnd();
                }
            }
        }
    }
    return plaintext;
}

public static byte[] StringToByteArray(String hex)
{
    int NumberChars = hex.Length / 2;
    byte[] bytes = new byte[NumberChars];
    using (var sr = new StringReader(hex))
    {
        for (int i = 0; i < NumberChars; i++)
            bytes[i] =
              Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
    }
    return bytes;
}
于 2013-10-15T14:10:03.070 に答える