Подписание запросов
Все запросы должны содержать в заголовках подпись, которая формируется при помощи RSA-ключа (OpenSSL). Чтобы проверить корректность подписания запросов от партнеров, нужно предоставить публичный (открытый) ключ с соответствующими документами, сопровождающими этот ключ:
- Акт приёма-передачи открытого ключа
- Соглашение на использование сервиса
Для рабочего слоя с реализацией подписания через OpenSSL ключ должен соответствовать формату RSA и содержать данные юрлица, которое представляет партнёра (в ключе должен содержаться электронный адрес компании и её наименование).
Срок действия RSA-ключа — от 365 до 1825 дней (не более 5 лет).
Создание приватного ключа
Для каждого слоя нужно генерировать отдельный приватный ключ и сертификат с помощью команды:
openssl genrsa -out rsaprivkey.pem 2048
Никому не передавайте приватную часть ключа.
Создание публичного ключа
На основе приватного ключа сформируйте публичный сертификат:
openssl req -days 1825 -new -x509 -key rsaprivkey.pem -out rsaacert.pem
Параметр days
задает нужный срок действия в днях. Его нужно передать сотрудникам банка, отвечающим за сервис.
Файл rsaacert.pem содержит публичную часть ключа, которая выглядит так:
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUOMamoGWXd5FATOQzf74j2tP6tWAwDQYJKoZIhvcNAQEL
...
-----END CERTIFICATE-----
Подписание запроса
Сформируйте запрос в виде строки следующего формата:
'{"Data": {"guaranteeType": "FULFILLMENT", "guaranteeStartDate": "string", "guaranteeEndDate": "string", "guaranteeSum": 0, "clientInn": "string", "tenderCustomerInn": "string", "purchaseType": 0}}'
- В запросе не должно быть переносов и табуляций
- Ключ и его значение должны разделяться двоеточием и пробелом
- Пары «ключ-значение» должны разделяться запятой и пробелом
Пример кода на python, который формирует корректную строку:
import json
request_payload = {
"Data": {
"guaranteeType": "FULFILLMENT",
"guaranteeStartDate": "string",
"guaranteeEndDate": "string",
"guaranteeSum": 0,
"clientInn": "string",
"tenderCustomerInn": "string",
"purchaseType": 0
}
}
sign_payload = json.dumps(request_payload) # Сообщение для подписи
print(sign_payload)
Пример формирования подписи через командную строку
Помещаем сформированную строку с запросом в файл message:
echo -n '{"Data": {"guaranteeType": "FULFILLMENT", "guaranteeStartDate": "string", "guaranteeEndDate": "string", "guaranteeSum": 0, "clientInn": "string", "tenderCustomerInn": "string", "purchaseType": 0}}' > message
Подписываем сообщения, используя алгоритм sha256. Это создаст бинарный файл message.sgn, содержащий подпись.
openssl dgst -sha256 -sign ./rsaprivkey.pem -out ./message.sgn ./message
base64 -i ./message.sgn
Получаем вывод формата:
ITL85xBoFIKmOYF8O6BCilexlkaSD3NgDiOqRgFtKutxhRXcsqt9RsnIaVHiioB7vnIea4XNgePe3h+lrLfm2SoVJetPZzQTfsrLS4fdblFnnwaOWPRyK9aBxwvHurFeruVZebFOzZ8VYPs6fztsOZX2lkrZ55iiFoaCqu5RDJ3GretYEhc5V9RkrSFOVooVkKs++tLohNJrn1jT0V47e9UI3ZM9Kh2p3R+IlqQgNo2O1CgtDDMd896DoOezFsVEvRs+7nqaKG3d6B8mEICknXCN1Bvs0bqxeN8pLrmCp0H6/s5e4QRx9NGHm8Q3hRbLO7TmLlojRhtodZUuf/Q5Pw==
Отправляем запрос.
Указываем идентификатор ключа, которым формировалась подпись в заголовке Sign-Key-Id
. Его передаст сотрудник банка
при передаче ключа.
Указываем подпись в формате base64 в заголовке Sign-Body
.
В Sign-Body
не должно быть переносов и других лишних символов.
curl -L 'https://enter.tochka.com/uapi/guarantee/v1.0/create' \
--header 'Sign-Body: 'ITL85xBoFIKmOYF8O6BCilexlkaSD3NgDiOqRgFtKutxhRXcsqt9RsnIaVHiioB7vnIea4XNgePe3h+lrLfm2SoVJetPZzQTfsrLS4fdblFnnwaOWPRyK9aBxwvHurFeruVZebFOzZ8VYPs6fztsOZX2lkrZ55iiFoaCqu5RDJ3GretYEhc5V9RkrSFOVooVkKs++tLohNJrn1jT0V47e9UI3ZM9Kh2p3R+IlqQgNo2O1CgtDDMd896DoOezFsVEvRs+7nqaKG3d6B8mEICknXCN1Bvs0bqxeN8pLrmCp0H6/s5e4QRx9NGHm8Q3hRbLO7TmLlojRhtodZUuf/Q5Pw==' \
--header 'Sign-Key-Id: 66019375-5ae8-4618-bf10-919547a269df' \
--header 'Content-Type: application/json' \
--data-binary @'./message'
Пример формирования подписи через код на python
Для выполнения этого кода необходимо по инструкции выше сформировать приватный ключ rsaprivkey.pem и установить
библиотеки pycryptodome
и httpx
:
pip install pycryptodome
pip install httpx
import base64
import json
import httpx
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.PublicKey.RSA import RsaKey
from Crypto.Signature import PKCS1_v1_5
from httpx import BasicAuth
def sign(message: bytes, private_key_: RsaKey) -> bytes:
signer = PKCS1_v1_5.new(private_key_)
data_hash = SHA256.new(message)
return signer.sign(data_hash)
with open('rsaprivkey.pem', 'rb') as key_file:
private_key = RSA.import_key(key_file.read())
request_payload = {
'Data': {
'guaranteeType': 'FULFILLMENT',
'guaranteeStartDate': "string',
'guaranteeEndDate': "string',
'guaranteeSum': 0,
'clientInn': 'string',
'tenderCustomerInn': 'string',
'purchaseType': 0
}
}
sign_payload = json.dumps(request_payload) # body запроса в корректном строковом формате
sign_body = sign(sign_payload.encode('utf-8'), private_key) # Подпись запроса
encoded_sign_body = base64.b64encode(sign_body).decode() # Подпись запроса в base_64
response = httpx.post(
'https://stage-openapi.bank24.int/uapi/guarantee/v1.0/create',
json=request_payload,
headers={
'Sign-Key-Id': 'Указать идентификатор ключа',
'Sign-Body': encoded_sign_body,
},
)