Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.90/41: Рейтинг темы: голосов - 41, средняя оценка - 4.90
0 / 0 / 0
Регистрация: 19.12.2013
Сообщений: 16
1
.NET 4.x

Шифрование и расшифровка строки с записью/чтением из БД

17.12.2014, 11:29. Просмотров 8467. Ответов 9
Метки нет (Все метки)


Доброго времени суток.
Необходимо реализовать шифрование строки, и затем ее расшифрование.
Данная строка записывается в БД в зашифрованном виде, а затем из нее должна преобразовываться в в исходную.

Данный функционал был реализован мною так, когда зашифрованное значение хранится в byte[], то все ок, но т.к. мне необходимо в конечном счете работать со строками, то расшифровка из строки не работает.
Не знаю, как решить данную проблему. Все уже перепробовали)
Помогите, пожалуйста, уважаемые форумчане, кто в этом силен.

Вот моя реализация):

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
using System;
using System.Security.Cryptography;
using System.Text;
 
namespace CoderDecoder
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string login = "UserLogin";
            
            var coderlogin = CoderString(login);
            var decoderlogin = DecoderString(coderlogin);
 
            Console.WriteLine("Логин:");
            Console.WriteLine(login + "\n");
           
            Console.WriteLine("Зашифрованный Логин:");
            Console.WriteLine(coderlogin+"\n");
            
            Console.WriteLine("Расшифрованный Логин:");
            Console.WriteLine(decoderlogin + "\n");
            
            Console.ReadKey();
        }
 
        /// <summary>
        /// Метод шифрования строки
        /// </summary>
        /// <param name="str">исходная (нешифрованная) строка</param>
        /// <returns>шифрованная строка</returns>
        private static string CoderString(string str)
        {
            string ret = string.Empty;
            try
            {
                var provider = new RSACryptoServiceProvider();
                Byte[] encryptedBytes = provider.Encrypt(
                    Encoding.UTF8.GetBytes(str), true);
                // этот "говнокод" переводит из массива в строку
                // не знаю, как это сделать иначе)
                foreach (byte encryptedByte in encryptedBytes)
                {
                    ret = ret + encryptedByte;
                }
            }
            catch (Exception)
            {
                Console.WriteLine("Ничего не вышло!");
            }
            return ret;
        }
 
        /// <summary>
        /// Метод дешифрования строки
        /// </summary>
        /// <param name="str">исходная (шифрованная) строка</param>
        /// <returns>дешифрованная строка</returns>
        private static string DecoderString(string str)
        {
            string ret = string.Empty;
            try
            {
                var provider = new RSACryptoServiceProvider();
                // привожу строку к массиву Byte для расшивровки
                // видимо здесь и косяк)
                Byte[] strbyte = Encoding.Default.GetBytes(str);
 
                ret = Encoding.UTF8.GetString(
                provider.Decrypt(strbyte, true));
            }
            catch (Exception)
            {
                Console.WriteLine("Ничего не вышло!");
            }
            return ret;
        }
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.12.2014, 11:29
Ответы с готовыми решениями:

Шифрование. Проблема с чтением и записью файла.
Доброго времени суток. Программа шифрует и расшифровывает файлы с помощью сети Фейстеля. Только...

Проблема с записью и чтением данных из файла
После записи программой в файл и открытии файла через Sublime Text, получается следующее: æåëåçî...

Работа с чтением/записью бинарного файла
Здравствуйте. Хочу создать бинарный файл, туда записать число. Затем его закрыть, заново открыть и...

Полное управление записью и чтением файлов
возникла такая ситуация , что надо на определёной строчке в фале добавить/изменить строчку. может...

9
Master of Orion
Эксперт .NET
6079 / 4935 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.12.2014, 10:31 2
lerochka_pnz, покажите ваш код, который работает правильно
0
Администратор
Эксперт .NET
13097 / 10675 / 4402
Регистрация: 17.03.2014
Сообщений: 21,480
Записей в блоге: 1
18.12.2014, 11:40 3
lerochka_pnz, во-первых, необходимо использовать одинаковые ключи при шифровке и дешифровке. Сохранить их можно с помощью ToXmlString(), восстановить с помощью FromXmlString(). Главное помнить что RSA асиметричный алгоритм использующий открытый и закрытый ключи. Закрытый ключ следует хранить в надежном месте!

Во-вторых, преобразование массива байтов в строку и обратно надо делать одинаково и правильно. Код внутри CoderString строит строку используя десятичную систему что означает что кол-во символов на один байт будет разным. При таком подходе невозможно понять что означает строка "111". Три байта со значением 1, один байт 111 или два байта 1 и 11? Лучше использовать 16 систему или base64 кодировку или вообще отказаться от преобразования и записывать в БД массив байтов.

