Signing#
HMAC#
hmac_sha256(*, key, base, output)
Данные подписи#
join(*parts, separator=b"", prefix=b"", suffix=b"")
method()
path()
target()
query(...)
body_digest(...)
canonical_json(...)
Результат#
header_output(name, encoding="hex")
query_output(name, encoding="hex")
cookie_output(name, encoding="hex")
body_output(name, encoding="hex")
Ключ задаётся через SigningKeyRequirement(name).
join(...) объединяет компоненты с явным separator. Доступные projections включают header(...),
query(...), canonical_json(...), wire_body() и previous_signature(...).
Output может записать подпись в header, query, cookie или body. encoding принимает hex,
base64 или raw; position фиксирует место для exact wire API.
Подпись объявляется по месту объявления: параметром signing= операции или атрибутом
signing роутера/миксина сервиса, наследуемым по MRO. Адресных (host/path) правил подписи нет:
глядя на операцию, всегда видно, подписана она или нет, а опечатка в правиле не может оставить
запрос молча неподписанным.
Если весь сервис подписывается одинаково, правило пишется один раз:
from dataclasses import dataclass
from eazy_sdk import AsyncApi, Http, HttpOperation, JsonField, op
from eazy_sdk.request import body_digest, header_output, hmac_sha256
class PaymentsService:
base_url = "https://payments.example"
signing = (hmac_sha256(key=KEY, base=body_digest(), output=header_output("X-Signature")),)
signed = True # операция без подписи отвергается при компиляции
@dataclass(frozen=True, slots=True, kw_only=True)
class Charge(HttpOperation[Receipt]):
__http__ = Http.post("/charge") # наследует подпись сервиса
account: JsonField[str]
@dataclass(frozen=True, slots=True, kw_only=True)
class Refund(HttpOperation[Receipt]):
__http__ = Http.post("/refund", signing=(REFUND_SIGNATURE,))
account: JsonField[str]
class PaymentsApi(PaymentsService, AsyncApi):
charge = op(Charge)
refund = op(Refund)
signing= на операции заменяет сервисное правило целиком, а не дополняет его; signing=()
снимает подпись и вместе с signed = True даёт ошибку при компиляции. Полная таблица слияния приведена
в мультисервисном SDK.
База подписи считается от тех же байтов, которые уйдут, в том числе когда тело зашифровано
целиком, и кодируется той же JsonPolicy, что и тело
(см. Представление запроса).
Identity.key_provider является callable
(SigningKeyRequirement) -> SigningKey. Secrets отсутствуют в arguments операции и redacted в
repr.