gifts2017

Шифрование и расшифровка строковых полей справочников методом Виженера (с улучшениями)

Опубликовал Никита Хацкевич (NikitaXa) в раздел Программирование - Защита и шифрование

Обработка по шифрованию и расшифровке строковых полей справочников модифицированным методом Виженера - реализация без внешних компонент, без com-объектов, чистый 1С.

Хочу поделиться примером реализации обработки по шифрованию/расшифровке произвольных текстовых полей справочников. Требования перед разработкой я поставил следующие:

  1. Должен быть реализован функционал шифрования и расшифровки по паролю;
  2. Зашифрованные данные должны храниться в полях исходных данных, т.е. длина зашифрованного текста должна быть равной длине исходного текста, дополнительных таблиц быть не должно;
  3. Список полей для шифрования/расшифровки должен быть настраиваемым и не зависеть от конфигурации;
  4. Шифрование должно выполняться средствами платформы 1С без внешних компонент, com-объектов и т.д., чтобы исключить зависимость от ОС;

Решений на Инфостарте по шифрованию/расшифровки строк огромное множество (Защита и шифрование) - практически на любой вкус. Приведу наиболее интересные (на мой субъективный взгляд):

  1. Подсистема шифрования данных + пример реализации: решение Keystore для хранения паролей;
  2. Симметричное шифрование в 1С;
  3. Шифрование текста, хеш сумма;
  4. Хеширование данных с ключом по алгоритму SHA-1 штатными средствами 1С;
  5.  Шифратор и дешифратор текста и файлов для 1С

