Расшифровать строку с помощью Rijndael, возвращающего System.SecureString (как строку), но не строку

Я использую алгоритм Rijndael для шифрования строк (паролей пользователей), но когда я их расшифровываю, он возвращает мне «System.SecureString», а не мой расшифрованный пароль.

Я использую этот базовый код:

public static string DecryptString(string cipherText, string password)
    {
        byte[] key, iv;
        Rfc2898DeriveBytes rfcDb = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(password));
        key = rfcDb.GetBytes(16);
        iv = rfcDb.GetBytes(16);

        byte[] cipheredData = Convert.FromBase64String(cipherText);

        RijndaelManaged rijndael = new RijndaelManaged();
        rijndael.Mode = CipherMode.CBC;

        ICryptoTransform decryptor = rijndael.CreateDecryptor(key, iv);
        MemoryStream ms = new MemoryStream(cipheredData);
        CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);

        byte[] plainTextData = new byte[cipheredData.Length];

        int decryptedByteCount = cs.Read(plainTextData, 0, plainTextData.Length);

        ms.Close();
        cs.Close();

        return Encoding.UTF8.GetString(plainTextData, 0, decryptedByteCount);
    }

Настоящая проблема в том, что он возвращает мне «System.SecureString», и я ничего не могу сделать.

Я думаю, что это происходит из-за преобразования в конце, но я действительно не знаю, как это изменить (кстати, это кажется хорошим)

return Encoding.UTF8.GetString(plainTextData, 0, decryptedByteCount);

Так что, если у вас есть идея или пример рабочего кода, мне интересно.

Хорошего дня


person crocteamgg    schedule 26.07.2013    source источник
comment
Причина вашей проблемы находится за пределами кода, который вы разместили. В нем нет безопасных строк. Я подозреваю, что вы где-то звоните password.ToString(), пытаясь преобразовать SecureString в String. Но так конвертировать нельзя.   -  person CodesInChaos    schedule 27.07.2013


Ответы (1)


Я реализовал rijndael в прошлом, и вот моя версия, если это поможет:

private static string Encrypt(string plainText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
        {
            // Convert strings into byte arrays.
            // Let us assume that strings only contain ASCII codes.
            // If strings include Unicode characters, use Unicode, UTF7, or UTF8 
            // encoding.
            var initVectorBytes = Encoding.ASCII.GetBytes(initVector);
            var saltValueBytes = Encoding.ASCII.GetBytes(saltValue);

            // Convert our plaintext into a byte array.
            // Let us assume that plaintext contains UTF8-encoded characters.
            var plainTextBytes = Encoding.UTF8.GetBytes(plainText);

            // First, we must create a password, from which the key will be derived.
            // This password will be generated from the specified passphrase and 
            // salt value. The password will be created using the specified hash 
            // algorithm. Password creation can be done in several iterations.
            var password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);

            // Use the password to generate pseudo-random bytes for the encryption
            // key. Specify the size of the key in bytes (instead of bits).
            var keyBytes = password.GetBytes(keySize / 8);

            // Create uninitialized Rijndael encryption object.

            // It is reasonable to set encryption mode to Cipher Block Chaining
            // (CBC). Use default options for other symmetric key parameters.
            var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC };

            // Generate encryptor from the existing key bytes and initialization 
            // vector. Key size will be defined based on the number of the key 
            // bytes.
            var encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);

            // Define memory stream which will be used to hold encrypted data.
            var memoryStream = new MemoryStream();

            // Define cryptographic stream (always use Write mode for encryption).
            var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);

            // Start encrypting.
            cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);

            // Finish encrypting.
            cryptoStream.FlushFinalBlock();

            // Convert our encrypted data from a memory stream into a byte array.
            var cipherTextBytes = memoryStream.ToArray();

            // Close both streams.
            memoryStream.Close();
            cryptoStream.Close();

            // Convert encrypted data into a base64-encoded string.
            var cipherText = Convert.ToBase64String(cipherTextBytes);

            // Return encrypted string.
            return cipherText;
        }


