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.