Однако, найти публикацию, отвечающую всем моим требованиям, так и не удалось. Из-за наличия требования №2 (о не превышении длиной зашифрованного текста длины исходного текста), в качестве метода шифрования был выбран шифр Виженера.
Да, по современным стандартам данный шифр является ненадежным и поддается взлому. Поэтому, чтобы повысить время на дешифровку текста, в базовый алгоритм были внесены следующие улучшения:

  1. Ключ для шифрования формируется на основании пароля, длина ключа шифрования равна длине шифруемого текста;
  2. Код каждого символа ключа шифрования равен коду соответсвующего символа пароля, смещенного на псевдо случайную величину А;
  3. Псевдо случайная величина А зависит от максимального кода среди символов пароля и длины кодируемой строки;
  4. Код каждого символа зашифрованной строки равен сумме кода соответствующего символа исходной строки, кода соответствующего символа ключа шифрования и псевдо-случайной величины В;
  5. Псевдо случайная величина В зависит от максимального кода среди символов ключа шифрования и длины кодируемой строки;

 Для генерации псевдо случайных величин использовался встроенный объект платформы "ГенераторСлучайныхЧисел". Ниже приведны основные функции обработки:

  1. Функция ПолучитьМаксимальныйКодСимволаСтроки - получает максимальный код символа в переданной строке : 

    Функция ПолучитьМаксимальныйКодСимволаСтроки(СтрокаАнализа)
    	
    	ДлинаСтрокиАнализа = СтрДлина(СтрокаАнализа);
    	
    	МаксимальныйКодСимвола = 0;
    	
    	Для Счетчик = 1 По ДлинаСтрокиАнализа Цикл
    				
    		КодТекущегоСимвола = КодСимвола(СтрокаАнализа, Счетчик);
    		
    		Если КодТекущегоСимвола > МаксимальныйКодСимвола Тогда
    			
    			МаксимальныйКодСимвола = КодТекущегоСимвола;
    			
    		КонецЕсли;
    		
    	КонецЦикла;
    	
    	Возврат МаксимальныйКодСимвола;
    	
    КонецФункции
  2. Функция ПолучитьКлючШифрования - получает по паролю ключ шифрования с учетом псевдо случайного смещения:

    Функция ПолучитьКлючШифрования(лПароль, ДлинаКодируемойСтроки)
    	
    	лПароль_Длина 	= СтрДлина(лПароль);
    	КлючШифрования	= "";
    	
    	ЧислоДляИнциализацииГенератораСлучаныхЧисел = ПолучитьМаксимальныйКодСимволаСтроки(лПароль_Длина);
    	
    	ЧислоДляИнциализацииГенератораСлучаныхЧисел = ЧислоДляИнциализацииГенератораСлучаныхЧисел + ДлинаКодируемойСтроки;
    	
    	ГенераторСлучаныхЧисел = Новый ГенераторСлучайныхЧисел(ЧислоДляИнциализацииГенератораСлучаныхЧисел);
    	
    	СчетчикПоПаролю = Неопределено;
    	
    	Для Счетчик = 1 По ДлинаКодируемойСтроки Цикл
    		
    		Если (СчетчикПоПаролю = Неопределено) ИЛИ (СчетчикПоПаролю > лПароль_Длина) Тогда
    			
    			СчетчикПоПаролю = 1;
    				
    		КонецЕсли;
    		
    		СлучайноеСмещение = ГенераторСлучаныхЧисел.СлучайноеЧисло(1, ЧислоДляИнциализацииГенератораСлучаныхЧисел);
    				
    		СимволПароля = Сред(лПароль, СчетчикПоПаролю, 1);
    		
    		КлючШифрования = КлючШифрования + Символ(КодСимвола(СимволПароля) + СлучайноеСмещение);
    		
    		СчетчикПоПаролю = СчетчикПоПаролю + 1;
    		
    	КонецЦикла;
    	
    	Возврат КлючШифрования;
    	
    КонецФункции
  3. Функция ЗашифроватьСтроку - шифрует строку шифром Виженера по ключу шифрования с учетом псевдо случайного смещения:

    Функция ЗашифроватьСтроку(КодируемаяСтрока, КлючШифрования)
    	
    	ДлинаКодируемойСтроки = СтрДлина(КодируемаяСтрока);
    	
    	ЧислоДляИнциализацииГенератораСлучаныхЧисел = ПолучитьМаксимальныйКодСимволаСтроки(КлючШифрования);
    	
    	ЧислоДляИнциализацииГенератораСлучаныхЧисел = ЧислоДляИнциализацииГенератораСлучаныхЧисел + ДлинаКодируемойСтроки;
    	
    	ГенераторСлучаныхЧисел = Новый ГенераторСлучайныхЧисел(ЧислоДляИнциализацииГенератораСлучаныхЧисел);
    	
    	ЗакодированнаяСтрока = "";
    	
    	Для Счетчик = 1 ПО ДлинаКодируемойСтроки Цикл
    		
    		КодСимволаИсходнойСтроки 	= КодСимвола(КодируемаяСтрока, Счетчик);
    		КодСимволаКлючаШифрования 	= КодСимвола(КлючШифрования, Счетчик);		
    		СлучайнаяСоставляющая 		= ГенераторСлучаныхЧисел.СлучайноеЧисло(1, ЧислоДляИнциализацииГенератораСлучаныхЧисел);
    		
    		КодЗакодированныгоСимвола = КодСимволаИсходнойСтроки + КодСимволаКлючаШифрования + СлучайнаяСоставляющая;
    		
    		ЗакодированнаяСтрока = ЗакодированнаяСтрока + Символ(КодЗакодированныгоСимвола);
    		
    	КонецЦикла;
    	
    	Возврат ЗакодированнаяСтрока;
    	
    КонецФункции
  4. Функция РасшифроватьСтроку - расшифровывает строку по ключу шифрования с учетом псевдо случайного смещения:

    Функция РасшифроватьСтроку(КодируемаяСтрока, КлючШифрования)
    	
    	ДлинаКодируемойСтроки = СтрДлина(КодируемаяСтрока);
    	
    	ЧислоДляИнциализацииГенератораСлучаныхЧисел = ПолучитьМаксимальныйКодСимволаСтроки(КлючШифрования);
    	
    	ЧислоДляИнциализацииГенератораСлучаныхЧисел = ЧислоДляИнциализацииГенератораСлучаныхЧисел + ДлинаКодируемойСтроки;
    	
    	ГенераторСлучаныхЧисел = Новый ГенераторСлучайныхЧисел(ЧислоДляИнциализацииГенератораСлучаныхЧисел);
    	
    	ЗакодированнаяСтрока = "";
    	
    	Для Счетчик = 1 ПО ДлинаКодируемойСтроки Цикл
    		
    		КодСимволаКлючаШифрования 	= КодСимвола(КлючШифрования, Счетчик);			
    		КодЗакодированныгоСимвола 	= КодСимвола(КодируемаяСтрока, Счетчик);
    		СлучайнаяСоставляющая 		= ГенераторСлучаныхЧисел.СлучайноеЧисло(1, ЧислоДляИнциализацииГенератораСлучаныхЧисел);
    		
    		КодСимволаИсходнойСтроки = КодЗакодированныгоСимвола - КодСимволаКлючаШифрования - СлучайнаяСоставляющая;
    		
    		ЗакодированнаяСтрока = ЗакодированнаяСтрока + Символ(КодСимволаИсходнойСтроки);
    		
    	КонецЦикла;
    	
    	Возврат ЗакодированнаяСтрока;
    	
    КонецФункции
  5. Функция ЗашифроватьРасшифроватьПолеОбъекта - получает ключ шифрования по паролю и шифрует или расшифровывает строку в зависимости от входных параметров:

    Процедура ЗашифроватьРасшифроватьПолеОбъекта(ЗначениеРеквизита, Пароль, ЗаписатьЭлемент, ЭтоШифрование)
    	
    	Если НЕ ПустаяСтрока(ЗначениеРеквизита) Тогда
    		
    		КлючШифрования = ПолучитьКлючШифрования(Пароль, СтрДлина(ЗначениеРеквизита));
    		
    		Если ЭтоШифрование Тогда
    			
    			ЗначениеРеквизита = ЗашифроватьСтроку(ЗначениеРеквизита, КлючШифрования);
    			
    		Иначе
    			
    			ЗначениеРеквизита = РасшифроватьСтроку(ЗначениеРеквизита, КлючШифрования);
    			
    		КонецЕсли;
    			
    		Если НЕ ЗаписатьЭлемент Тогда
    			
    			ЗаписатьЭлемент = ИСТИНА;
    			
    		КонецЕсли;
    		
    	КонецЕсли;
    	
    КонецПроцедуры

