Шифрование в 1С

Шифрование в 1С

При выборе метода шифрования необходимо исходить из правила - «Если стоимость взлома алгоритма выше, чем стоимость зашифрованных данных, вы,
скорее всего, в безопасности»
Брюс Шнайер.

НЕМНОГО ТЕОРИИ
Существует два метода шифрования:

  • Симметричное шифрование - использует один и тот же ключ и для шифрования, и для дешифрования. Основная проблема этого метода заключается в том, что если вы хотите передать зашифрованное сообщение, то должны передать и ключ, который можно при передаче скомпрометировать.
  • Асимметричное шифрование - использует два разных ключа: один для шифрования (который также называется открытым), другой для дешифрования (называется
    закрытым). Этот метод лишен недостатка предыдущего. Открытый ключ можно передать по открытым каналам.

Электронная цифровая подпись (ЭЦП) – это разновидность асимметричного шифрования, когда документ подписывается закрытым ключом, а достоверность документа проверяется открытым.
Хотя в реальности это выглядит несколько сложнее. Хэш-функцией создается хэш документа, который и подписывается закрытым ключом. Далее, эта подпись добавляется к документу.
При проверке подписи, хэш-функцией создается хэш проверяемого документа. Подпись, присоединенная при подписи, дешифруется открытым ключом. Сравниваются два хэша, если они равны, то все в порядке.

Сертификат безопасности – если упростить до предела, сертификат безопасности и является тем самым открытым ключом с дополнительной информацией. Обычно,
сертификаты располагаются в базах данных центров сертификации, которые и формируют из открытого ключа, сертификат. Эти центры отвечают за достоверность сертификатов.
На практике, если вы получили документ, подписанный ЭЦП, и хотите проверить подлинность подписи, необходимо проверить сертификат в центре сертификации и, если он действительно принадлежит отправителю и не просрочен, проверить целостность документа.
При отправке шифрованного сообщения, получаете сертификат получателя в центре, зашифруете сообщение открытым ключом из сертификата и отправляете получателю.
Поскольку создание сертификата и размещение в базе данных дело платное, можно создать временный сертификат. Это сертификат, который не удостоверен в центре сертификации, и его достоверность не может быть подтверждена кроме как вашим словом.
Каждая локальная машина под управлением любой ОС имеет свою локальную базу сертификатов. В Windows для просмотра сертификатов достаточно запустить консоль управления набрав в командной строке certmgr.msc, в Linux можно использовать апплет шифрования оболочки, хотя там возможностей больше.
Обычно сертификаты попадают в эту базу автоматически, когда используется шифрованное соединение вроде SSL, VPN и др., однако временный сертификат необходимо добавлять в ручную.

Криптопровайдер – из названия понятно, что это набор программных средств управляющих всем, что связанно с криптографией. Создание сертификатов, проверка сертификатов в центрах сертификации, шифрование, дешифрование и пр.

МЕТОДЫ ШИФРОВАНИЯ
В 1С возможны три варианта с помощью которых можно шифровать данные:

  1. Шифрование методом встроенного объекта «МенеджерКриптографии».
  2. Шифрование с использованием внешних компонент.
  3. Шифрование непосредственно в 1С.

ШИФРОВАНИЕ МЕТОДОМ ВСТРОЕННОГО ОБЪЕКТА «МенеджерКриптографии».
Этот метод достаточно подробно описан в Синтакс-Помощнике. Поэтому я опишу только последовательность работы с ним.
Создаем объект МенеджерКриптографии.

Где "Microsoft Enhanced Cryptographic Provider v1.0" и есть тот самый криптопровайдер, а "1" тип который можно посмотреть в реестре.

Дальше еще проще, получаем из менеджера криптографии, хранилище сертификатов. Из хранилища получаем нужный сертификат.
При выборе сертификата лучше использовать серийный номер, так как он короче отпечатка, меньше вероятность ошибки. Поиск по наименованию субъекта необходимо делать с осторожностью, так как при создании нескольких сертификатов одним владельцем, наименования субъекта могут быть одинаковыми.
После того как сертификат получен, зашифровываем, дешифровываем, подписываем, проверяем подпись, в общем делаем все что необходимо.
В интернете имеются реализации, когда сертификат записывают в регистр, а оттуда извлекают их при необходимости. Проблема заключается в том, что все сертификаты имеют срок действия, и к тому же они могут быть перевыпущены в любой момент, в случае, когда закрытые ключи утеряны или скомпрометированы. Эти изменения придется отслеживать вручную.

ШИФРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ ВНЕШНИХ КОМПОНЕНТ
Использование внешних компонент зависит от опыта и прихоти программиста. Есть множество бесплатных и платных реализаций.
Каждая из таких реализаций предусматривает наличие собственных методов управления ключами и алгоритмами шифрования, поэтому описывать хотя бы некоторые из них не имеет никакого смысла, так как каждый выберет реализацию по душе.
В качестве единственного примера реализации предлагаю статью «Шифрование
и защита информации в 1С:Предприятие 7.7/8.0/8.1/8.2»
, так как она использует широко распространённую платформу .Net Framework, в которой можно реализовать шифрование множеством алгоритмов.

ШИФРОВАНИЕ НЕПОСРЕДСТВЕННО В 1С
Чаще всего, бывают случаи, когда «танцы с бубнами» вокруг сертификатов абсолютно не нужны. Никто не будет заморачиваться покупкой сертификатов, а создание и отслеживание временных сертификатов, только добавляет «головной боли» программисту. К тому же необходимо всего лишь передать ведомость по зарплате в филиал или в документообороте создать персональную служебную записку.
Для этого можно реализовать достаточно надежный для этих целей алгоритм шифрования на встроенном языке.
Основными ограничениями в этом случае являются отсутствие в 1С методов для работы с двоичными данными и производительность платформы.
Обойти ограничения отсутствия методов двоичного счисления можно применив для работы алгоритма обычную десятичную математику.
С производительностью, к сожалению, ничего сделать нельзя. Все попытки существенно увеличить производительность при шифровании и дешифровании не привели к успеху, натыкаясь на ограничения платформы.

RSA для 1С
С теорией алгоритма RSA можно познакомиться здесь.
Основываясь именно на этом материале был реализован программный код состоящий всего из шести небольших функций.

// Функция проверяет является ли проверяемое число простым.
// Тест простоты (Перебор делителей).
// Параметры:
// 	- натуральное число.
// Возврат:
// 	- ИСТИНА - если число является простым.
&НаСервере
Функция ТестПростоты(ЧислоДляПроверки)
	Индекс = 2;
	Признак = 0;
	Пока ((Индекс * Индекс) <= ЧислоДляПроверки) И (Признак <> 1) Цикл 
		ЦелаяЧасть = Цел(ЧислоДляПроверки/Индекс);
		Если (ЧислоДляПроверки/Индекс - ЦелаяЧасть) = 0 Тогда 
			Признак = 1;
		КонецЕсли;
		Индекс = Индекс + 1;
	КонецЦикла;
	Если Признак = 1 Тогда
		Возврат Ложь;
	Иначе
		Возврат Истина;
	КонецЕсли;
КонецФункции
// Функция возвращает случайное простое число в заданном диапазоне.
// Параметры:
// 	- НижнийДиапазон - нижняя граница диапазона;
// 	- ВерхнийДиапазон - верхняя граница диапазона.
// Возврат:
// 	- случайное простое число.
&НаСервере
Функция ПолучитьПростоеЧисло(НижнийДиапазон, ВерхнийДиапазон, ЧислоИнициации)
	ГСЧ = Новый ГенераторСлучайныхЧисел(ЧислоИнициации);
	СлучайноеЧисло = ГСЧ.СлучайноеЧисло(НижнийДиапазон, ВерхнийДиапазон);
	Пока Не ТестПростоты(СлучайноеЧисло) Цикл 
		СлучайноеЧисло = ГСЧ.СлучайноеЧисло(НижнийДиапазон, ВерхнийДиапазон);
	КонецЦикла;
	ЧислоИнициации = ГСЧ.СлучайноеЧисло(НижнийДиапазон, ВерхнийДиапазон);
	Возврат СлучайноеЧисло;