В итоге код можно переписать так:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
static string rsaXmlPublic = "<RSAKeyValue><Modulus>mebyWauzOoDktNIbyph7fqSYG9uMfTkKu+tzxLgPhEQZ7kt1/caZOvAA1ge66B8U3X4TjYygtTMEfC0j/8YZX0MA6el11AUnVSc6NmQh5ONjTplhgu2qmtDTrcSU57jm9KlkGk3tgY0WjMd0J8LjmCGVRbNGVvFOWV44SR+wY2c=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
static string rsaXmlAll = "<RSAKeyValue><Modulus>mebyWauzOoDktNIbyph7fqSYG9uMfTkKu+tzxLgPhEQZ7kt1/caZOvAA1ge66B8U3X4TjYygtTMEfC0j/8YZX0MA6el11AUnVSc6NmQh5ONjTplhgu2qmtDTrcSU57jm9KlkGk3tgY0WjMd0J8LjmCGVRbNGVvFOWV44SR+wY2c=</Modulus><Exponent>AQAB</Exponent><P>0RKybKN5gJGH5SypTENQZfwnLT+caIpBz6OtDIswTIy8BB7p1QUKMib4bOV9xSEwfkmHYbipwf+sZD7jmpeiSQ==</P><Q>vHIjgGssedvLzd5lc2icub/ZzgZxL9hxDYDM0YSW/yuIYMgCnhceuDJWIn1OecNuDZk+LB0C8a55gt86pYzYLw==</Q><DP>eDOmr30hSwDgv6r4vubon2nkYEh1NUlf4vA4esC/iRNUuY3IZHecUA9Fvt4GfELDrae6lT1lJCtJwuzBUM0jOQ==</DP><DQ>oUO8BeWxhgcGfgLYJs9bb8oyhhEVQ7Ch7sBOhu5EmdGTP99p/ggjDdZlx9YcFi+cOp7tiaq6HkEFU23dLlc9mQ==</DQ><InverseQ>gDUuyy5cNsdkiXVenPKG4m71lRCm4PyFPSOiiU1IIfYNUJADj/Lbp1f7t4WaA1uBvCeXnWXXxMr9GYgamY0ZAg==</InverseQ><D>eQG+IcU/6cr4iDf/g/76cqvlsVmhj7/u8ayCXPU/tgZ5wQRyJHQnfNDCR4bSbboqhLChnRUqMu6HIz+241+WCDku8uPtGKV0dLoubWQBISsj+4JKIqpIHFdctVkV6VYPdKaVKh23ppJma2pYM3WIYCNUsy888436zRxjZbxY3HE=</D></RSAKeyValue>";
 
private static string CoderString(string str)
{
    var provider = new RSACryptoServiceProvider();
    provider.FromXmlString(rsaXmlPublic);
    byte[] encryptedBytes = provider.Encrypt(Encoding.UTF8.GetBytes(str), true);
    
    var sb = new StringBuilder(encryptedBytes.Length*2);
    for (int i = 0; i < encryptedBytes.Length; i++)
    {
        sb.AppendFormat("{0:X2}", encryptedBytes[i]);
    }
    return sb.ToString();
}
 
private static string DecoderString(string str)
{
    var provider = new RSACryptoServiceProvider();
    provider.FromXmlString(rsaXmlAll);
    
    byte[] strbyte = new byte[str.Length/2];
    for (int i=0; i<str.Length; i+=2)
    {
        int high = (int)str[i] - 48;
        if (high >= 49) high -= 39; else if (high >= 17) high -= 7;
        int low = (int)str[i+1] - 48;
        if (low >= 49) low -= 39; else if (low >= 17) low -= 7;
        strbyte[i/2] = (byte)(high << 4 | low);
    }
    
    return Encoding.UTF8.GetString(provider.Decrypt(strbyte, true));
}

P.S. Не забудь другую пару ключей сгенерировать.
0
Master of Orion
Эксперт .NET
6079 / 4935 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.12.2014, 11:59 4
OwenGlendower, вот это ужас Зачем конвертить в строку и потом таким диким образом парсить?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
 
namespace ConsoleApplication11
{
    class Program
    {
        private static string RsaKey;
        static void Main()
        {
            string s = "Hello world!";
            var res = Encode(s);
            Console.WriteLine(string.Join("", res.Select(x => x.ToString("X2"))));
            var res2 = Decode(res);
            Console.WriteLine(res2);
        }
 
        private static byte[] Encode(string str)
        {
            var provider = new RSACryptoServiceProvider();
            RsaKey = provider.ToXmlString(true);
            return provider.Encrypt(Encoding.UTF8.GetBytes(str), true);
        }
 
        private static string Decode(byte[] bytes)
        {
            var provider = new RSACryptoServiceProvider();
            provider.FromXmlString(RsaKey);
            return Encoding.UTF8.GetString(provider.Decrypt(bytes, true));
        }
    }
}
0
Администратор
Эксперт .NET
13097 / 10675 / 4402
Регистрация: 17.03.2014
Сообщений: 21,480
Записей в блоге: 1
18.12.2014, 12:03 5
Цитата Сообщение от Psilon Посмотреть сообщение
Зачем конвертить в строку и потом таким диким образом парсить?
Потому что автору вопроса хочется работать со строками Это не значит что я считаю этот подход оптимальным. Безусловно правильнее чтобы метод шифрования возвращал byte[]. Я упомянул это в своем ответе. "Дикие" преобразования пришлось написать потому что в .NET нет встроенного метода для преобразования из hex-строки в byte[] я и просто хотел показать как это можно сделать не претендуя на оптимальность.
0
Master of Orion
Эксперт .NET
6079 / 4935 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.12.2014, 12:37 6
OwenGlendower, неужели не проще распарсить стандартно?
C#
1
2
3
4
5
6
7
8
9
10
            byte[] bytes = {10, 12, 13, 14, 15};
            string s2 = string.Join("", bytes.Select(x => x.ToString("X2")));
            Console.WriteLine(s2);
 
            byte[] resultBytes = new byte[s2.Length/2];
            for (int i = 0; i < resultBytes.Length; i++)
            {
                resultBytes[i] = byte.Parse(s2.Substring(2*i, 2), NumberStyles.AllowHexSpecifier);
                Console.Write(resultBytes[i] + " ");
            }
0
Администратор
Эксперт .NET
13097 / 10675 / 4402
Регистрация: 17.03.2014
Сообщений: 21,480
Записей в блоге: 1
18.12.2014, 12:43 7
Цитата Сообщение от Psilon Посмотреть сообщение
неужели не проще распарсить стандартно?
Хотелось попробовать без Substring чтобы избежать лишних выделений памяти. Тоже самое относится к использованию StringBuilder вместо string.Join + Select.
0
Master of Orion
Эксперт .NET
6079 / 4935 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.12.2014, 12:58 8
OwenGlendower, во-первых Join сам использует stringbuilder. А Select вообще никаких накладных расходов практически не накладывает, только на вызов метода, который нельзя заинлайнить.
ну а что касается выделений памяти, то вы же сами писали:
я и просто хотел показать как это можно сделать не претендуя на оптимальность.
ну и не претендуйте Преждевременные оптимизации есть зло. И скорее всего никакого импакта на производительность кучка объектов в куче нулевого поколения не окажет, а т.к. ссылка очень короткоживущая, то смысла париться по этому поводу нет. В шарпе короткоживущие объекты можно создавать и удалять проще, чем в С++. Потому что выделение памяти в шарпе это просто увеличение указателя, а в С++ оператор new это целое приключение с поиском блока нужного размера.
0
Администратор
Эксперт .NET
13097 / 10675 / 4402
Регистрация: 17.03.2014
Сообщений: 21,480
Записей в блоге: 1
18.12.2014, 16:01 9
Psilon, мне известно как .NET работает с памятью и что короткоживущие объекты очищаются быстро. Однако это не значит что к памяти следует относиться так как будто она бесконечная.

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

Говоря про сравнительную оптимальность я имел в виду решения подобные вот такому. Для него даже StringBuilder оказался недостаточно эффективным. Подобные решения имеют право на жизнь, разумеется, но применяться должны только когда это имеет смысл.

На этом предлагаю закончить дисскуссию.
0
Master of Orion
Эксперт .NET
6079 / 4935 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
18.12.2014, 16:14 10
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Psilon, мне известно как .NET работает с памятью и что короткоживущие объекты очищаются быстро. Однако это не значит что к памяти следует относиться так как будто она бесконечная.
почему бы и нет? С вероятностью 99% этот код вообще никак не повлияет ни на скорость, ни на объем памяти. Если постоянно выделять и очищать память, то она будет бесконечной в некотором смысле, да.

Шарп в принципе не предназначен для извращения в стиле if (cmd[1] == RESET) {((void(*)(void))0)();}, он для написания читабельного безопасного кода. И программа, написанная в понятном стиле, по которой прошлись профайлером, будет и чище, и быстрее, чем с оптимизацией на каждом шагу.

Конечно, вы имеете право на собственное мнение. Но по моему опыту это так.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.12.2014, 16:14

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Хранилище данных с быстрым чтением/записью
Добрый день! Подскажите пожалуйста, в чем лучше хранить данные (скажем коллекцию List&lt;T&gt;), чтобы...

Задачка с записью и чтением из текстового файла с++
В текстовом файле «In.txt» сохраняются через пробел целые числа. Переписать в новый текстовый...

Проблемы с чтением и записью в файл в Юникоде
Добрый день. Есть код: Запись в файл: Option Explicit Sub SavingCaseAsUnicodeFile() Dim...

Не могу разобраться чтением и записью в файл
Тема моей курсовой работы &quot;разработка программы определения размера стихотворения&quot;. В краце мне...

Проблемы с чтением и записью двух однонаправленных сокетов
Добрый день, прошу подсказать как решить проблемы с чтением и записью в сокет. У меня есть два...

Задержка между записью/чтением Serial-порта
Доброе время суток. Работаю с одним устройством через RS232 порт, точнее через его эмуляцию с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.