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

SQL: удаление дублей записей в таблице

Ну задача написания нужного запроса сводится к следующим шагам:

  1. Сделаем выборку записей, сгруппировав по дублирующемуся полю. Получим количество дублей, и максимальный id дубля (чтобы знать какой удалять)
  2. Если количество записей больше 1, то запись с максимальным id удалим

В итоге запрос может получится примерно таким:

delete from ls_indications where id in (
	select max_id from (
		select count(ls) as cnt,max(id) as max_id from ls_indications where period='2025-03-01' group by ls
	) as zxc where zxc.cnt>1	
)

P.S. Если дублей больше 2-х, то запрос нужно выполнить несколько раз, т.к. он удаляет за один раз только одну дублирующуюся запись. Можно конечно наваять скрипт, который этот недостаток убирает, но смысла обычно нет, проще запрос выполнить несколько раз

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

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

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

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

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

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

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

1с: Работа с деревом значений

Задача: создать инструмент для распределения заявок по дням.

Решение: Наиболее удобным вариант я подумал что будет создание некого «дерева», узлами которого будут даты, а «ветвями» — заявки. Заявки можно будет перетаскивать между датами, тем самым равномерно распределяя нагрузку по дням.

Для того чтобы работать с деревьями, в 1С есть специальный тип: Дерево значений. Основной сущностностью у него являются строки. У каждой строки могут быть реквизиты (колонки). В то-же время каждая строка может иметь «потомков» — другие строки.

Создадим на форме «ДеревоОтключений» с типом «Дерево значений», и добавим у него реквизиты:

И перетащим его на форму. Далее по событию открытия, заполним дерево:

ДО = РеквизитФормыВЗначение("ДеревоОтключений");
	ДО.Строки.Очистить();
	
   	Для Счетчик = 0 По Число(Сред(КонецМесяца(объект.ПериодОтключения), 1, 2)) Цикл
    	УДеньМесяца=ДО.Строки.Добавить();
		если Счетчик=0 тогда
			УДеньМесяца.ДатаОтключения="не распределено";
		иначе	
			УДеньМесяца.ДатаОтключения=Формат(Дата(Год(объект.ПериодОтключения),Месяц(объект.ПериодОтключения),Счетчик),"ДФ=dd.MM.yyyy");						
		конецесли;
		УДеньМесяца.expanded=false;
		кол=0;
		для каждого стр из МассивОтключаемых[Счетчик] цикл
			ссср=УДеньМесяца.Строки.Добавить();
			ссср.Отключаемый=стр;
			ссср.ЛС=Строка(стр.ЛС);
			ссср.Адрес=стр.АдресПотребителя;
			кол=кол+1;
		конеццикла;			
		если кол>0 тогда
			УДеньМесяца.ЛС=Строка(кол);
		конецесли;
		
		
    КонецЦикла;

	ЗначениеВРеквизитФормы(ДО,"ДеревоОтключений");

Получаем такую чудную картинку:

Теперь осталось только запретить перетаскивание во все колонки кроме «ДатаОтключения», чтобы избежать «не правильных» деревьев. Для этого заполним событие «ПриПеретаскивании»:

&НаКлиенте
Процедура ДеревоОтключенийПеретаскивание(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка, Строка, Поле)
//запретим если имя колонки куда тащим отличается от "ДатаОтключения"
	если Поле.Имя<>"ДеревоОтключенийДатаОтключения" тогда
		СтандартнаяОбработка=ложь;
	конецесли;	                            
//запретим если дата отключения пустая
	Куда=ДеревоОтключений.НайтиПоИдентификатору(Строка);
	если Куда.ДатаОтключения="" тогда
		СтандартнаяОбработка=ложь;
	конецесли;	
//запретим перетаскивание "в корень"
	если Куда.ДатаОтключения=ДеревоОтключений.НайтиПоИдентификатору(Элементы.ДеревоОтключений.ТекущаяСтрока).ПолучитьРодителя().ДатаОтключения тогда
		СтандартнаяОбработка=ложь;
	конецесли;	
КонецПроцедуры

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

&НаКлиенте
Процедура ДеревоОтключенийОкончаниеПеретаскивания(Элемент, ПараметрыПеретаскивания, СтандартнаяОбработка)
	ОбновляюКоличествоЛС();	
КонецПроцедуры

&НаКлиенте
Функция ОбновляюКоличествоЛС()
	 ЭлементыДерева = ДеревоОтключений.ПолучитьЭлементы();	
	 для каждого стр из ЭлементыДерева цикл
		 клв=стр.ПолучитьЭлементы().Количество();
		 если клв<50 тогда
	 		стр.ЛС=клв;
		 конецесли;
	 конеццикла;	 
КонецФункции

В рекруссию не пошел, т.к. в моём случае заведомо известно, что ветвей не более 1

1 10 11 12 13 14 310