В расширении представлены алгоритмы:
- Кодирования / декодирования строки в base58.
- Кодирование строк utf8 в массив байт и декодирование массива байт в строку uft8
Данные алгоритмы перенесены с JS. За основу взята библиотека ts-lib-crypto. Внешние компоненты в разработки не использовались. Для использования алгоритмов необходима платформа версии не ниже 8.3.11
Разработка распространяется под лицензией MIT.
Исходный код всех модулей представлен ниже:
// Функция - Base58 encode
//
// Параметры:
// Буфер - Массив - Массив байт, Результат функции base58 decode
//
// Возвращаемое значение:
// Строка - Результат кодирование байт в строку
//
Функция base58_encode(Знач Буфер) Экспорт
Если ТипЗнч(Буфер) <> ТипЗнч(Новый Массив) Тогда
Возврат "";
КонецЕсли;
Если Буфер.Количество() = 0 Тогда
Возврат "";
КонецЕсли;
Числа = Новый Массив;
Числа.Добавить(0);
сч = 0;
Пока сч < Буфер.Количество() Цикл
счч = 0;
Пока счч < Числа.Количество() Цикл
Числа[счч] = ПобитовыйСдвигВлево(Числа[счч], 8);
счч = счч + 1;
КонецЦикла;
Числа[0] = Числа[0] + Буфер[сч];
carry = 0;
к = 0;
Пока к < Числа.Количество() Цикл
Числа[к] = Числа[к] + carry;
Если Числа[к] % 58 = 0 Тогда
carry = ПобитовоеИли(Числа[к] / 58, 0);
Иначе
carry = Числа[к] / 58;
carry = Число(Лев(carry, СтрНайти(carry, ",") - 1));
Если ЗначениеЗаполнено(carry) тогда
carry = Число(carry);
Иначе
carry = 0;
КонецЕсли;
КонецЕсли;
Числа[к] = Числа[к] % 58;
к = к + 1;
КонецЦикла;
Пока carry <> 0 Цикл
Числа.Добавить(carry % 58);
Если carry % 58 = 0 Тогда
carry = ПобитовоеИли((carry / 58), 0);
Иначе
carry = carry / 58;
carry = Число(Лев(carry, СтрНайти(carry, ",") - 1));
Если ЗначениеЗаполнено(carry) тогда
carry = Число(carry);
Иначе
carry = 0;
КонецЕсли;
КонецЕсли;
КонецЦикла;
сч = сч + 1;
КонецЦикла;
сч = 0;
Пока (Буфер[сч] = "0" И сч < Буфер.Количество() - 1) Цикл
Числа.Добавить(0);
сч = сч + 1;
КонецЦикла;
ALPHABET = Crypt_ОбщегоНазначенияКлиентСевер.ПолучитьСтруктуруALPHABET();
Результат = "";
Для Каждого Индекс из Crypt_ОбщегоНазначенияКлиентСевер.РазвернутьМассив(Числа) Цикл
Результат = Результат + ALPHABET.Массив[Индекс];
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Base58 decode
//
// Параметры:
// тСтр - Строка - Строка
//
// Возвращаемое значение:
// Массив - данные в Base58
//
Функция base58_decode(Знач тСтр) Экспорт
ALPHABET = Crypt_ОбщегоНазначенияКлиентСевер.ПолучитьСтруктуруALPHABET();
Если Не ЗначениеЗаполнено(тСтр) Тогда
Возврат Новый Массив;
КонецЕсли;
Байты = Новый Массив;
Байты.Добавить(0);
Для сч = 1 По СтрДлина(тСтр) Цикл
с = Сред(тСтр, сч, 1);
Если ALPHABET.Массив.Найти(с) = Неопределено Тогда
ВызватьИсключение "There is no character " + с + " in the Base58 sequence!";
КонецЕсли;
счч = 0;
Пока счч < Байты.Количество() Цикл
Байты[счч] = Байты[счч] * 58;
счч = счч + 1;
КонецЦикла;
Байты[0] = Байты[0] + (ALPHABET.Массив.Найти(с));
carry = 0;
счч = 0;
Пока счч < Байты.Количество() Цикл
Байты[счч] = Байты[счч] + carry;
carry = ПобитовыйСдвигВправо(Байты[счч], 8);
Байты[счч] = ПобитовоеИ(Байты[счч], 255);
счч = счч + 1;
КонецЦикла;
Пока carry <> 0 Цикл
Байты.Добавить(ПобитовоеИ(carry, 255));
carry = ПобитовыйСдвигВправо(carry, 8);
КонецЦикла;
КонецЦикла;
сч = 1;
Пока (Сред(тСтр, сч, 1) = "1" и сч < Байты.Количество()) Цикл
Байты.Добавить(0);
КонецЦикла;
Возврат Crypt_ОбщегоНазначенияКлиентСевер.РазвернутьМассив(Байты);
КонецФункции
///////////////////////////////////////////////////////////////////////////////////
//Модуль - Общего назначения Клиент Сервер
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
#Область ОбщиеПроцедурыФункции
// Функция - Получить структуру ALPHABET
//
// Возвращаемое значение:
// Структура - Ключи струкруры: Строка, Массив
//
Функция ПолучитьСтруктуруALPHABET() Экспорт
Результат = Новый Структура;
Результат.Вставить("Строка",
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
ALPHABET_СРазделителями = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,"+
"L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
Результат.Вставить("Массив", РазложитьСтрокуВМассив(ALPHABET_СРазделителями));
Возврат Результат;
КонецФункции
#КонецОбласти
///////////////////////////////////////////////////////////////////////////////////
#Область Массивы
// Функция - Разложить строку в массив
//
// Параметры:
// Стр - Строка - Строка с разделителями
// Разделитель - Разделитель - Разделитель подстрок
//
// Возвращаемое значение:
// Массив - Массив подстрок
//
Функция РазложитьСтрокуВМассив(Знач Стр, Разделитель = ",") Экспорт
Результат = Новый Массив;
Строки = СтрЗаменить(Стр, Разделитель, Символы.ПС);
Для Индекс = 1 По СтрЧислоСтрок(Строки) Цикл
Результат.Добавить(СтрПолучитьСтроку(Строки, Индекс));
КонецЦикла;
Возврат Результат;
КонецФункции
// Функция - Разложить массив в строку
//
// Параметры:
// Массив - Массив - Элементы которого разложим в строку
// Разделитель - Строка - Разделитель элементов массива
//
// Возвращаемое значение:
// Строка - Строка из элементов массива, с раздилителями
//
Функция РазложитьМассивВСтроку(Знач Массив, Разделитель = ",") Экспорт
СтрокаРезультат = "";
Для Каждого ЭлементМассива Из Массив цикл
СтрокаРезультат = СтрокаРезультат + СокрЛП(Строка(ЭлементМассива)) + Разделитель;
КонецЦикла;
СтрокаРезультат = Лев(СтрокаРезультат, СтрДлина(СтрокаРезультат) - 1);
Возврат СтрокаРезультат;
КонецФункции
// Функция - Развернуть массив
//
// Параметры:
// пМассив - Массив - Массив который необходимо развернуть
//
// Возвращаемое значение:
// Массив - Массив с обратной последовательностью элементов
//
Функция РазвернутьМассив(Знач пМассив) Экспорт
рМассив = Новый Массив;
сч = пМассив.Количество() - 1;
Пока сч > -1 Цикл
рМассив.Добавить(пМассив[сч]);
сч = сч - 1;
КонецЦикла;
Возврат рМассив;
КонецФункции
#КонецОбласти
///////////////////////////////////////////////////////////////////////////////////
// Функция - Строка в utf8 массив байт
//
// Параметры:
// тСтрока - Строка - Строка в кодировки uft8
//
// Возвращаемое значение:
// Массив - Массив байт построенный по строке uft8
//
Функция СтрокаВUtf8МассивБайт(Знач тСтрока) Экспорт
МассивUtf8 = Новый Массив;
сч = 1;
Пока сч <= СтрДлина(тСтрока) Цикл
СимвольныйКод = КодСимвола(тСтрока, сч);
Если СимвольныйКод < 128 Тогда
МассивUtf8.Добавить(СимвольныйКод);
ИначеЕсли СимвольныйКод < 2048 Тогда
МассивUtf8.Добавить(ПобитовоеИли(192, ПобитовыйСдвигВправо(СимвольныйКод, 6)));
МассивUtf8.Добавить(ПобитовоеИли(128, ПобитовоеИ(63, СимвольныйКод)));
ИначеЕсли СимвольныйКод < 55296 ИЛИ СимвольныйКод > 57344 Тогда
МассивUtf8.Добавить(ПобитовоеИли(224, ПобитовыйСдвигВправо(СимвольныйКод, 12)));
МассивUtf8.Добавить(ПобитовоеИли(128,
ПобитовоеИ(ПобитовыйСдвигВправо(СимвольныйКод, 6), 63)));
МассивUtf8.Добавить(ПобитовоеИ(128, ПобитовоеИ(СимвольныйКод, 63)));
Иначе
СимвольныйКод = 65536 + ПобитовоеИли(
ПобитовыйСдвигВлево(ПобитовоеИ(СимвольныйКод, 1023), 10),
ПобитовоеИ(КодСимвола(тСтрока, сч + 1), 1023));
МассивUtf8.Добавить(ПобитовоеИли(240, ПобитовыйСдвигВправо(СимвольныйКод, 18)));
МассивUtf8.Добавить(ПобитовоеИли(128,
ПобитовоеИ(ПобитовыйСдвигВправо(СимвольныйКод, 12),63)));
МассивUtf8.Добавить(ПобитовоеИли(128,
ПобитовоеИ(ПобитовыйСдвигВправо(СимвольныйКод, 6), 63)));
МассивUtf8.Добавить(ПобитовоеИли(128, ПобитовоеИ(СимвольныйКод, 63)));
КонецЕсли;
сч = сч + 1;
КонецЦикла;
Возврат МассивUtf8;
КонецФункции
// Функция - Массив байт в utf8 строку
//
// Параметры:
// мБайт - Массив - Массив байт строки формата utf8
//
// Возвращаемое значение:
// Строка - строка раскодированная по массиву байт
//
Функция МассивБайтВUtf8Строку(Знач мБайт) Экспорт
Байт = Неопределено;
Код = Неопределено;
Результат = "";
сч = 0;
Пока сч < мБайт.Количество() Цикл
Байт = мБайт[сч];
Если Байт <= 127 Тогда
Код = Байт;
ИначеЕсли Байт <= 223 Тогда
сч = сч + 1;
Код = ПобитовоеИли(ПобитовыйСдвигВлево(ПобитовоеИ(Байт, 31), 6), ПобитовоеИ(мБайт[сч], 63));
ИначеЕсли Байт <= 239 Тогда
Код = ПобитовоеИли(ПобитовоеИли(ПобитовыйСдвигВлево(ПобитовоеИ(Байт, 15), 12),
ПобитовыйСдвигВлево(ПобитовоеИ(мБайт[сч + 1], 63), 6)),
ПобитовоеИ(мБайт[сч + 2], 63));
сч = сч + 2;
Иначе
Код = 63;
сч = сч + 3;
КонецЕсли;
сч = сч + 1;
Результат = Результат + Символ(Код);
КонецЦикла;
Возврат Результат;
КонецФункции
Разработка не предусматривает интерфейса и состоит только из общих модулей.