Skip to content

Instantly share code, notes, and snippets.

@ftomza
Created March 20, 2018 14:40
Show Gist options
  • Save ftomza/2381166bf053b00688b97aa2938a5e44 to your computer and use it in GitHub Desktop.
Save ftomza/2381166bf053b00688b97aa2938a5e44 to your computer and use it in GitHub Desktop.
1С Модуль обработки
Перем ФорматДатыISO8601;
Перем ФорматДатыКороткий;
Перем ИгнорируемыеЗаголовки;
Перем АлгоритмПодписиВ4;
Функция ПоместитьДвоичныеДанныеВКорзину(Знач Корзина, Знач Регион, Знач ИмяДанных, Данные) Экспорт
ЗапросАмазонки = ПолучитьСтруктуруЗапроса("PUT", Новый Соответствие);
Возврат ВыполнитьОперацию(ЗапросАмазонки,Корзина,Регион,ИмяДанных,Данные);
КонецФункции
Функция ПолучитьДвоичныеДанныеИзКорзины(Знач Корзина, Знач Регион, Знач ИмяДанных, Данные) Экспорт
ЗапросАмазонки = ПолучитьСтруктуруЗапроса("GET", Новый Соответствие);
Возврат ВыполнитьОперацию(ЗапросАмазонки,Корзина,Регион,ИмяДанных,,Данные);
КонецФункции
Функция ВыполнитьОперацию(ЗапросАмазонки, Знач Корзина = "", Знач Регион, Знач Путь = "/", Данные = Неопределено, ДанныеОтвета = Неопределено) Экспорт
Заголовки = Новый Соответствие();
Заголовки.Вставить("Host",Сервер);
Если Не Данные = Неопределено Тогда
Заголовки.Вставить("X-Amz-Content-Sha256", ПолучитьHexСтрокуИзДвоичныхДанных(Криптота.Hash(Данные, ХешФункция.SHA256)));
Иначе
Заголовки.Вставить("X-Amz-Content-Sha256", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
КонецЕсли;
Соединение = Новый HTTPСоединение(Сервер,Порт,,,,,?(Защищенный,Новый ЗащищенноеСоединениеOpenSSL,Неопределено));
Путь = ?(ЗначениеЗаполнено(Корзина),"/"+Корзина+Путь, Путь);
ЗапросАмазонки.HTTPЗапрос = Новый HTTPЗапрос(Путь, Заголовки);
Если Не Данные = Неопределено Тогда
ЗапросАмазонки.HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(Данные);
КонецЕсли;
ПодписатьВ4(Ключ, Секрет, Регион, "", ЗапросАмазонки);
Ответ = Соединение.ВызватьHTTPМетод(ЗапросАмазонки.Метод, ЗапросАмазонки.HTTPЗапрос);
Если Не Ответ.КодСостояния = 200 Тогда
Сообщить("" + Ответ.КодСостояния + " " + Ответ.ПолучитьТелоКакСтроку());
Возврат Ложь;
КонецЕсли;
ДанныеОтвета = Ответ.ПолучитьТелоКакДвоичныеДанные();
Возврат Истина;
КонецФункции
////
//Подпись
//
Процедура ПодписатьВ4(Знач Ключ, Знач Секрет, Знач Регион, Знач ТокенСессии, Запрос) Экспорт
Если Не ЗначениеЗаполнено(Ключ) ИЛИ Не ЗначениеЗаполнено(Секрет) Тогда
Возврат;
КонецЕсли;
ВремяЗапроса = ТекущаяУниверсальнаяДата();
Запрос.HTTPЗапрос.Заголовки.Вставить("X-Amz-Date", Формат(ВремяЗапроса, ФорматДатыISO8601));
Если ЗначениеЗаполнено(ТокенСессии) ТОгда
Запрос.HTTPЗапрос.Заголовки.Вставить("X-Amz-Security-Token", ТокенСессии);
КонецЕсли;
КаноническийЗапрос = ПолучитьКаноническийЗапрос(Запрос, ИгнорируемыеЗаголовки);
СтрокаДляПодписи = ПолучитьСтрокуДляПодписи(ВремяЗапроса, Регион, КаноническийЗапрос);
ПодписанныйКлюч = ПолучитьПодписанныйКлюч(Секрет, Регион, ВремяЗапроса);
Мандат = ПолучитьМандат(Ключ, Регион, ВремяЗапроса);
ПодписанныеЗаголовки = ПолучитьПодписанныеЗаголовки(Запрос, ИгнорируемыеЗаголовки);
Сигнатура = ПолучитСигнатуру(ПодписанныйКлюч, СтрокаДляПодписи);
Запрос.HTTPЗапрос.Заголовки.Вставить("Authorization",
СтрШаблон("%1 Credential=%2, SignedHeaders=%3, Signature=%4",
АлгоритмПодписиВ4,
Мандат,
ПодписанныеЗаголовки,
Сигнатура
)
);
КонецПроцедуры
Функция ПолучитьКаноническийЗапрос(Знач Запрос, Знач ИгнорируемыеЗаголовки)
МассивРезультата = Новый Массив;
МассивРезультата.Добавить(ВРег(Запрос.Метод));
МассивРезультата.Добавить(КодироватьСтроку(Запрос.HTTPЗапрос.АдресРесурса,СпособКодированияСтроки.URLВКодировкеURL));
МассивРезультата.Добавить(ПолучитьПараметрыЗапросаСтрокой(Запрос.ПараметрыЗапроса));
МассивРезультата.Добавить(ПолучитьЗаголовкиСтрокой(Запрос.HTTPЗапрос.Заголовки, ИгнорируемыеЗаголовки));
МассивРезультата.Добавить(ПолучитьКлючиЗаголовковСтрокой(Запрос.HTTPЗапрос.Заголовки, ИгнорируемыеЗаголовки));
МассивРезультата.Добавить(ПолучитьХэшТелаСтрокой(Запрос.HTTPЗапрос));
Возврат СтрСоединить(МассивРезультата,Символы.ПС);
КонецФункции
Функция ПолучитьСтрокуДляПодписи(Знач ВремяЗапроса, Знач Регион, Знач КаноническийЗапрос)
МассивРезультата = Новый Массив;
МассивРезультата.Добавить(АлгоритмПодписиВ4);
МассивРезультата.Добавить(Формат(ВремяЗапроса, ФорматДатыISO8601));
МассивРезультата.Добавить(СтрШаблон("%1/%2/s3/aws4_request",Формат(ВремяЗапроса, ФорматДатыКороткий),Регион));
МассивРезультата.Добавить(ПолучитХешЗначенияСтрокой(КаноническийЗапрос));
Возврат СтрСоединить(МассивРезультата,Символы.ПС);
КонецФункции
Функция ПолучитьПодписанныйКлюч(Знач Секрет, Знач Регион, Знач ВремяЗапроса)
КриптотаДаты = Криптота.HMAC(ПолучитьСтрокуВДвоичныхДанных("AWS4"+Секрет),ПолучитьСтрокуВДвоичныхДанных(Формат(ВремяЗапроса, ФорматДатыКороткий)), ХешФункция.SHA256);
КриптотаРегиона = Криптота.HMAC(КриптотаДаты,ПолучитьСтрокуВДвоичныхДанных(Регион), ХешФункция.SHA256);
КриптотаСервиса = Криптота.HMAC(КриптотаРегиона,ПолучитьСтрокуВДвоичныхДанных("s3"), ХешФункция.SHA256);
ПодписанныйКлюч = Криптота.HMAC(КриптотаСервиса,ПолучитьСтрокуВДвоичныхДанных("aws4_request"), ХешФункция.SHA256);
Возврат ПодписанныйКлюч;
КонецФункции
Функция ПолучитьМандат(Знач Ключ, Знач Регион, Знач ВремяЗапроса)
Возврат СтрШаблон("%1/%2/%3/s3/aws4_request",Ключ,Формат(ВремяЗапроса, ФорматДатыКороткий),Регион);
КонецФункции
Функция ПолучитьПодписанныеЗаголовки(Знач Запрос, Знач ИгнорируемыеЗаголовки)
Возврат ПолучитьКлючиЗаголовковСтрокой(Запрос.HTTPЗапрос.Заголовки, ИгнорируемыеЗаголовки);
КонецФункции
Функция ПолучитСигнатуру(Знач ПодписанныйКлюч, Знач СтрокаДляПодписи)
ПодписанныйКлюч = Криптота.HMAC(ПодписанныйКлюч,ПолучитьСтрокуВДвоичныхДанных(СтрокаДляПодписи), ХешФункция.SHA256);
Возврат НРег(ПолучитьHexСтрокуИзДвоичныхДанных(ПодписанныйКлюч));
КонецФункции
Функция ПолучитьСтруктуруЗапроса(Метод, ПараметрыЗапроса) Экспорт
Возврат Новый Структура("Метод,HTTPЗапрос,ПараметрыЗапроса", Метод, Новый HTTPЗапрос, ПараметрыЗапроса);
КонецФункции
Функция ПолучитьПараметрыЗапросаСтрокой(ПараметрыЗапроса) Экспорт
РезультатМассив = Новый Массив;
СписокЗначений = ПолучитСортированныйСписокКлючЗначение(ПараметрыЗапроса, Ложь);
Для Каждого ПараметрЗапроса Из СписокЗначений Цикл
РезультатМассив.Добавить(КодироватьСтроку(ПараметрЗапроса.Значение,СпособКодированияСтроки.КодировкаURL) + "="
+ КодироватьСтроку(ПараметрЗапроса.Представление,СпособКодированияСтроки.КодировкаURL));
КонецЦикла;
Возврат СтрСоединить(РезультатМассив,"&");
КонецФункции
Функция ПолучитьКлючиЗаголовковСтрокой(Заголовки, ИгнорируемыеЗаголовки)
РезультатМассив = Новый Массив;
СписокЗначений = ПолучитСортированныйСписокКлючЗначение(Заголовки);
Для Каждого Элемент Из СписокЗначений Цикл
Если СтрНайти(НРег(ИгнорируемыеЗаголовки)+",",Элемент.Значение + ",") Тогда
Продолжить;
КонецЕсли;
РезультатМассив.Добавить(Элемент.Значение);
КонецЦикла;
Возврат СтрСоединить(РезультатМассив, ";");
КонецФункции
Функция ПолучитьЗаголовкиСтрокой(Заголовки, ИгнорируемыеЗаголовки)
РезультатМассив = Новый Массив;
СписокЗначений = ПолучитСортированныйСписокКлючЗначение(Заголовки);
Для Каждого Элемент Из СписокЗначений Цикл
Если СтрНайти(НРег(ИгнорируемыеЗаголовки)+",",Элемент.Значение + ",") Тогда
Продолжить;
КонецЕсли;
РезультатМассив.Добавить(Элемент.Значение + ":" + Элемент.Представление);
КонецЦикла;
Возврат СтрСоединить(РезультатМассив, Символы.ПС)+ Символы.ПС;
КонецФункции
Функция ПолучитСортированныйСписокКлючЗначение(ВхСтруктура, ВНРег = Истина)
СписокЗаголовков = Новый СписокЗначений;
Для Каждого Заголовок Из ВхСтруктура Цикл
СписокЗаголовков.Добавить(?(ВНРег,НРег(Заголовок.Ключ),Заголовок.Ключ), СокрЛП(Заголовок.Значение));
КонецЦикла;
СписокЗаголовков.СортироватьПоЗначению();
Возврат СписокЗаголовков
КонецФункции
Функция ПолучитьХэшТелаСтрокой(HTTPЗапрос)
Хеш = HTTPЗапрос.Заголовки["X-Amz-Content-Sha256"];
Если ЗначениеЗаполнено(Хеш) Тогда
Возврат Хеш
КонецЕсли;
Возврат ПолучитХешЗначенияСтрокой(HTTPЗапрос.ПолучитьТелоКакПоток());
КонецФункции
Функция ПолучитХешЗначенияСтрокой(Значение) Экспорт
ХешДанных = Новый ХешированиеДанных(ХешФункция.SHA256);
ХешДанных.Добавить(Значение);
//
//Возврат Криптота.HexToString(ХешДанных.ХешСумма);
Возврат НРег(ПолучитьHexСтрокуИзДвоичныхДанных(ХешДанных.ХешСумма))
КонецФункции
Функция ПолучитьСтрокуВДвоичныхДанных(Значение)
//ПотокДляЗначения = Новый ПотокВПамяти;
//ДанныеЗначения = Новый ЗаписьДанных(ПотокДляЗначения);
//ДанныеЗначения.ЗаписатьСимволы(Значение);
////ДанныеЗначения.СброситьБуферы();
//Возврат ПотокДляЗначения.ЗакрытьИПолучитьДвоичныеДанные();
Возврат ПолучитьДвоичныеДанныеИзСтроки(Значение);
КонецФункции
АлгоритмПодписиВ4 = "AWS4-HMAC-SHA256";
ФорматДатыISO8601 = "Л=en; ДФ=yyyyMMddTHHmmssZ";
ФорматДатыКороткий = "Л=en; ДФ=yyyyMMdd";
ИгнорируемыеЗаголовки = "Authorization,Content-Type,Content-Length,User-Agent";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment