Вопрос по aes, cryptography, c#, windows-runtime – Расшифровка AesManaged в приложении Metro WinRT

4

У меня есть некоторый текст, зашифрованный Ces AesManaged, который необходимо расшифровать в приложении WinRT Metro. Я не могу изменить код шифрования, так как у кода есть другие зависимости, которые нельзя изменить.

Функция шифрования выглядит следующим образом:

// Note: Edited out possibly real password and salt:
Guid password = Guid.Parse("AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA");
Guid salt = Guid.Parse("AAAAAAAAA-BBBB-BBBB-BBBB-AAAAAAAAAAAA");

string EncryptedValue(string data)
{   
byte[] passwordBytes = password.ToByteArray();
byte[] saltBytes = salt.ToByteArray();

byte[] bKey = new byte[16];
for(int i = 0; i < 16; i++)
{
    bKey[i] = passwordBytes[i];
}

string encryptedData = String.Empty;
using (System.Security.Cryptography.AesManaged aesAlg = new System.Security.Cryptography.AesManaged())
{
    aesAlg.Key = bKey;
    aesAlg.IV = saltBytes;

    // Create a decrytor to perform the stream transform.
    System.Security.Cryptography.ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

    // Create the streams used for encryption.
    using (MemoryStream msEncrypt = new MemoryStream())
    {
        using (System.Security.Cryptography.CryptoStream csEncrypt = new System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write))
        {
            using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
            {

                //Write all data to the stream.
                swEncrypt.Write(data);
            }

            encryptedData = Convert.ToBase64String(msEncrypt.ToArray());
        }
    }
}

return encryptedData;
}

Пример данных:

   // Decrypted value is: 2029
   var _id = EncryptedSettingsBase.Decrypt("ROSNJ1XnAozF7LC0wW8AOg==");

Я прочитал следующий пост: http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/7cfcc576-1c2c-4a50-a546-09a45d3ff41f что похоже на ту же проблему, однако я не смог заставить их работать предложение, так как получаю исключение: «Ошибка данных (проверка циклическим избыточным кодом). (Исключение из HRESULT: 0x80070017).

internal class EncryptedSettingsBase
{
    public static string Decrypt(string cipherText)
    {
        var passwordBytes = (new Guid("AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")).ToByteArray();
        var salt = (new Guid("AAAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA")).ToString();

        byte[] bKey = new byte[16];
        for (int i = 0; i < 16; i++)
        {
            bKey[i] = passwordBytes[i];
        }

        IBuffer pwBuffer = CryptographicBuffer.CreateFromByteArray(bKey);
        IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf16LE);
        IBuffer cipherBuffer = CryptographicBuffer.DecodeFromBase64String(cipherText);

        // Derive key material for password size 32 bytes for AES256 algorithm
        KeyDerivationAlgorithmProvider keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");
        // using salt and 1000 iterations
        KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000);

        // create a key based on original key and derivation parmaters
        CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
        IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32);
        CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer);

        // derive buffer to be used for encryption salt from derived password key 
        IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16);

        // display the keys - because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately
        string keyMaterialString = CryptographicBuffer.EncodeToBase64String(keyMaterial);
        string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial);

        SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
        // create symmetric key from derived password material
        CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);

        // encrypt data buffer using symmetric key and derived salt material
        IBuffer resultBuffer = CryptographicEngine.Decrypt(symmKey, cipherBuffer, saltMaterial);
        string result = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf16LE, resultBuffer);
        return result;
    }
}

Я, вероятно, делаю что-то глупое, но я не совсем понимаю этот материал. Кто-нибудь знает, где я ошибаюсь?

Буду признателен за любую оказанную помощь.

Ура, Джон

Если это ваш настоящий пароль и соль, размещать его в публичном месте не очень хорошая идея ... Eric J.
Я думаю, что для AES ваш ключ должен быть 32 байта, а не 16. Не уверен, что в этом проблема, но я не знаю, что он будет делать, если он слишком короткий. SwDevMan81
У меня была похожая проблема некоторое время назад, когда я пытался соединить алгоритм JavaScript AES с алгоритмом C # AES. Я обнаружил, что они не все реализованы одинаково, поэтому я так и не получил ожидаемых результатов! series0ne
@ SwDevMan81 AES поддерживает оба. AES-256 имеет 32-байтовый ключ, а AES-128 - 16-байтовый ключ. CodesInChaos
@Eric - не беспокойтесь, я изменил их перед публикацией ;-) Jon Rea

Ваш Ответ

2   ответа
3

.net. К сожалению, та часть, которую вы не можете изменить, неправильно использует ключ; он просто использует UID напрямую.

Означает ли это, что это не может работать? Как бы вы изменили генерацию ключа на стороне .Net, чтобы исправить это? Jon Rea
Нет, он может работать, он не настолько криптографически безопасен, как следовало бы. Удалите pbkdf2 на стороне WinRT.
3

если я могу изменить все свои зависимости для правильного шифрования:

Код здесь помог:http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2966549-make-equal-aesmanaged-snippet-as-in-silverlight-an

Код шифрования на стороне C # 4.0:

string salt = "AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA";
string password = "AAAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA";

string EncryptedValue(string data)
{   
byte[] saltBytes = System.Text.Encoding.UTF8.GetBytes(salt);

string encryptedData = String.Empty;
using (System.Security.Cryptography.AesManaged aes = new System.Security.Cryptography.AesManaged())
{
    var rfc = new System.Security.Cryptography.Rfc2898DeriveBytes(password, saltBytes);

    aes.BlockSize = aes.LegalBlockSizes[0].MaxSize; 
    aes.KeySize = aes.LegalKeySizes[0].MaxSize; 
    aes.Key = rfc.GetBytes(32); 
    rfc.Reset(); 
    aes.IV = rfc.GetBytes(16);

    // Create a decrytor to perform the stream transform.
    System.Security.Cryptography.ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

    // Create the streams used for encryption.
    using (MemoryStream msEncrypt = new MemoryStream())
    {
        using (System.Security.Cryptography.CryptoStream csEncrypt = new System.Security.Cryptography.CryptoStream(msEncrypt, encryptor, System.Security.Cryptography.CryptoStreamMode.Write))
        {
            using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
            {
                // Write all data to the stream.
                swEncrypt.Write(data);
            }

            encryptedData = Convert.ToBase64String(msEncrypt.ToArray());
        }
    }
}

return encryptedData;
}

Расшифровка кода WinRT стороной:

protected string Decrypt(string encryptedData)
    {
        const string password = "AAAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA";
        const string salt = "AAAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA";

        IBuffer pwBuffer = CryptographicBuffer.ConvertStringToBinary(password, BinaryStringEncoding.Utf8);
        IBuffer saltBuffer = CryptographicBuffer.ConvertStringToBinary(salt, BinaryStringEncoding.Utf8);
        IBuffer cipherBuffer = CryptographicBuffer.DecodeFromBase64String(encryptedData);

        KeyDerivationAlgorithmProvider keyDerivationProvider = KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1");

        KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000);

        CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer);
        IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32);

        CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer);

        IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16);

        SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");

        CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial);

        IBuffer resultBuffer = CryptographicEngine.Decrypt(symmKey, cipherBuffer, saltMaterial);

        byte[] asd;
        CryptographicBuffer.CopyToByteArray(resultBuffer, out asd);
        string result = CryptographicBuffer.ConvertBinaryToString(BinaryStringEncoding.Utf8, resultBuffer);
        return result;
    }

Похожие вопросы