КонецФункции
// Функция вычисляет взаимно простое число к заданному значению (Алгоритм Евклида).
// Параметры:
// 	- ЧислоОснова - число являющееся основой для поиска взаимно простых чисел.
// 	- ЧислоПоиска - число от которого начинается поиск взаимно простого числа.
// Возврат:
// 	- структура с взаимно простым числом и обратное число по модулю.
&НаСервере
Функция ПолучитьВзаимноПростыеЧисла(ЧислоОснова, ЧислоПоиска) 
	СтруктураВозврата = Новый Структура;
	Пока ЧислоПоиска < ЧислоОснова Цикл
		НаибольшийОбщийДелитель = 0;
		Делимое = ЧислоОснова;
		Делитель = ЧислоПоиска;
		Остаток = ЧислоПоиска;
		// Из соотношения Безу.
		АльфаМинус2 = 1;
		АльфаМинус1 = 0;
		ВитаМинус2 = 0;
		ВитаМинус1 = 1;
		Пока Остаток > 0 Цикл
			Частное = Делимое/Делитель;
			Остаток = Делимое - Делитель * Цел(Частное);
			Альфа = АльфаМинус2 - Цел(Частное) * АльфаМинус1;
			Вита = ВитаМинус2 - Цел(Частное) * ВитаМинус1;
			Если Остаток > 0 Тогда
				Делимое = Делитель;
				Делитель = Остаток;
			Иначе
				НаибольшийОбщийДелитель = Делитель;
			КонецЕсли;
			АльфаМинус2 = АльфаМинус1;
			АльфаМинус1 = Альфа;
			ВитаМинус2 = ВитаМинус1;
			ВитаМинус1 = Вита;
		КонецЦикла;
		Если НаибольшийОбщийДелитель = 1 И ВитаМинус2 > 0 Тогда //  
			СтруктураВозврата.Вставить("НОД", ЧислоПоиска);
			СтруктураВозврата.Вставить("Вита", ВитаМинус2);
			Возврат СтруктураВозврата;
		КонецЕсли;
		ЧислоПоиска = ЧислоПоиска + 1;
	КонецЦикла;
	Возврат ПолучитьВзаимноПростыеЧисла(ЧислоОснова, Цел(ЧислоПоиска/2));
КонецФункции
// Функция формирует закрытый и открытый ключ.
// Возврат:
// 	- структура с набором ключей, открытый-(e, n) и закрытый-(d, n).
&НаСервере
Функция СформироватьКлючи() Экспорт
	// Управление разрядностью ключа
	ВерхняяГраница = 100;
	НижняяГраница = 32;
	ЧислоИнициации = (Год(ТекущаяДата()) + Месяц(ТекущаяДата()) + День(ТекущаяДата()))*(Час(ТекущаяДата())+Минута(ТекущаяДата())+Секунда(ТекущаяДата()));
	// p
	ЧастьПи = ПолучитьПростоеЧисло(НижняяГраница, ВерхняяГраница, ЧислоИнициации);
	// q
	ЧастьКью = ЧастьПи;
	Пока ЧастьКью = ЧастьПи Цикл
		ЧастьКью = ПолучитьПростоеЧисло(НижняяГраница, ВерхняяГраница, ЧислоИнициации);
	КонецЦикла;
	// n
	ЧастьЭн = ЧастьПи * ЧастьКью;
	// Вычисляем функцию Эйлера.
	ЗначениеЭйлера = (ЧастьПи - 1) * (ЧастьКью - 1);
	// Вычисляем случайное взаимно простое чисело.
	ГСЧ = Новый ГенераторСлучайныхЧисел(ЗначениеЭйлера);
	СлучайноеЧисло = ГСЧ.СлучайноеЧисло(1, ЗначениеЭйлера);
	// e, d
	СтруктураЗначений = ПолучитьВзаимноПростыеЧисла(ЗначениеЭйлера, СлучайноеЧисло);
	ЧастьЕ = СтруктураЗначений.НОД;
	ЧастьД = СтруктураЗначений.Вита;
	// Собираем готовые ключи
	СтруктураВозврата = Новый Структура;
	СтруктураКлюча = Новый Структура;
	СтруктураКлюча.Вставить("ЧастьЕ", ЧастьЕ);
	СтруктураКлюча.Вставить("ЧастьЭн", ЧастьЭн);
	СтруктураВозврата.Вставить("ОткрытыйКлюч", ЗначениеВСтрокуВнутр(СтруктураКлюча));
	СтруктураКлюча = Новый Структура;
	СтруктураКлюча.Вставить("ЧастьЭн", ЧастьЭн);
	СтруктураКлюча.Вставить("ЧастьД", ЧастьД);
	СтруктураВозврата.Вставить("ЗакрытыйКлюч", ЗначениеВСтрокуВнутр(СтруктураКлюча));
	Возврат СтруктураВозврата;
КонецФункции
// Функция шифрует текст с использованием открытого ключа.
// Параметры:
// 	- текст подлежащий шифрованию;
// 	- открытый ключ.
// Возврат:
// 	- шифротекст в виде строки чисел через ";".
&НаСервере
Функция Шифрование(ШифруемыйТекст, ОткрытыйКлюч) Экспорт
	СтрокаВозврата = "";
	СтруктураКлюча = ЗначениеИзСтрокиВнутр(ОткрытыйКлюч);
	Для Индекс = 1 По СтрДлина(ШифруемыйТекст) Цикл
		Код = КодСимвола(ШифруемыйТекст, Индекс);
		Степень = Pow(Код, СтруктураКлюча.ЧастьЕ);
		Шифрокод = Степень - СтруктураКлюча.ЧастьЭн * Цел(Степень / СтруктураКлюча.ЧастьЭн);
		СтрокаВозврата = СтрокаВозврата + Шифрокод + ";"
	КонецЦикла;
	Возврат СтрокаВозврата;
КонецФункции
// Функция дешифрует текст с использованием закрытого ключа.
// Параметры:
// 	- шифротекст;
// 	- закрытый ключ.
// Возврат:
// 	- дешифрованный текст.
&НаСервере
Функция Дешифрование(Шифротекст, ЗакрытыйКлюч) Экспорт
	СтрокаВозврата = "";
	СтруктураКлюча = ЗначениеИзСтрокиВнутр(ЗакрытыйКлюч);
	СтрШифрокод = "";
	Для Индекс = 1 По СтрДлина(Шифротекст) Цикл
		Если Сред(Шифротекст, Индекс, 1) = ";" Тогда 
			Шифрокод = Число(СтрШифрокод);
			Степень = Pow(Шифрокод, СтруктураКлюча.ЧастьД);
			Код = Степень - СтруктураКлюча.ЧастьЭн * Цел(Степень / СтруктураКлюча.ЧастьЭн);
			СтрокаВозврата = СтрокаВозврата + Символ(Код);
			СтрШифрокод = "";
		Иначе 
			Если Не Сред(Шифротекст, Индекс, 1) = " " Тогда
				СтрШифрокод = СтрШифрокод + Сред(Шифротекст, Индекс, 1);
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	Возврат СтрокаВозврата;
КонецФункции

Функции расположены в модуле объекта обработки «ОбменСообщениями» из демонстрационного примера |File: demo.zip - Hash: MD5 - 63AF4F485464C863D6B626BAEC44C6C0|.
Демонстрационный пример представляет из себя средство обмена сообщениями между пользователями 1С.

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

Алгоритм RSA был разработан еще в 1977 г. В 2003 г. Ади Шамир и Эран Тромер разработали схему устройства TWIRL, которое при стоимости $ 10 000 может дешифровать 512-битный ключ за 10 минут, а при стоимости $ 10 000 000 – 1024-битный ключ меньше, чем за год.
Однако этот алгоритм используется и до настоящего времени с рекомендуемой длинной ключа 2048 бит.
В нашем же случае используется ключ примерно в 14 бит, увеличить длину ключа можно увеличив период диапазона.

// Управление разрядностью ключа
ВерхняяГраница = 100;
НижняяГраница = 32;

Однако значительное увеличение, резко замедляет процесс шифрования и дешифрования.

1С:Предприятие

Самый большой опыт работы был накоплен при внедрении программных продуктов от компании "1С".
Подробнее...

PALO

Этот продукт мы включили специально для тех заказчиков, которые решили организовать финансовый учет, на своем предприятии, либо ведут его в таблицах MS Excel.
Подробнее...

Профессионалам

Информационные материалы содержащие справочную информацию или полезные сведения для повышения квалификации.
Подробнее...