Подтвердить что ты не робот

Действительно простое шифрование с помощью С# и SymmetricAlgorithm

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

    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;
    }

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

Спасибо.

4b9b3361

Ответ 1

Если вы не хотите самостоятельно обрабатывать ключи, то пусть операционная система сделает это за вас. Например. используйте Защита данных 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) ) );
}

Ответ 2

Как насчет чего-то подобного?

код

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);
    }
}

Unit Test

[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);
}

EDIT:

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

"Я знаю о рисках такого подхода".

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

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

Ответ 3

Вам нужно установить режим шифрования на 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.

Ответ 4

Переписать методы Crypt и Decrypt для извлечения параметра ввода байтов. Убедитесь, что байты правильно зашифрованы и дешифрованы.