1С: Получение полей отбора с формы списка

Задача: узнать состав текущего отбора на форме списка..и составить аналогичный запрос в БД, для получения выборки

Решение: Применимо в данный момент только к динамическому списку. Отборы получаем чтением данных из компоновщика настроек. Запрос (фактически условие) получается крайне грубым, но приемлемым для моих входящих данных. Итак код:

 	// Проработаем текущий отбор
	sql="";   	
	для каждого стр из Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы цикл
			попытка ош=стр["Элементы"];исключение прервать; конецпопытки;
			для каждого эл из стр.Элементы цикл
				если эл.ВидСравнения=ВидСравненияКомпоновкиДанных.Содержит тогда
					sql=sql+" И "+эл.ЛевоеЗначение+" ПОДОБНО ""%"+эл.ПравоеЗначение+"%""";
				конецесли;	
				если эл.ВидСравнения=ВидСравненияКомпоновкиДанных.Равно тогда
					sql=sql+" И "+эл.ЛевоеЗначение+" = """+эл.ПравоеЗначение+"""";
				конецесли;	
				если эл.ВидСравнения=ВидСравненияКомпоновкиДанных.Больше тогда
					sql=sql+" И "+эл.ЛевоеЗначение+" > """+эл.ПравоеЗначение+"""";
				конецесли;	
				если эл.ВидСравнения=ВидСравненияКомпоновкиДанных.Меньше тогда
					sql=sql+" И "+эл.ЛевоеЗначение+" < """+эл.ПравоеЗначение+"""";
				конецесли;	
				если эл.ВидСравнения=ВидСравненияКомпоновкиДанных.НеРавно тогда
					sql=sql+" И "+эл.ЛевоеЗначение+" <> """+эл.ПравоеЗначение+"""";
				конецесли;	
				
			конеццикла;
	конеццикла;	 

1С: Сохранение логов изменений регистра сведений

Задача: вести журнал логов изменения записей регистра сведений

Решение:

Штатного механизма как в Документа или Справочниках нет (ну собственно и правильно, т.к. запись сейчас есть, через минуту её нет). Потому разработаем собственный механизм. Общий алгоритм будет следующий:

  • при открытии форма регистра — запоминаем структуру и значения данных записи регистра
  • при записи регистра из формы — сравниваем новые данные с охраненными, и при выявлении изменений, записываем оные в отдельный регистр «изменений».

При открытии формы регистра, получаем его структуру из метаданных, и запоминаем значения:

&НаКлиенте
Перем ДанныеФормыДоИзменения;

&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
	СохранитьИзмененияЕслиТаковыеЕсть(ДанныеФормыДоИзменения)
КонецПроцедуры

&НаСервере
Функция ПолучитьДанныеДоОбновления()
	ДанныеПоРегистру=Метаданные.РегистрыСведений.СГ_ГР_ТранспортныйФайлПриборыУчета;
	ДоступныеПоля=Новый Структура();
	для каждого стр из ДанныеПоРегистру.Измерения цикл
		ДоступныеПоля.Вставить(стр.имя,неопределено);
	конеццикла;	
	для каждого стр из ДанныеПоРегистру.Ресурсы цикл
		ДоступныеПоля.Вставить(стр.имя,неопределено);
	конеццикла;	
	
	Данные=Новый Структура();
	для каждого стр из ДоступныеПоля цикл
		 ключ=стр.Ключ;
		 значение=ЭтотОбъект.Запись[Стр.Ключ];
		 Данные.Вставить(ключ,Строка(значение));
	 конеццикла;		
	 возврат Данные;
КонецФункции

При сохранении данных из формы регистра:

НаСервере
Функция СохранитьИзмененияЕслиТаковыеЕсть(ДанныеФормыДоИзменения)
	для каждого стр из ДанныеФормыДоИзменения цикл
		если стр.Значение<>Строка(ЭтотОбъект.Запись[Стр.Ключ]) тогда
			СК_ГР_РаботаСТранспортнымиФайлами.СделатьЗаписьОбИзменении(
				ЭтотОбъект.Запись["dt"],
				перечисления.СК_ГР_РегистрДляОбработки.Приборы,
				Строка(Стр.Ключ),
				Строка(стр.Значение),
				Строка(ЭтотОбъект.Запись[Стр.Ключ])
			);
		конецесли;	
	конеццикла;
КонецФункции	

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	ДанныеФормыДоИзменения=ПолучитьДанныеДоОбновления();
КонецПроцедуры

В сам регистр «изменений», пишем так:

// Запись в регистр данных об изменении какого то поля в регистрах
// Вход:
//		Период - Дата загрузки из регистра
//		Изменяемый регистр - перечисления.СК_ГР_РегистрДляОбработки
//		Поле - изменяемое поле (строка)
//		Было - значение которое было (строка)
//		Стало - значение которое стало (строка)
Функция СделатьЗаписьОбИзменении(Период,Регистр,Поле,Было,Стало) экспорт
		
	МенеджерЗаписи = РегистрыСведений.СК_ГР_ИсторияИзменений.СоздатьМенеджерЗаписи(); 
		МенеджерЗаписи.Период=ТекущаяДата();
		МенеджерЗаписи.ПериодЗагрузки = Период; 
		МенеджерЗаписи.ИзменяемыйРегистр = Регистр; 
		МенеджерЗаписи.ИзменяемоеПоле = Поле; 
		МенеджерЗаписи.Было = Было; 
		МенеджерЗаписи.Стало = Стало; 
		МенеджерЗаписи.Исполнитель = Пользователи.ТекущийПользователь(); 
	МенеджерЗаписи.Записать();    			
КонецФункции	

1С: Получение текущего пользователя

Постараюсь описать все способы определения текущего пользователя информационной базы. К сожалению от версии к версии БСП способы могут меняться.

Способ № 1

ПользователиИнформационнойБазы.ТекущийПользователь()

Способ №2

ОбщийМодульСистема.ОпределитьТекущегоПользователя();

Способ №3

ПользователиКлиентСервер.ТекущийПользователь()

Способ №4

Клиент - ПользователиКлиент.ТекущийПользователь()
Сервер - Пользователи.ТекущийПользователь()

Способ №5

ЗначениеТекущегоПользователя = ПараметрыСеанса.ТекущийПользователь;

Наиболее актуальный на текущий момент способ №4.

ИИ для написания кода для 1С

Попробовал попросить ИИ написать код на языке 1С, который давно хотел, но всё не мог осилить, вт.ч. из-за недостатка времени разбираться в низкоуровневых операциях работы с битами на 1С. А именно — написание функции по генерации TOTP кодов на основании хэша и текущего времени. Ну что если в кратце: ИИ (https://chat.mistral.ai/) пока не готова тоже к этому. Помучавшись с час, так и не добился рабочего кода. Ниже переписка..

Напиши функцию получения TOTP кода на языке программирования 1С

3 Apr, 10:22

Для создания функции получения TOTP (Time-Based One-Time Password) кода на языке программирования 1С, необходимо выполнить несколько шагов. TOTP — это алгоритм генерации одноразовых паролей, основанный на времени. Он использует текущее время и секретный ключ для генерации пароля.

Читать далее: ИИ для написания кода для 1С Читать далее: ИИ для написания кода для 1С

Вот пример реализации TOTP на языке 1С:

Copy// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущее время
    Если Время = Неопределено Тогда
        Время = ТекущаяДатаВремя();
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (Время - ДатаВремя(1970, 1, 1, 0, 0, 0)) / 30;

    // Преобразуем секретный ключ в байтовый массив
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ПолучитьHMACSHA1(БайтыКлюча, ВремяСЭпохи);

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения HMAC-SHA1
Функция ПолучитьHMACSHA1(Ключ, Сообщение) Экспорт
    // Используем встроенную функцию для получения HMAC-SHA1
    HMAC = Новый ХэшSHA1;
    HMAC.УстановитьКлюч(Ключ);
    HMAC.Обновить(Сообщение);
    Возврат HMAC.Получить();
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = ПраваяСтрока(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. СекретныйКлюч: Это ключ, который используется для генерации TOTP. Он должен быть согласован между сервером и клиентом.
  2. Время: Используется текущее время, если оно не задано.
  3. HMAC-SHA1: Используется для генерации хэша на основе временного интервала и секретного ключа.
  4. TOTP: Получается из последних 4 байт HMAC и форматируется как 6-значное число.

Этот пример демонстрирует базовую реализацию TOTP. В реальных приложениях могут потребоваться дополнительные проверки и обработка ошибок.

3 Apr, 10:22

Я же уже писал, что в 1С нету функции ХэшSHA1. Вместо неё используй и встрой следующий код: Функция ВыполнитьШифрование(СтрокаДляХеш, КлючДляХеш) Экспорт СтрокаНули = «00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000»; СтрокаОПАД = «5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c»; СтрокаИПАД = «36363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636»; К = ПолучитьДвоичныеДанныеИзСтроки(КлючДляХеш); К = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(К); Нули = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаНули); Нули.ЗаписатьПобитовоеИли(0, К); Шаг1 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Нули); ИПАД = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаИПАД); БуферШаг1 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг1); ИПАД.ЗаписатьПобитовоеИсключительноеИли(0, БуферШаг1); Шаг2 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ИПАД); БуферШаг2 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг2); БуферТекст = ПолучитьБуферДвоичныхДанныхИзСтроки(СтрокаДляХеш); БуферШаг3 = БуферШаг2.Соединить(БуферТекст); Шаг3 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(БуферШаг3); ХД = Новый ХешированиеДанных(ХешФункция.SHA1); ХД.Добавить(Шаг3); Шаг4 = ХД.ХешСумма; ОПАД = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаОПАД); БуферШаг1 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг1); ОПАД.ЗаписатьПобитовоеИсключительноеИли(0, БуферШаг1); Шаг5 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ОПАД); БуферШаг4 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг4); БуферШаг5 = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Шаг5); БуферШаг6 = БуферШаг5.Соединить(БуферШаг4); Шаг6 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(БуферШаг6); ХД = Новый ХешированиеДанных(ХешФункция.SHA1); ХД.Добавить(Шаг6); Шаг7 = ХД.ХешСумма; СтруктураРезультата = Новый Структура; СтруктураРезультата.Вставить(«ДД», Шаг7); СтруктураРезультата.Вставить(«HexСтрока», НРег(ПолучитьHexСтрокуИзДвоичныхДанных(Шаг7))); СтруктураРезультата.Вставить(«Base64Строка», Base64Строка(Шаг7)); Возврат СтруктураРезультата; КонецФункции

3 Apr, 10:23

Спасибо за предоставленный код. Давайте интегрируем его в функцию получения TOTP кода. Мы будем использовать вашу функцию ВыполнитьШифрование для генерации HMAC-SHA1.

Вот как можно изменить код для получения TOTP с использованием вашей функции:

Copy// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущее время
    Если Время = Неопределено Тогда
        Время = ТекущаяДатаВремя();
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (Время - ДатаВремя(1970, 1, 1, 0, 0, 0)) / 30;

    // Преобразуем секретный ключ в байтовый массив
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(ВремяСЭпохи, БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = ПраваяСтрока(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. ВыполнитьШифрование: Используется для генерации HMAC-SHA1. Она принимает строку для хеширования и ключ.
  2. ВремяСЭпохи: Вычисляется как количество 30-секундных интервалов с момента эпохи Unix.
  3. ПолучитьTOTPКод: Преобразует HMAC в 6-значный TOTP код.

Этот код должен работать в среде 1С, используя вашу функцию для генерации HMAC. Убедитесь, что все необходимые функции и методы доступны в вашей версии 1С.

3 Apr, 10:23

В 1С нет функции ТекущаяДатаВремя. Вместо неё используй ТекущаяДата

3 Apr, 10:27

Понял, давайте заменим ТекущаяДатаВремя на ТекущаяДата и адаптируем код для работы с датой. В 1С ТекущаяДата возвращает только текущую дату без времени, поэтому нам нужно будет учесть это при вычислении временного интервала.

Вот обновленный код:

Copy// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата() + СтрокаВремени(Час(ТекущееВремя()), Минута(ТекущееВремя()), Секунда(ТекущееВремя()));
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - ДатаВремя(1970, 1, 1, 0, 0, 0)) / 30;

    // Преобразуем секретный ключ в байтовый массив
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = ПраваяСтрока(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. ТекущаяДатаВремя: Мы используем ТекущаяДата и ТекущееВремя для получения текущей даты и времени.
  2. ВремяСЭпохи: Вычисляется как количество 30-секундных интервалов с момента эпохи Unix.
  3. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя доступные функции для работы с датой и временем.

3 Apr, 10:27

Нене, функция ТекущаяДата уже возвращает и дату и время. Перепиши код

3 Apr, 10:28

Спасибо за уточнение. Давайте перепишем код, учитывая, что ТекущаяДата возвращает как дату, так и время.

Вот обновленный код:

Copy// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - ДатаВремя(1970, 1, 1, 0, 0, 0)) / 30;

    // Преобразуем секретный ключ в байтовый массив
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = ПраваяСтрока(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. ТекущаяДата: Возвращает текущую дату и время.
  2. ВремяСЭпохи: Вычисляется как количество 30-секундных интервалов с момента эпохи Unix.
  3. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя ТекущаяДата для получения текущей даты и времени.

3 Apr, 10:28

В 1С нет функции ДатаВремя, вместо этого используй Дата(1970,1,1)

3 Apr, 10:29

Понял, давайте перепишем код, используя Дата(1970, 1, 1) для вычисления временного интервала.

Вот обновленный код:

Copy// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в байтовый массив
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = ПраваяСтрока(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  2. ТекущаяДата: Возвращает текущую дату и время.
  3. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя Дата(1970, 1, 1) для вычисления временного интервала.

3 Apr, 10:29

В 1С нет функции СтрокаВБайты, напиши аналог

3 Apr, 10:31

В 1С для преобразования строки в массив байтов можно использовать методы работы с двоичными данными. Давайте создадим аналог функции СтрокаВБайты с использованием доступных методов.

Вот как можно реализовать преобразование строки в массив байтов:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем буфер двоичных данных
    Буфер = Новый ДвоичныеДанные(Строка);

    // Получаем массив байтов из буфера
    МассивБайтов = Новый Массив;
    Длина = Буфер.Длина;

    Для Индекс = 0 По Длина - 1 Цикл
        МассивБайтов.Добавить(Буфер.ПолучитьБайт(Индекс));
    КонецЦикла;

    Возврат МассивБайтов;
КонецФункции

// Пример использования
СтрокаДляПреобразования = "Пример строки";
МассивБайтов = СтрокаВБайты(СтрокаДляПреобразования);

Пояснения:

  1. ДвоичныеДанные: Используется для создания буфера двоичных данных из строки.
  2. МассивБайтов: Создается массив, в который добавляются байты из буфера.

Теперь вы можете использовать эту функцию в коде для получения TOTP. Если у вас есть другие вопросы или требуется дополнительная помощь, дайте знать!

3 Apr, 10:31

Ага, теперь перепиши код используюя эту функцию

3 Apr, 10:31

Конечно, давайте обновим код для получения TOTP, используя функцию СтрокаВБайты для преобразования строки в массив байтов.

Вот обновленный код:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем буфер двоичных данных
    Буфер = Новый ДвоичныеДанные(Строка);

    // Получаем массив байтов из буфера
    МассивБайтов = Новый Массив;
    Длина = Буфер.Длина;

    Для Индекс = 0 По Длина - 1 Цикл
        МассивБайтов.Добавить(Буфер.ПолучитьБайт(Индекс));
    КонецЦикла;

    Возврат МассивБайтов;
КонецФункции

// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = ПраваяСтрока(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. СтрокаВБайты: Преобразует строку в массив байтов.
  2. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  3. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя СтрокаВБайты для преобразования строки в массив байтов.

3 Apr, 10:31

Что делает функция ПраваяСтрока

3 Apr, 10:33

Функция ПраваяСтрока в языке программирования 1С используется для извлечения подстроки из строки, начиная с конца. Она возвращает указанное количество символов с конца строки.

Синтаксис:

CopyПраваяСтрока(Строка, КоличествоСимволов)

Параметры:

  • Строка: Исходная строка, из которой нужно извлечь подстроку.
  • КоличествоСимволов: Количество символов, которые нужно извлечь с конца строки.

Пример использования:

CopyСтрока = "Пример строки";
Подстрока = ПраваяСтрока(Строка, 6); // Подстрока будет "строки"

Пояснения:

  • Если КоличествоСимволов больше длины строки, то функция вернет всю строку.
  • Если КоличествоСимволов равно нулю, то функция вернет пустую строку.

Если у вас есть другие вопросы или требуется дополнительная помощь, дайте знать!

3 Apr, 10:33

В 1С нет такой функции. Вместо неё используй функцию Прав

3 Apr, 10:34

Понял, давайте заменим использование ПраваяСтрока на функцию Прав в коде для получения TOTP. Функция Прав в 1С используется для извлечения подстроки с конца строки.

Вот обновленный код:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем буфер двоичных данных
    Буфер = Новый ДвоичныеДанные(Строка);

    // Получаем массив байтов из буфера
    МассивБайтов = Новый Массив;
    Длина = Буфер.Длина;

    Для Индекс = 0 По Длина - 1 Цикл
        МассивБайтов.Добавить(Буфер.ПолучитьБайт(Индекс));
    КонецЦикла;

    Возврат МассивБайтов;
КонецФункции

// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = Прав(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. Прав: Используется для извлечения подстроки с конца строки.
  2. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  3. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя Прав для извлечения последних байтов из HMAC.

3 Apr, 10:34

В 1С нет функции БайтыВЧисло, напиши аналог и перепиши код

3 Apr, 10:35

В 1С для преобразования массива байтов в число можно использовать методы работы с двоичными данными. Давайте создадим аналог функции БайтыВЧисло, который будет преобразовывать массив байтов в число.

Вот как можно реализовать эту функцию и обновить код для получения TOTP:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем буфер двоичных данных
    Буфер = Новый ДвоичныеДанные(Строка);

    // Получаем массив байтов из буфера
    МассивБайтов = Новый Массив;
    Длина = Буфер.Длина;

    Для Индекс = 0 По Длина - 1 Цикл
        МассивБайтов.Добавить(Буфер.ПолучитьБайт(Индекс));
    КонецЦикла;

    Возврат МассивБайтов;
КонецФункции

// Функция для преобразования массива байтов в число
Функция БайтыВЧисло(МассивБайтов) Экспорт
    Число = 0;
    Для Индекс = 0 По МассивБайтов.Количество() - 1 Цикл
        Число = Число + МассивБайтов[Индекс] * (256 ^ Индекс);
    КонецЦикла;
    Возврат Число;
КонецФункции

// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = Прав(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. БайтыВЧисло: Преобразует массив байтов в число, используя байты как коэффициенты степеней 256.
  2. Прав: Используется для извлечения последних байтов из HMAC.
  3. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  4. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя БайтыВЧисло для преобразования массива байтов в число.

3 Apr, 10:35

Что означает ^ в строке Число = Число + МассивБайтов[Индекс] * (256 ^ Индекс);

3 Apr, 10:36

В языке программирования 1С оператор ^ используется для возведения числа в степень. В данном контексте 256 ^ Индекс означает возведение числа 256 в степень, равную значению переменной Индекс.

Пояснение:

  • 256 ^ Индекс: Это выражение вычисляет 256 в степени Индекс. Например, если Индекс равен 2, то результат будет 2562=655362562=65536.

Зачем это нужно:

  • В данном случае мы используем это выражение для преобразования массива байтов в число. Каждый байт в массиве рассматривается как коэффициент при соответствующей степени 256. Это позволяет правильно интерпретировать последовательность байтов как единое число.

Пример:

Если у нас есть массив байтов [B0, B1, B2, B3], то число будет вычисляться как:Число=𝐵0×2560+𝐵1×2561+𝐵2×2562+𝐵3×2563Число=B0×2560+B1×2561+B2×2562+B3×2563

Таким образом, каждый байт влияет на итоговое число в зависимости от своей позиции в массиве.

Если у вас есть дополнительные вопросы или требуется дальнейшее пояснение, дайте знать!

3 Apr, 10:36

В языке 1С вместо этого испольуется команада pow. Например pow(5,3) возведет 5 в степень 3. Перепиши код

3 Apr, 10:44

Понял, давайте заменим возведение в степень с использованием функции pow в языке 1С.

Вот обновленный код:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем буфер двоичных данных
    Буфер = Новый ДвоичныеДанные(Строка);

    // Получаем массив байтов из буфера
    МассивБайтов = Новый Массив;
    Длина = Буфер.Длина;

    Для Индекс = 0 По Длина - 1 Цикл
        МассивБайтов.Добавить(Буфер.ПолучитьБайт(Индекс));
    КонецЦикла;

    Возврат МассивБайтов;
КонецФункции

// Функция для преобразования массива байтов в число
Функция БайтыВЧисло(МассивБайтов) Экспорт
    Число = 0;
    Для Индекс = 0 По МассивБайтов.Количество() - 1 Цикл
        Число = Число + МассивБайтов[Индекс] * pow(256, Индекс);
    КонецЦикла;
    Возврат Число;
КонецФункции

// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = Прав(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. pow: Используется для возведения числа в степень.
  2. Прав: Используется для извлечения последних байтов из HMAC.
  3. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  4. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя pow для возведения в степень.

3 Apr, 10:44

Попробуй переписать код без использования функции ДвоичныеДанные

3 Apr, 10:51

Конечно, давайте перепишем код без использования функции ДвоичныеДанные. Мы будем работать с массивами байтов напрямую.

Вот обновленный код:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем массив байтов из строки
    МассивБайтов = Новый Массив;
    Для Индекс = 1 По СтрДлина(Строка) Цикл
        МассивБайтов.Добавить(СимволВЦелое(Сред(Строка, Индекс, 1)));
    КонецЦикла;
    Возврат МассивБайтов;
КонецФункции

// Функция для преобразования массива байтов в число
Функция БайтыВЧисло(МассивБайтов) Экспорт
    Число = 0;
    Для Индекс = 0 По МассивБайтов.Количество() - 1 Цикл
        Число = Число + МассивБайтов[Индекс] * pow(256, Индекс);
    КонецЦикла;
    Возврат Число;
КонецФункции

// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = Прав(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. СтрокаВБайты: Преобразует строку в массив байтов, используя функцию СимволВЦелое для получения кода символа.
  2. БайтыВЧисло: Преобразует массив байтов в число, используя функцию pow для возведения в степень.
  3. Прав: Используется для извлечения последних байтов из HMAC.
  4. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  5. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя массивы байтов напрямую.

3 Apr, 10:51

Что делает функция СимволВЦелое

3 Apr, 10:57

Функция СимволВЦелое в языке программирования 1С используется для получения числового кода символа в строке. Она возвращает целое число, представляющее код символа в кодировке, используемой в системе (например, Unicode).

Синтаксис:

CopyСимволВЦелое(Символ)

Параметры:

  • Символ: Символ, для которого нужно получить числовой код. Это может быть строка длиной 1 символ.

Пример использования:

CopyСимвол = "A";
КодСимвола = СимволВЦелое(Символ); // КодСимвола будет равен 65 для символа 'A' в кодировке Unicode

Пояснения:

  • Числовой код: Это значение, которое представляет символ в таблице символов (например, Unicode). Например, символ ‘A’ имеет код 65 в Unicode.
  • Использование: Эта функция полезна, когда нужно работать с символами на уровне их числовых представлений, например, при шифровании или обработке текста.

Если у вас есть другие вопросы или требуется дополнительная помощь, дайте знать!

3 Apr, 10:57

В 1С нет такой функции. Используй вместо неё функцию КодСимвола

3 Apr, 10:59

Понял, давайте заменим использование функции СимволВЦелое на КодСимвола в языке 1С. Функция КодСимвола возвращает числовой код символа в строке.

Вот обновленный код:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем массив байтов из строки
    МассивБайтов = Новый Массив;
    Для Индекс = 1 По СтрДлина(Строка) Цикл
        МассивБайтов.Добавить(КодСимвола(Сред(Строка, Индекс, 1)));
    КонецЦикла;
    Возврат МассивБайтов;
КонецФункции

// Функция для преобразования массива байтов в число
Функция БайтыВЧисло(МассивБайтов) Экспорт
    Число = 0;
    Для Индекс = 0 По МассивБайтов.Количество() - 1 Цикл
        Число = Число + МассивБайтов[Индекс] * pow(256, Индекс);
    КонецЦикла;
    Возврат Число;
КонецФункции

// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), БайтыКлюча).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = Прав(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. КодСимвола: Используется для получения числового кода символа.
  2. Прав: Используется для извлечения последних байтов из HMAC.
  3. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  4. ВыполнитьШифрование: Используется для генерации HMAC-SHA1.

Этот код должен корректно работать в среде 1С, используя КодСимвола для получения числового кода символа.

3 Apr, 10:59

В функции ВыполнитьШифрование на входе должны быть строки а не массивы

3 Apr, 11:02

Понял, давайте изменим функцию ВыполнитьШифрование, чтобы она принимала строки на входе. Мы будем преобразовывать строки в массивы байтов непосредственно внутри этой функции.

Вот обновленный код:

Copy// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    // Создаем массив байтов из строки
    МассивБайты = Новый Массив;
    Для Индекс = 1 По СтрДлина(Строка) Цикл
        МассивБайты.Добавить(КодСимвола(Сред(Строка, Индекс, 1)));
    КонецЦикла;
    Возврат МассивБайты;
КонецФункции

// Функция для преобразования массива байтов в число
Функция БайтыВЧисло(МассивБайты) Экспорт
    Число = 0;
    Для Индекс = 0 По МассивБайты.Количество() - 1 Цикл
        Число = Число + МассивБайты[Индекс] * pow(256, Индекс);
    КонецЦикла;
    Возврат Число;
КонецФункции

// Функция для выполнения шифрования
Функция ВыполнитьШифрование(СтрокаДляХеш, КлючДляХеш) Экспорт
    СтрокаНули = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
    СтрокаОПАД = "5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c";
    СтрокаИПАД = "36363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636";

    К = СтрокаВБайты(КлючДляХеш);

    К = ПолучитьБуферДвоичныхДанныхИзМассиваБайтов(К);
    Нули = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаНули);
    Нули.ЗаписатьПобитовоеИли(0, К);
    Шаг1 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(Нули);

    ИПАД = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаИПАД);
    БуферШаг1 = ПолучитьБуферДвоичныхДанныхИзМассиваБайтов(Шаг1);
    ИПАД.ЗаписатьПобитовоеИсключительноеИли(0, БуферШаг1);
    Шаг2 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ИПАД);

    БуферШаг2 = ПолучитьБуферДвоичныхДанныхИзМассиваБайтов(Шаг2);
    БуферТекст = ПолучитьБуферДвоичныхДанныхИзСтроки(СтрокаДляХеш);
    БуферШаг3 = БуферШаг2.Соединить(БуферТекст);
    Шаг3 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(БуферШаг3);

    ХД = Новый ХешированиеДанных(ХешФункция.SHA1);
    ХД.Добавить(Шаг3);
    Шаг4 = ХД.ХешСумма;

    ОПАД = ПолучитьБуферДвоичныхДанныхИзHexСтроки(СтрокаОПАД);
    БуферШаг1 = ПолучитьБуферДвоичныхДанныхИзМассиваБайтов(Шаг1);
    ОПАД.ЗаписатьПобитовоеИсключительноеИли(0, БуферШаг1);
    Шаг5 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(ОПАД);

    БуферШаг4 = ПолучитьБуферДвоичныхДанныхИзМассиваБайтов(Шаг4);
    БуферШаг5 = ПолучитьБуферДвоичныхДанныхИзМассиваБайтов(Шаг5);
    БуферШаг6 = БуферШаг5.Соединить(БуферШаг4);
    Шаг6 = ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных(БуферШаг6);

    ХД = Новый ХешированиеДанных(ХешФункция.SHA1);
    ХД.Добавить(Шаг6);
    Шаг7 = ХД.ХешСумма;

    СтруктураРезультата = Новый Структура;
    СтруктураРезультата.Вставить("ДД", Шаг7);
    СтруктураРезультата.Вставить("HexСтрока", НРег(ПолучитьHexСтрокуИзДвоичныхДанных(Шаг7)));
    СтруктураРезультата.Вставить("Base64Строка", Base64Строка(Шаг7));

    Возврат СтруктураРезультата;
КонецФункции

// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч, Время = Неопределено) Экспорт
    // Если время не задано, используем текущую дату и время
    Если Время = Неопределено Тогда
        ТекущаяДатаВремя = ТекущаяДата();
    Иначе
        ТекущаяДатаВремя = Время;
    КонецЕсли;

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), СекретныйКлюч).ДД;

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Получаем последние 4 байта HMAC
    ПоследниеБайты = Прав(HMAC, 4);

    // Преобразуем байты в число
    Число = БайтыВЧисло(ПоследниеБайты);

    // Применяем модуль 10^6 для получения 6-значного числа
    TOTP = Число % 1000000;

    // Форматируем TOTP как 6-значное число
    TOTP = Формат(TOTP, "ЧГ=0;ЧН=6");

    Возврат TOTP;
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  1. КодСимвола: Используется для получения числового кода символа.
  2. Прав: Используется для извлечения последних байтов из HMAC.
  3. Дата(1970, 1, 1): Используется для вычисления количества 30-секундных интервалов с момента эпохи Unix.
  4. ВыполнитьШифрование: Теперь принимает строки и преобразует их в массивы байтов внутри функции.

Этот код должен корректно работать в среде 1С, используя строки на входе функции ВыполнитьШифрование.

3 Apr, 11:02

Ладно, забудь всё. Бред получается какой то

3 Apr, 11:11

Понял, давайте попробуем упростить задачу. Давайте начнем с самого начала и попробуем реализовать генерацию TOTP кода в 1С, используя только доступные функции и методы.

Основные шаги:

  1. Получение времени: Мы будем использовать текущую дату и время.
  2. Преобразование времени в интервал: Вычислим количество 30-секундных интервалов с момента эпохи Unix.
  3. Генерация HMAC-SHA1: Используем встроенные функции для генерации HMAC.
  4. Получение TOTP кода: Извлечем нужные байты из HMAC и преобразуем их в 6-значный код.

Давайте начнем с простого примера, который выполняет эти шаги. Если у вас есть конкретные требования или ограничения, дайте знать!

Пример кода:

Copy// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч) Экспорт
    // Получаем текущую дату и время
    ТекущаяДатаВремя = ТекущаяДата();

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = (ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30;

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), СекретныйКлюч);

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    МассивБайтов = Новый Массив;
    Для Индекс = 1 По СтрДлина(Строка) Цикл
        МассивБайтов.Добавить(КодСимвола(Сред(Строка, Индекс, 1)));
    КонецЦикла;
    Возврат МассивБайтов;
КонецФункции

// Функция для выполнения шифрования (HMAC-SHA1)
Функция ВыполнитьШифрование(СтрокаДляХеш, КлючДляХеш) Экспорт
    // Здесь должна быть реализация HMAC-SHA1
    // На данный момент просто возвращаем заглушку
    Возврат "Заглушка HMAC";
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Здесь должна быть реализация извлечения и преобразования байтов в TOTP
    // На данный момент просто возвращаем заглушку
    Возврат "123456";
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  • СтрокаВБайты: Преобразует строку в массив байтов.
  • ВыполнитьШифрование: Заглушка для генерации HMAC-SHA1.
  • ПолучитьTOTPКод: Заглушка для получения TOTP кода из HMAC.

Если у вас есть конкретные требования или ограничения, дайте знать, и мы сможем адаптировать код под ваши нужды!

3 Apr, 11:11

В переменной ВремяСЭпохи должно быть целое число или дробное? Сейчас дробное

3 Apr, 11:14

В алгоритме TOTP (Time-Based One-Time Password) временной интервал, используемый для генерации кода, должен быть целым числом. Это связано с тем, что TOTP коды обновляются через равные промежутки времени (обычно 30 секунд), и для каждого такого интервала генерируется уникальный код.

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

Вот исправленный код:

Copy// Функция для получения TOTP кода
Функция ПолучитьTOTP(СекретныйКлюч) Экспорт
    // Получаем текущую дату и время
    ТекущаяДатаВремя = ТекущаяДата();

    // Получаем количество 30-секундных интервалов с момента эпохи Unix (1 января 1970 года)
    ВремяСЭпохи = Цел((ТекущаяДатаВремя - Дата(1970, 1, 1)) / 30);

    // Преобразуем секретный ключ в массив байтов
    БайтыКлюча = СтрокаВБайты(СекретныйКлюч);

    // Генерируем HMAC-SHA1 от временного интервала с использованием секретного ключа
    HMAC = ВыполнитьШифрование(Строка(ВремяСЭпохи), СекретныйКлюч);

    // Получаем TOTP код
    TOTP = ПолучитьTOTPКод(HMAC);

    Возврат TOTP;
КонецФункции

// Функция для преобразования строки в массив байтов
Функция СтрокаВБайты(Строка) Экспорт
    МассивБайтов = Новый Массив;
    Для Индекс = 1 По СтрДлина(Строка) Цикл
        МассивБайтов.Добавить(КодСимвола(Сред(Строка, Индекс, 1)));
    КонецЦикла;
    Возврат МассивБайтов;
КонецФункции

// Функция для выполнения шифрования (HMAC-SHA1)
Функция ВыполнитьШифрование(СтрокаДляХеш, КлючДляХеш) Экспорт
    // Здесь должна быть реализация HMAC-SHA1
    // На данный момент просто возвращаем заглушку
    Возврат "Заглушка HMAC";
КонецФункции

// Функция для получения TOTP кода из HMAC
Функция ПолучитьTOTPКод(HMAC) Экспорт
    // Здесь должна быть реализация извлечения и преобразования байтов в TOTP
    // На данный момент просто возвращаем заглушку
    Возврат "123456";
КонецФункции

// Пример использования
СекретныйКлюч = "12345678901234567890"; // Пример секретного ключа
TOTP = ПолучитьTOTP(СекретныйКлюч);
Сообщить(TOTP);

Пояснения:

  • Цел(): Используется для округления значения до ближайшего целого числа. Это необходимо для корректной работы алгоритма TOTP.

Теперь ВремяСЭпохи будет целым числом, что соответствует требованиям алгоритма TOTP. Если у вас есть дополнительные вопросы или требуется помощь с реализацией HMAC-SHA1, дайте знать!

3 Apr, 11:14

Ок, пока вроде нормально. Давай реализуем функцию ВыполнитьШифрование

3 Apr, 11:15

Отлично, давайте реализуем функцию ВыполнитьШифрование, которая будет выполнять HMAC-SHA1. Для этого нам нужно будет использовать встроенные функции 1С для работы с хешированием.

Основные шаги:

  1. Преобразование строк в массивы байтов: Мы уже имеем функцию СтрокаВБайты.
  2. Генерация HMAC-SHA1: Используем встроенные функции для вычисления HMAC.

Вот как это можно сделать:

Copy// Функция для выполнения шифрования (HMAC-SHA1)
Функция ВыполнитьШифрование(СтрокаДляХеш, КлючДляХеш) Экспорт
    // Преобразуем строки в массивы байтов
    БайтыСтроки = СтрокаВБайты(СтрокаДляХеш);
    БайтыКлюча = СтрокаВБайты(КлючДляХеш);

    // Если ключ короче 64 байт, дополняем его нулями до 64 байт
    Если БайтыКлюча.Количество() < 64 Тогда
        Для i = БайтыКлюча.Количество() + 1 По 64 Цикл
            БайтыКлюча.Добавить(0);
        КонецЦикла;
    КонецЕсли;

    // Если ключ длиннее 64 байт, хешируем его с помощью SHA-1
    Если БайтыКлюча.Количество() > 64 Тогда
        ХешКлюча = Новый ХешированиеДанных(ХешФункция.SHA1);
        ХешКлюча.Добавить(БайтыКлюча);
        БайтыКлюча = ХешКлюча.ХешСумма;
    КонецЕсли;

    // Создаем внутренний и внешний паддинг
    ИПАД = Новый Массив;
    ОПАД = Новый Массив;

    Для i = 0 По 63 Цикл
        ИПАД.Добавить(БайтыКлюча[i] XOR 0x36);
        ОПАД.Добавить(БайтыКлюча[i] XOR 0x5C);
    КонецЦикла;

    // Добавляем внутренний паддинг к строке
    Для i = 0 По 63 Цикл
        БайтыСтроки.Вставить(ИПАД[i], i);
    КонецЦикла;

    // Вычисляем внутренний хеш
    ВнутреннийХеш = Новый ХешированиеДанных(ХешФункция.SHA1);
    ВнутреннийХеш.Добавить(БайтыСтроки);
    ВнутреннийХешСумма = ВнутреннийХеш.ХешСумма;

    // Добавляем внешний паддинг к внутреннему хешу
    Для i = 0 По 63 Цикл
        ВнутреннийХешСумма.Вставить(ОПАД[i], i);
    КонецЦикла;

    // Вычисляем окончательный HMAC
    ВнешнийХеш = Новый ХешированиеДанных(ХешФункция.SHA1);
    ВнешнийХеш.Добавить(ВнутреннийХешСумма);
    HMAC = ВнешнийХеш.ХешСумма;

    Возврат HMAC;
КонецФункции

Пояснения:

  • ИПАД и ОПАД: Это внутренний и внешний паддинги, используемые в алгоритме HMAC.
  • XOR: Побитовая операция исключающее ИЛИ, используемая для создания паддингов.
  • ХешированиеДанных: Используется для вычисления SHA-1 хеша.

Этот код должен корректно выполнять HMAC-SHA1 в среде 1С. Если у вас есть дополнительные вопросы или требуется помощь, дайте знать!

3 Apr, 11:16

Вместо XOR используй функцию ПобитовоеИсключительноеИли(Число1,Число2)

3 Apr, 11:21

Понял, давайте заменим операцию XOR на функцию ПобитовоеИсключительноеИли в языке 1С. Эта функция выполняет побитовую операцию исключающее ИЛИ для двух чисел.

Вот обновленный код:

Copy// Функция для выполнения шифрования (HMAC-SHA1)
Функция ВыполнитьШифрование(СтрокаДляХеш, КлючДляХеш) Экспорт
    // Преобразуем строки в массивы байтов
    БайтыСтроки = СтрокаВБайты(СтрокаДляХеш);
    БайтыКлюча = СтрокаВБайты(КлючДляХеш);

    // Если ключ короче 64 байт, дополняем его нулями до 64 байт
    Если БайтыКлюча.Количество() < 64 Тогда
        Для i = БайтыКлюча.Количество() + 1 По 64 Цикл
            БайтыКлюча.Добавить(0);
        КонецЦикла;
    КонецЕсли;

    // Если ключ длиннее 64 байт, хешируем его с помощью SHA-1
    Если БайтыКлюча.Количество() > 64 Тогда
        ХешКлюча = Новый ХешированиеДанных(ХешФункция.SHA1);
        ХешКлюча.Добавить(БайтыКлюча);
        БайтыКлюча = ХешКлюча.ХешСумма;
    КонецЕсли;

    // Создаем внутренний и внешний паддинг
    ИПАД = Новый Массив;
    ОПАД = Новый Массив;

    Для i = 0 По 63 Цикл
        ИПАД.Добавить(ПобитовоеИсключительноеИли(БайтыКлюча[i], 0x36));
        ОПАД.Добавить(ПобитовоеИсключительноеИли(БайтыКлюча[i], 0x5C));
    КонецЦикла;

    // Добавляем внутренний паддинг к строке
    Для i = 0 По 63 Цикл
        БайтыСтроки.Вставить(ИПАД[i], i);
    КонецЦикла;

    // Вычисляем внутренний хеш
    ВнутреннийХеш = Новый ХешированиеДанных(ХешФункция.SHA1);
    ВнутреннийХеш.Добавить(БайтыСтроки);
    ВнутреннийХешСумма = ВнутреннийХеш.ХешСумма;

    // Добавляем внешний паддинг к внутреннему хешу
    Для i = 0 По 63 Цикл
        ВнутреннийХешСумма.Вставить(ОПАД[i], i);
    КонецЦикла;

    // Вычисляем окончательный HMAC
    ВнешнийХеш = Новый ХешированиеДанных(ХешФункция.SHA1);
    ВнешнийХеш.Добавить(ВнутреннийХешСумма);
    HMAC = ВнешнийХеш.ХешСумма;

    Возврат HMAC;
КонецФункции

Пояснения:

  • ПобитовоеИсключительноеИли: Используется для выполнения операции XOR между двумя числами.
  • ИПАД и ОПАД: Внутренний и внешний паддинги, используемые в алгоритме HMAC.
  • ХешированиеДанных: Используется для вычисления SHA-1 хеша.

Этот код должен корректно выполнять HMAC-SHA1 в среде 1С, используя функцию ПобитовоеИсключительноеИли. Если у вас есть дополнительные вопросы или требуется помощь, дайте знать!

3 Apr, 11:21

Подключение к фоновым заданиям 1С

Случаются ситуации, что фоновое задание запущенное пользователем, продолжает работать и после выхода самого пользователя из 1С. Как же исключить повторный запуск фонового задания пользователем? Ну и заодно показать текущий прогресс выполнения задания. На самом деле всё оказалось просто. В 1С есть функционал получения полного списка выполняемых в текущий момент фоновых заданий:

ФоновыеЗадания.ПолучитьФоновыеЗадания();		

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

&НаКлиенте
Процедура ВыгрузкаКвитанцийНаБумаге(Команда)
	этаформа.ИндикаторВыгрузкаКвитанций=0;
	ЗапуститьФЗВыгрузкиКвитанций();					
	ПодключитьОбработчикОжидания("ИндикаторВыполненияВыгрузкиКвитанцийИсточник1",1,ложь);
	ПодключитьОбработчикОжидания("ИндикаторВыполненияВыгрузкиКвитанцийИсточник2",1,ложь);
КонецПроцедуры       

&НаСервере
Процедура ЗапуститьФЗВыгрузкиКвитанций()		
	Фоновые = ФоновыеЗадания.ПолучитьФоновыеЗадания();		
	Для Каждого Фоновое из Фоновые Цикл
		если Фоновое.ИмяМетода="СК_ГР_ГеоаналитикаЗагрузки.ВыгрузитьКвитанцииВГеоаналитикуИсточник1" тогда
			если Фоновое.Состояние<>СостояниеФоновогоЗадания.ЗавершеноАварийно и Фоновое.Состояние<>СостояниеФоновогоЗадания.Завершено тогда
				сообщить("-предыдущее задание еще не завершено!");
				объект.ФЗ_ВыгрузкаКвитанций = Фоновое.УникальныйИдентификатор;									
				возврат;
			конецесли;
		конецесли;				
		если Фоновое.ИмяМетода="СК_ГР_ГеоаналитикаЗагрузки.ВыгрузитьКвитанцииВГеоаналитикуИсточник2" тогда
			сообщить("-предыдущее задание еще не завершено!");
			если Фоновое.Состояние<>СостояниеФоновогоЗадания.ЗавершеноАварийно и Фоновое.Состояние<>СостояниеФоновогоЗадания.Завершено тогда
				сообщить("-предыдущее задание еще не завершено!");
				объект.ФЗ_ВыгрузкаКвитанций2 = Фоновое.УникальныйИдентификатор;									
				возврат;
			конецесли;
			возврат;
		 конецесли;							
	конеццикла;	
	
	Парм=Новый Структура("Период,ПроверятьНаличиевБД",объект.Период,объект.ПроверятьНаличиевБД);
	МассивПараметров = Новый Массив;
	МассивПараметров.Добавить(Парм);
	ФЗ = ФоновыеЗадания.Выполнить("СК_ГР_ГеоаналитикаЗагрузки.ВыгрузитьКвитанцииВГеоаналитикуИсточник1",МассивПараметров);	
	объект.ФЗ_ВыгрузкаКвитанций = ФЗ.УникальныйИдентификатор;						
	ФЗ2 = ФоновыеЗадания.Выполнить("СК_ГР_ГеоаналитикаЗагрузки.ВыгрузитьКвитанцииВГеоаналитикуИсточник2",МассивПараметров);	
	объект.ФЗ_ВыгрузкаКвитанций2 = ФЗ2.УникальныйИдентификатор;							
КонецПроцедуры

Т.е. если фоновое уже запущено — то просто получаем его идентификатор и отображаем прогресс бар. Если нет — запускаем

1 2 3 4 5 6 50