Действительно простое шифрование с C # и SymmetricAlgorithm - PullRequest
26 голосов
/ 27 января 2012

Я ищу очень простой метод шифрования / дешифрования.Я буду использовать всегда один и тот же статический ключ.Я знаю о рисках такого подхода.В настоящее время я использую следующий код, но он не выдает тот же результат после шифрования и дешифрования одной и той же строки (в середине строки есть какой-то мусор).

public static string Crypt(this string text)
{
    string result = null;

    if (!String.IsNullOrEmpty(text))
    {
        byte[] plaintextBytes = Encoding.Unicode.GetBytes(text);

        SymmetricAlgorithm symmetricAlgorithm = DES.Create();
        symmetricAlgorithm.Key = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8};
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, symmetricAlgorithm.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cryptoStream.Write(plaintextBytes, 0, plaintextBytes.Length);
            }

            result = Encoding.Unicode.GetString(memoryStream.ToArray());
        }
    }

    return result;
}

public static string Decrypt(this string text)
{
    string result = null;

    if (!String.IsNullOrEmpty(text))
    {
        byte[] encryptedBytes = Encoding.Unicode.GetBytes(text);

        SymmetricAlgorithm symmetricAlgorithm = DES.Create();
        symmetricAlgorithm.Key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        using (MemoryStream memoryStream = new MemoryStream(encryptedBytes))
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, symmetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Read))
            {
                byte[] decryptedBytes = new byte[encryptedBytes.Length];
                cryptoStream.Read(decryptedBytes, 0, decryptedBytes.Length);
                result = Encoding.Unicode.GetString(decryptedBytes);
            }
        }
    }

    return result;
}

Я могу изменить что угоднонеобходимо, без ограничений (но я хочу просто иметь метод для шифрования и еще один для расшифровки без разделения переменных между ними). ​​

Спасибо.

Ответы [ 3 ]

52 голосов
/ 27 января 2012

Если вы не хотите обрабатывать ключи самостоятельно, то пусть операционная система сделает это за вас. Например. используйте Защита данных Windows (DPAPI).

Вы можете написать свои собственные string версии System.Security.Cryptography.ProtectedData.Protect и Unprotect методов, используя что-то вроде:

public static string Crypt (this string text)
{
    return Convert.ToBase64String (
        ProtectedData.Protect (
            Encoding.Unicode.GetBytes (text) ) );
}

public static string Derypt (this string text)
{
    return Encoding.Unicode.GetString (
        ProtectedData.Unprotect (
             Convert.FromBase64String (text) ) );
}
33 голосов
/ 27 января 2012

Как насчет этого?

Код

using System;
using System.Security.Cryptography;
using System.Text;

public static class StringUtil
{
    private static byte[] key = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8};
    private static byte[] iv = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8};

    public static string Crypt(this string text)
    {
        SymmetricAlgorithm algorithm = DES.Create();
        ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
        byte[] inputbuffer = Encoding.Unicode.GetBytes(text);
        byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
        return Convert.ToBase64String(outputBuffer);
    }

    public static string Decrypt(this string text)
    {
        SymmetricAlgorithm algorithm = DES.Create();
        ICryptoTransform transform = algorithm.CreateDecryptor(key, iv);
        byte[] inputbuffer = Convert.FromBase64String(text);
        byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
        return Encoding.Unicode.GetString(outputBuffer);
    }
}

Модульный тест

[Test]
public void Test()
{
    string expected = "this is my test string";
    string a = expected.Crypt();
    Debug.WriteLine(a);
    string actual = a.Decrypt();
    Assert.AreEqual(expected, actual);
}

РЕДАКТИРОВАТЬ:

Чтобы уточнить: я знаю, что это не очень хорошая практика.

«Я знаю о рисках, связанных с этим подходом».

Я сделал предположение, что ОП также знает и внесет соответствующие изменения кода до того, какрассмотреть возможность использования чего-либо подобного в производственной среде.

Вопрос подчеркивает простоту перед хорошей практикой.

9 голосов
/ 27 января 2012

Вам необходимо установить режим шифрования на CipherMode.ECB или использовать IV.

SymmetricAlgorithm symmetricAlgorithm = DES.Create();
symmetricAlgorithm.Key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
symmetricAlgorithm.Mode = CipherMode.ECB;
...

Еще один момент - не использовать кодировку Unicode. Вместо этого используйте Base64. Unicode может «уничтожать» байты, которые не являются UTF-16.

...