private static string Decrypt(string cipherText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
        {
            // Convert strings defining encryption key characteristics into byte
            // arrays. Let us assume that strings only contain ASCII codes.
            // If strings include Unicode characters, use Unicode, UTF7, or UTF8
            // encoding.
            var initVectorBytes = Encoding.ASCII.GetBytes(initVector);
            var saltValueBytes = Encoding.ASCII.GetBytes(saltValue);

            // Convert our ciphertext into a byte array.
            var cipherTextBytes = Convert.FromBase64String(cipherText);

            // First, we must create a password, from which the key will be 
            // derived. This password will be generated from the specified 
            // passphrase and salt value. The password will be created using
            // the specified hash algorithm. Password creation can be done in
            // several iterations.
            var password = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations);

            // Use the password to generate pseudo-random bytes for the encryption
            // key. Specify the size of the key in bytes (instead of bits).
            var keyBytes = password.GetBytes(keySize / 8);

            // Create uninitialized Rijndael encryption object.
            // It is reasonable to set encryption mode to Cipher Block Chaining
            // (CBC). Use default options for other symmetric key parameters.
            var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC };

            // Generate decryptor from the existing key bytes and initialization 
            // vector. Key size will be defined based on the number of the key 
            // bytes.
            var decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);

            // Define memory stream which will be used to hold encrypted data.
            var memoryStream = new MemoryStream(cipherTextBytes);

            // Define cryptographic stream (always use Read mode for encryption).
            var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);

            // Since at this point we don't know what the size of decrypted data
            // will be, allocate the buffer long enough to hold ciphertext;
            // plaintext is never longer than ciphertext.
            var plainTextBytes = new byte[cipherTextBytes.Length];

            // Start decrypting.
            var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

            // Close both streams.
            memoryStream.Close();
            cryptoStream.Close();

            // Convert decrypted data into a string. 
            // Let us assume that the original plaintext string was UTF8-encoded.
            var plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);

            // Return decrypted string.   
            return plainText;
        }

public static string EncryptData(string encryptText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
{
    return Encrypt(encryptText, passPhrase, saltValue, hashAlgorithm, passwordIterations, initVector, keySize);
}

public static string DecryptData(string decryptText, string passPhrase, string saltValue, string hashAlgorithm, int passwordIterations, string initVector, int keySize)
{
    return Decrypt(decryptText, passPhrase, saltValue, hashAlgorithm, passwordIterations, initVector, keySize);
}

Затем у меня были некоторые общедоступные методы, которые вызывают вышеуказанные методы...

public static string EncryptData(string encryptText)
{
    return EncryptionHelper.EncryptData(encryptText, ConfigHelper.PassPhrase, ConfigHelper.SaltValue, ConfigHelper.HashAlgorithm, ConfigHelper.PasswordIterations, ConfigHelper.InitVector, ConfigHelper.KeySize);
}

public static string DecryptData(string decryptText)
{
    return EncryptionHelper.DecryptData(decryptText, ConfigHelper.PassPhrase, ConfigHelper.SaltValue, ConfigHelper.HashAlgorithm, ConfigHelper.PasswordIterations, ConfigHelper.InitVector, ConfigHelper.KeySize);
}

Затем у меня было это в файле конфигурации ...

<add key="passPhrase" value=""/>
<add key="saltValue" value=""/>
<add key="hashAlgorithm" value="SHA1"/>
<add key="passwordIterations" value="5"/>
<add key="initVector" value=""/>
<add key="keySize" value="256"/>
person christiandev    schedule 26.07.2013
comment
Так что мой код правильный, я просто глупый. Я отправляю свой пароль с помощью passwordBox.SecurePassword, а не passwordBox.Password в свою функцию. Так что он отправлял System.SecurePassword (почему?, idk) вместо моего пароля. Так что для меня было нормальным найти System.SecurePassword, потому что на самом деле это было зашифровано. Итак, спасибо, christiandev, мой код правильный, но это ваш, который заставил меня понять это. Хорошего дня. - person crocteamgg; 26.07.2013
comment
@crocteamgg Пожалуйста, опубликуйте это как ответ, это достаточно полезно для людей, которые делают то же самое. Это совсем не так далеко. - person Maarten Bodewes; 26.07.2013