Фактическая реализация алгоритма в виде обработки в приложенном файле. Интерфейс обработки интуитивно понятен. Для выполнения шифрования (или расшифровки) необходимо выполнить несколько простых шагов: 

  1. Выбрать поля данных в базе для обработки (при нажатии на гиперссылку с надписью "Обработать:" открывается отдельная форма с деревом справочников конфигурации со всеми текстовыми реквизитами и табличными частями с текстовыми реквизитами;
  2. Ввести пароль;
  3. Ввести подтверждение пароля;
  4. Нажать кнопку "Зашифровать" или "Расшифровать" в зависимости от требуемого действия. 

В качестве примера работы алгоритма приложены скриншоты со справочником "Страны" до шифрования и после шифрования.  На этом все, спасибо за внимание, надеюсь, кому-нибудь пригодится.

Конструктивная критика приветствуется! 

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
ШифрованиеСтроковыхПолейСправочников.epf
.epf 18,58Kb
21.06.16
5
.epf 1.01 18,58Kb 5 Скачать

См. также

Contragent+ 5.0 от 2 500
Подписаться Добавить вознаграждение

Комментарии

1. Сергей Ожерельев (Поручик) 27.04.16 07:57
Интересно. Где бы это приспособить?
2. Никита Хацкевич (NikitaXa) 27.04.16 08:23
(1) Поручик, например, временное скрытие конфиденциальной информации в базе.
3. Олег (oleg_km) 27.04.16 09:54
У меня в базе хранятся зашифрованные пароли от всякий банк-клиентов так, чтобы их не мог прочитать ни администратор, ни программист. Но я использую для всякий шифрований .NET
4. Александр (altu71) 27.04.16 10:24
А не подскажите, сколько времени занимает шифрование/расшифровка этим методом на значительном объеме данных? Т.е. запись 10 000 элементов справочника без шифрования столько то, а этих же данных, но с шифрованием - столько то. Т.е. хочется узнать накладные расходы времени на шифрование.
5. Никита Хацкевич (NikitaXa) 27.04.16 21:38
(4) altu71, накладные расходы на шифрование будут напрямую зависеть от оборудования. Я делал замеры (5 циклов шифрования/расшифровки) на справочнике объемом около 6.000. Общее время записи элементов справочника плюс/минус равно (точность до секунды) общему времени записи элементов этих же элементов с шифрованием двух полей (номер телефона и электронная почта). Т..е .время шифрования незначительно по сравнению с временем записи элемента справочника в БД. Если скорость шифрования справочника неудовлетворительна из-за длительной записи элементов справочника, то всегда можно распараллелить этот процесс через фоновые задания.
6. Вася Пупкин (bubus) 26.05.16 02:30
И какова стойкость такого метода интересно? Брутфорс пальцами конечно не вариант, а если из 1С обработки пробутфорсить, сколько времени займет интересно на строку из 10 символов (зашифрованный пароль)?
7. Никита Хацкевич (NikitaXa) 26.05.16 23:07
(6) bubus, вот здесь есть описание продолжительности перебора пароля в общем случае. Т.е. для 10 символов пароля получается 1162 года. Однако существуют различные методы расшифровки шифра Виженера, которые позволяют ускорить время расшифровки.
8. Вася Пупкин (bubus) 27.05.16 08:31
(7) NikitaXa, я уже глянул, да есть. И очень эффективный - частотный криптоанализ. https://habrahabr.ru/post/221485/ Жаль там ссылка на программу мертвая. Но, программа та работает с "обычным" Виженером, а у вас я так понял изменения некоторые с ключом, плюс не "алфавитный квадрат" а символьный. Но, было бы очень интересно посмотреть за сколько бы та программа справилась, если бы справилась вообще. Но, в любом случае ваша разработка мне кажется очень и очень полезной. Для мобильных приложений к примеру, где у нас нет возможности юзать .NET Framework для шифрования.
9. Vladimir Polyakov (spectre1978) 05.06.16 16:30
(1) Ну наиболее типичное на мой взгляд применение - это если в объектах конфы хранятся имена-пароли (скажем от неких сторонних веб-сервисов, с которыми работает программа) и есть желание это дело немного прикрыть от посторонних глаз.
10. Vladimir Polyakov (spectre1978) 05.06.16 16:34
(6) bubus, если нужна стойкость от реального взлома - Вижинер вряд ли подойдет. Это один из самых известных и простых методов шифрования.
Т.е. "защита от дурака". Для серьезных применений нужно использовать CryptoAPI и алгоритмы из него.
11. John Bolshakov (soulsteps) 21.06.16 16:32
Автор, сделай сортировку в списке выбора объектов. А так обработка супер. Как раз понадобилось шифрануть данные.
12. Никита Хацкевич (NikitaXa) 22.06.16 11:30
(11) soulsteps, приложена новая версия обработки с сортировкой дерева справочников по синониму.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа