Приложенные pdf-файлы с лабораторными работами представляют собой описание последовательности действий (с заданием, программным кодом и скриншотами).
Описание работы
Часто в работе пользователей с данными возникает ситуация, когда пользователь хочет быть уверен, что его данные не изменялись другими пользователями. При этом данных бывает очень много и пользователь не может быстро вручную проверить все данные на предмет отсутствия внесения в них несанкционированных изменений (материалы работы базируются на публикации "Хеширование данных с ключом по алгоритму SHA-1 штатными средствами 1С").
Порядок работы
Подробно о хешировании рассказывалось во второй лабораторной работе. При необходимости вы можете вернуться к ней и изучить основы хеширования. Поэтому уделим внимание самой задаче.
1-й вариант решения поставленной задачи. Допустим, у нас есть справочник товаров и первый пользователь (П1) внесёт в него название товара «Молоко». При использовании встроенной в платформу «1С:Предприятие 8» возможности хеширования алгоритмом SHA1 получим следующее значение хеш-суммы: BA 59 FA C2 3C 06 81 98 FD 5D 01 69 6D DD 0E 0F C0 B9 8D 30. Назовём это значение хеш-суммы как «Первичная хеш-сумма» (ПХС). Если второй пользователь (П2) исправит название, внесенное П1, на «Сыр», то хеш-сумма измененного названия будет равняться значению: 13 2B AF 5D F8 7B 3C 28 BD 25 4D A1 CA 74 D1 56 B3 5C A8 E5. Назовём это значение хеш-суммы как «Текущая хеш-сумма» (ТХС). В результате простого сравнения ПХС и ТХС первый пользователь сможет понять, что текущее название товара отличается от ранее внесенного им названия. Такой способ позволят довольно быстро проанализировать и показать П1 данные, значения которых отличаются от ранее внесённых им.
2-й вариант решения поставленной задачи. Продолжим рассматривать пример, приведенный в 1-м варианте решения поставленной задачи. П2 решает исправить ранее внесённое им название «Сыр» на изначальное название, внесенное П1, и вместо значения «Сыр» он вносит значение «Молоко». Новое значение ТХС будет равняться значению: BA 59 FA C2 3C 06 81 98 FD 5D 01 69 6D DD 0E 0F C0 B9 8D 30. Это значение полностью идентично ПХС. В таком случае, несмотря на то, что в первичное название товара были внесены исправления и затем значение было возвращено в исходное состояние, П1 не сможет относительно быстро узнать какие данные несанкционированное редактировались П2.
Для решения данной задачи (понимания, что кто-то несанкционированно редактировал первичные данные) необходимо дополнить процедуру расчёта хеш-суммы секретной частью. В большинстве случаев для этого используется пароль, который в нашем случае известен только П1. Допустим, П1 перед вводом названия товара «Молоко» вносит только ему известный пароль в значении «KjuT». В таком случае значение ПХС при использовании ранее описанного алгоритма ее формирования примет значение: 8F EB 83 F0 E7 5B 1C C1 93 10 08 DC C9 4F B0 17 2E 79 EE 4D. Как уже было сказано ранее, П2 меняет название на «Сыр», а потом решает исправить внесённое им название на изначальное название, внесенное П1, и вместо значения «Сыр» он вносит значение «Молоко». Новое значение ТХС будет равняться значению: BA 59 FA C2 3C 06 81 98 FD 5D 01 69 6D DD 0E 0F C0 B9 8D 30. Это значение не равно ПХС. В таком случае, П1 сможет относительно оперативно узнать какие данные несанкционированно редактировались другими пользователями.
Ниже приведен программный код, реализованный в данной лабораторной работе:
&НаСервере
Процедура РассчитатьНаСервере(ПарольДляШифрования,ТекущийМетодШифрованияКлиент) Экспорт
//определяем алгоритм шифрования архива
Если НЕ ТекущийМетодШифрованияКлиент = Неопределено Тогда
ТекущийМетодШифрования = ХешФункция[ТекущийМетодШифрованияКлиент];
Иначе
//по умолчанию такой
ТекущийМетодШифрования = ХешФункция.SHA1;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Ссылка КАК Ссылка
|ИЗ
| Справочник.Товары КАК Товары";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ДанныеДляХешСуммы = ВыборкаДетальныеЗаписи.Ссылка.Наименование;
//записываем в текущий элемент справочника в поле ХешСуммаНаименования с учетом пароля
ТекОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
ТекОбъект.ХешСуммаТекущегоНаименования = ЗашифроватьSHA1ШтатнымиСредствами(ДанныеДляХешСуммы,Объект.Пароль,ТекущийМетодШифрования);
ТекОбъект.Записать();
КонецЦикла;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Все элементы справочника были зашифрованы.";
Сообщение.Сообщить();
КонецПроцедуры
&НаКлиенте
Процедура Рассчитать(Команда)
//проверка на равенство пароля подтверждению
Если (Объект.Пароль = Объект.Подтверждение) Тогда
//определяем алгоритм шифрования архива
Если ЗначениеЗаполнено(ТипХешФункции) Тогда
ТекущийМетодШифрованияКлиент = ТипХешФункции;
Иначе
//по умолчанию такой
ТекущийМетодШифрованияКлиент = Неопределено;
КонецЕсли;
РассчитатьНаСервере(Объект.Пароль, ТекущийМетодШифрованияКлиент);
Иначе
Сообщить("Пароль и подтверждение не совпадают или они пустые!" + Символы.ПС + "Шифрование не выполнено.");
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПроверитьНаСервере(ПарольДляРасшифровки,ТекущийМетодШифрованияКлиент)
//определяем алгоритм шифрования архива
Если НЕ ТекущийМетодШифрованияКлиент = Неопределено Тогда
ТекущийМетодШифрования = ХешФункция[ТекущийМетодШифрованияКлиент];
Иначе
//по умолчанию такой
ТекущийМетодШифрования = ХешФункция.SHA1;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Ссылка КАК Ссылка
|ИЗ
| Справочник.Товары КАК Товары";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ДанныеДляХешСуммы = ВыборкаДетальныеЗаписи.Ссылка.Наименование;
ХешСуммаТекущегоНаименования = ЗашифроватьSHA1ШтатнымиСредствами(ДанныеДляХешСуммы,Объект.Пароль,ТекущийМетодШифрования);
Если ХешСуммаТекущегоНаименования = ВыборкаДетальныеЗаписи.Ссылка.ХешСуммаТекущегоНаименования Тогда
//значит оба наименования идентичны
Иначе
Сообщить("Наименование " + СокрЛП(ВыборкаДетальныеЗаписи.Ссылка) + " отличается от ранее указанного");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура Проверить(Команда)
//определяем алгоритм шифрования архива
Если ЗначениеЗаполнено(ТипХешФункции) Тогда
ТекущийМетодШифрованияКлиент = ТипХешФункции;
Иначе
//по умолчанию такой
ТекущийМетодШифрованияКлиент = Неопределено;
КонецЕсли;
ПроверитьНаСервере(Объект.Пароль,ТекущийМетодШифрованияКлиент);
КонецПроцедуры
Функция ЗашифроватьSHA1ШтатнымиСредствами(СтрокаТекст,СтрокаКлюч,ТекущийМетодШифрования) Экспорт
СтрокаНули = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
СтрокаОПАД = "5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c";
СтрокаИПАД = "36363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636";
К = ПолучитьДвоичныеДанныеИзСтроки(СтрокаКлюч);
К = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(К);
Нули = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаНули);
Нули.ЗаписатьПобитовоеИли(0,К);
Шаг1 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Нули);
ИПАД = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаИПАД);
БуферШаг1 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг1);
ИПАД.ЗаписатьПобитовоеИсключительноеИли(0,БуферШаг1);
Шаг2 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ипад);
БуферШаг2 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг2);
БуферТекст = ПолучитьБуферДвоичныхДанныхИзСтроки(СтрокаТекст);
БуферШаг3 = БуферШаг2.Соединить(БуферТекст);
Шаг3 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(БуферШаг3);
ХД = Новый ХешированиеДанных(ТекущийМетодШифрования);
ХД.Добавить(Шаг3);
Шаг4 = ХД.ХешСумма;
ОПАД = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаОПАД);
БуферШаг1 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг1);
ОПАД.ЗаписатьПобитовоеИсключительноеИли(0,БуферШаг1);
Шаг5 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ОПАД);
БуферШаг4 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг4);
БуферШаг5 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг5);
БуферШаг6 = БуферШаг5.Соединить(БуферШаг4);
Шаг6 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(БуферШаг6);
ХД = Новый ХешированиеДанных(ТекущийМетодШифрования);
ХД.Добавить(Шаг6);
Шаг7 = ХД.ХешСумма;
Возврат НРег(ПолучитьHexСтрокуИзДвоичныхДанных(Шаг7));
КонецФункции
К публикации приложена база 1С, в которой реализованы все четыре лабораторные работы. Конфигурация должна работать на любой платформе более-менее современной платформе «1С:Предприятие 8» (режим совместимости специально установил как «Версия 8.3.10»). Разработка и тестирование осуществлялись на базе учебной платформы «1С:Предприятие 8.3, учебная версия» (8.3.16.1224).