Зашифровывая структуру, ошибка с плохими данными, что вызывает это? - PullRequest
1 голос
/ 20 февраля 2012

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

    public byte[] Serialize(object obj, string key)
    {
        byte[] returnBytes;
        using (MemoryStream memory = new MemoryStream())
        {
            UTF8Encoding UTF8 = new UTF8Encoding();
            TripleDESCryptoServiceProvider crypt = new TripleDESCryptoServiceProvider();
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] pass = provider.ComputeHash(UTF8.GetBytes(key));
            crypt.Key = pass;
            crypt.Mode = CipherMode.ECB;
            crypt.Padding = PaddingMode.PKCS7;
            using (CryptoStream stream = new CryptoStream(memory, crypt.CreateEncryptor(), CryptoStreamMode.Write))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, obj);
                stream.Close();
                memory.Close();
            }

            returnBytes = memory.ToArray();
        }

        return returnBytes;
    }
    public object Deserialize(byte[] inBytes, string key)
    {
        object returnObj;
        using (MemoryStream memory = new MemoryStream())
        {
            UTF8Encoding UTF8 = new UTF8Encoding();
            TripleDESCryptoServiceProvider crypt = new TripleDESCryptoServiceProvider();
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] pass = provider.ComputeHash(UTF8.GetBytes(key));
            crypt.Key = pass;
            crypt.Mode = CipherMode.ECB;
            crypt.Padding = PaddingMode.PKCS7;
            using (CryptoStream stream = new CryptoStream(memory, crypt.CreateDecryptor(), CryptoStreamMode.Read))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                returnObj = formatter.Deserialize(stream);
                stream.Close();
                memory.Close();
            }
            return returnObj;
        }

    }

Этот код, который я делал некоторое время назад, работает со строками

        public string encrypt(string message, string password)
        {
            byte[] result;
            UTF8Encoding UTF8 = new UTF8Encoding();
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] key = provider.ComputeHash(UTF8.GetBytes(password));
            TripleDESCryptoServiceProvider algorithm = new TripleDESCryptoServiceProvider();
            algorithm.Key = key;
            algorithm.Mode = CipherMode.ECB;
            algorithm.Padding = PaddingMode.PKCS7;
            byte[] data = UTF8.GetBytes(message);
            try
            {
                ICryptoTransform encryptor = algorithm.CreateEncryptor();
                result = encryptor.TransformFinalBlock(data, 0, data.Length);
            }
            finally
            {
                algorithm.Clear();
                provider.Clear();
            }
            return Convert.ToBase64String(result);
        }
        public string decrypt(string message, string passsword)
        {
            byte[] result;
            UTF8Encoding UTF8 = new UTF8Encoding();
            MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
            byte[] key = provider.ComputeHash(UTF8.GetBytes(passsword));
            TripleDESCryptoServiceProvider algorithm = new TripleDESCryptoServiceProvider();
            algorithm.Key = key;
            algorithm.Mode = CipherMode.ECB;
            algorithm.Padding = PaddingMode.PKCS7;
            byte[] data = Convert.FromBase64String(message);
            try
            {
                ICryptoTransform decryptor = algorithm.CreateDecryptor();
                result = decryptor.TransformFinalBlock(data, 0, data.Length);
            }
            finally
            {
                algorithm.Clear();
                provider.Clear();
            }
            return UTF8.GetString(result);
        }

1 Ответ

2 голосов
/ 20 февраля 2012

Вы не устанавливаете свойство IV для crypt, поэтому каждый раз оно начинается со случайного значения.Вам нужно установить для него то же значение при расшифровке, что и при шифровании - как соль для хеширования.РЕДАКТИРОВАТЬ: Учитывая, как работает ECB, похоже, что IV может игнорироваться, поэтому ваш предыдущий код работал без его сохранения.

EDIT: Хотя часть IV, безусловно, требуется для не-ECB, это не такдовольно.Я не уверен, в чем заключается остальная проблема, хотя:

  • Режим шифрования ECB не рекомендуется - есть какая-то причина его использовать?
  • Вы можете в конечном итогестолкнуться с проблемами из-за заполнения;Я не знаю, обрабатывает ли BinaryFormatter это для вас автоматически, но стоит разобраться.

РЕДАКТИРОВАТЬ: Doh - я решил большую проблему;вы действительно должны использовать inBytes, согласно комментарию Элиана.В настоящее время вы полностью игнорируете зашифрованный текст - у него есть нет шансов на работу!

Вот полная программа, показывающая все это вместе:

using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Runtime.Serialization.Formatters.Binary;

class Test
{
    static void Main()
    {
        byte[] data = Serialize("Some arbitrary test data", "pass");
        object x = Deserialize(data, "pass");
        Console.WriteLine(x);
    }

    private static SymmetricAlgorithm CreateCryptoServiceProvider(string key)
    {
        byte[] passwordHash;
        using (MD5 md5 = MD5.Create())
        {
            // It's not clear why you're taking the hash of the password...
            passwordHash = md5.ComputeHash(Encoding.UTF8.GetBytes(key));
        }
        var crypt = new TripleDESCryptoServiceProvider();
        crypt.Key = passwordHash;
        crypt.Mode = CipherMode.CBC; // This is the default anyway - can remove
        crypt.Padding = PaddingMode.PKCS7; // Ditto
        // Fix this to use a randomly generated one and store it for real code.
        crypt.IV = new byte[crypt.BlockSize / 8];
        return crypt;
    }

    public static byte[] Serialize(object obj, string key)
    {
        var provider = CreateCryptoServiceProvider(key);

        using (MemoryStream memory = new MemoryStream())
        {
            using (CryptoStream stream = new CryptoStream(
                memory, provider.CreateEncryptor(), CryptoStreamMode.Write))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, obj);
            }
            return memory.ToArray();
        }
    }

    public static object Deserialize(byte[] inBytes, string key)
    {
        var provider = CreateCryptoServiceProvider(key);

        using (MemoryStream memory = new MemoryStream(inBytes))
        {
            using (CryptoStream stream = new CryptoStream(
                memory, provider.CreateDecryptor(), CryptoStreamMode.Read))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                return formatter.Deserialize(stream);
            }
        }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...