GH GambleHub

Підпис і верифікація запитів

Підпис запиту доводить справжність відправника і цілісність вмісту. На відміну від TLS (який захищає канал), прикладний підпис робить кожне повідомлення перевіряється і стійким до проксі, кешу і відкладеної доставки.

Цілі:

1. Автентичність (хто відправив) і цілісність (не змінювалося).

2. Неповторюваність (захист від реплеїв).

3. Відв'язка від транспорту (працює поверх HTTP, черг, вебхуків).

4. Аудиторійність (відтворювана перевірка через місяці).

1) Модель загроз (мінімум)

Підміна тіла/заголовків на шляху прямування.
Реплей (повтор легітимного запиту).
Downgrade/strip заголовків підпису.
Крадіжка секретів інтеграції.
Несинхронний годинник (clock skew) і довгі черги.

2) Вибір примітиву

HMAC (симетрія): простий і швидкий, ключ зберігається в обох сторін. Підходить для B2B-вебхуків і внутрішніх API.
RSA/ECDSA (асиметрія): ключ приватний у відправника, публічний у одержувача. Підходить для відкритих інтеграцій і коли важливо не ділитися секретом.
mTLS: взаємна автентифікація на транспортному рівні; часто комбінується з НМАС/підписом тіла.
JWT/JWS: зручно для bearer-токенів і самодостатніх клеймів; для підпису тіла краще використовувати канонікалізацію + JWS Detached/HTTP Message Signatures.
HTTP Message Signatures (підпис вибраних частин запиту): сучасний підхід для REST.

Рекомендація: для вебхуків - HMAC + timestamp + nonce + канонікалізація тіла; для публічного API - HTTP Message Signatures або JWS; при високих ризиках - додайте mTLS.

3) Канонікалізація (що саме підписуємо)

Підписувати потрібно детермінований рядок, однаково відновлюваний обома сторонами.

Референсний склад:

method \n path_with_query_normalized \n content-type \n digest: SHA-256=BASE64(SHA256(body)) \n x-ts: <unix    iso> \n x-nonce: <uuid> \n host \n x-tenant: <tenant_id> \n
Підсумковий рядок:

canonical = join("\n", fields)
signature = HMAC(secret, canonical)  # или ECDSA_sign(private_key, canonical)
Правила:
  • Нормалізуйте шлях і порядок query-параметрів.
  • Пробіли/юнікод/регістр - фіксуйте (наприклад, lower-case заголовків, trim).
  • Великі тіла - хешуйте (Digest), а не вмикайте «як є».

4) Формат заголовків

Приклад для HMAC:

X-Signature-Alg: hmac-sha256
X-Signature: v1=hex(hmac),ts=1730379005,nonce=550e8400-e29b-41d4-a716-446655440000,kid=prov_42
Digest: SHA-256=BASE64(SHA256(body))
X-Tenant: brand_eu
Приклад для асиметрії (ECDSA P-256):

Signature: keyId="prov_42", alg="ecdsa-p256-sha256",
ts="2025-10-31T12:30:05Z", nonce="550e...", headers="(request-target) host digest x-tenant",
sig="BASE64(raw_signature)"

Де'kid '/' keyId'дозволяє вибрати ключ з реєстру (див. ротацію).

5) Верифікація на приймальній стороні

Псевдокод:
python def verify(request):
1) Basic assert abs (now () - request. ts) <= ALLOWED_SKEW  # напр., 300 с assert not replayed(request. nonce, window = TTL) # store nonce/ts in KV

2) Restore canonical canonical = build_canonical (
method=request. method,
path=normalize_path(request. path, request. query),
content_type=request. headers["content-type"],
digest=hash_body(request. body),
ts=request. ts,
nonce=request. nonce,
host=request. headers["host"],
tenant=request. headers. get("x-tenant")
)

3) Get the key key = key_registry. get(request. kid) # secret (HMAC) или public key (ECDSA)

4) Verify if request signature. alg. startswith("hmac"):
ok = hmac_compare(key. secret, canonical, request. signature)
else:
ok = asym_verify(key. public, canonical, request. signature)

5) Solution if not ok: return 401, "SIGNATURE_INVALID"
return 200, "OK"

Constant-time порівняння HMAC, зберігання'nonce '/' (ts, event_id)'в швидких KV (TTL ≥ вікно доставки).

6) Анти-реплей і вікна

Timestamp + Nonce: відхиляйте запити старше «± Δ» (напр., 5 хв) і повтори nonce в цьому вікні.
Для вебхуків: використовуйте стабільний'event _ id'і inbox-таблицю - це надійніше, ніж тільки nonce.
Повторна доставка (ретраї) повинна використовувати ті ж ts/nonce/event_id, а не генерувати нові.

7) Мульти-тенант і регіони

Зберігайте ключі per tenant/region: `kid = <tenant>:<region>:<key_id>`.
Розділяйте пули секретів і ліміти; дотримуйтесь data residency.
У заголовках/канонікалізації вказуйте'X-Tenant'і регіон - це частина перевіряється контексту.

8) Управління ключами та ротація

Реєстр ключів (KMS/Vault): 'kid', тип, алгоритм, статус ('active','deprecating','retired'),'valid _ from/valid _ to'.
Dual-secret: тримайте одночасно поточний і наступний ключ (приймач приймає обидва).
Ротація за розкладом і за подією (компрометація).
Key pinning (по можливості) і обмеження доступу до матеріалів ключів.
Логи доступу до ключів і дій з ними.

9) Поєднання з mTLS і OAuth

mTLS перевіряє канал і «хто ви» на рівні сертифіката.
Підпис захищає повідомлення (корисна через проксі/кеші/черги).
OAuth/JWT доповнює автентифікацію/авторизацію, але сам по собі не гарантує цілісність тіла (якщо його не підписувати в канонікалізації).
Кращі практики: mTLS + підпис тіла (Digest) + HMAC/ECDSA + короткий'ts'-інтервал.

10) Помилки та коди відповідей

'401 SIGNATURE_INVALID' - невірний підпис/алгоритм.
'401 KEY_REVOKED' -'kid'недійсний/прострочений.
'400 TIMESTAMP_OUT_OF_RANGE' - годинник/вікно.
'409 NONCE_REPLAYED' - виявлено повтор.
400 DIGEST_MISMATCH' - тіло змінено.
'415 UNSUPPORTED_ALGORITHM' - недозволений'alg'.
'429 TOO_MANY_ATTEMPTS' - тротлінг за ключем/тенантом.

Штовхайте точну причину в машинно-читаному'error _ code'; не повертайте секрети/канонікалізацію «як є».

11) Спостережуваність і аудит

Метрики:
  • `verify_p95_ms`, `verify_error_rate`, `digest_mismatch_rate`, `replay_blocked_rate`, `alg_usage{hmac,ecdsa}`, `clock_skew_ms`.
  • Логи (структурні): `kid`, `alg`, `tenant`, `region`, `ts`, `nonce`, `digest_hash`, `decision`, `reason`.
  • Трейсинг: атрибути'signature. kid`, `signature. alg`, `signature. ts_skew`.
  • Аудит: незмінний журнал ротацій, використання ключів і прапорів допуску.

12) Продуктивність

Хешируйте тіло стримінгом (не тримайте в пам'яті).
Кешуйте публічні ключі по'kid'з коротким TTL і інвалідацією по події.
На edge/gateway виносьте попередні перевірки (ts/nonce/формат).
HMAC швидше ECDSA; ECDSA зручніше для зовнішніх інтеграцій і «нероздільних» ключів.

13) Тестування

Набори фікстур: однакові запити → однакова канонікалізація/підпис; «брудні» прогалини/порядок query/заголовків → стійкі.
Negative: невірний'kid/alg', модифіковане тіло/host, повтор nonce, застарілий ts, clock skew.
Property-based: будь-які еквівалентні запити дають один canonical-рядок.
Interop: крос-мовні перевірки (Go/Java/Node/Python).
Chaos: затримки, ретраї, зміна ключа «на льоту».

14) Плейбуки (runbooks)

1. Сплеск'SIGNATURE _ INVALID '

Перевірити ротацію ключів, розсинхрон clock, зміни канонікалізації у відправника.
Тимчасово включити'dual-accept'для старого'kid', повідомити партнера.

2. Зростання'REPLAYED '

Збільшити TTL зберігання nonce, звірити ретрайнери у відправника, перевірити clock skew.
Перекрити зловживає IP/ASN на edge.

3.'DIGEST _ MISMATCH'масово

Перевірити проксі/компресію/перезапис заголовків; зафіксувати версію канонікалізації.
Відключити посередників, що порушують тіло/заголовки.

4. Компрометація ключа

Негайно revoke'kid', перекласти на'next _ kid', регенерувати всі секрети/токени, аудит доступу.

15) Типові помилки

Підписувати «частину тіла» або JSON без фіксації порядку → вразливість до перестановки полів.
Відсутність «Digest» → проксі може змінити тіло непомітно.
Довге вікно'ts'без nonce → відкритий реплей.
Зберігати секрети в змінних оточення без KMS/Vault.
Порівнювати підпис не constant-time.
Ігнорувати'host '/' path'в канонікалізації → атаки на переадресацію.
Змішувати'kid'різних тенантів і регіонів.

16) Чек-лист перед продом

Визначено формат канонікалізації (method, path + query, content-type, Digest, ts, nonce, host, tenant).

  • Реалізовані HMAC/ECDSA з'kid', реєстр ключів і dual-secret.
  • Включені анти-реплей (nonce + ts) і зберігання inbox/event_id для вебхуків.
  • Налаштовані коди помилок/політика ретраїв і троттлінг per tenant/key.
  • Спостережуваність: метрики verify, логи, трасування, алерти на сплески.
  • Ротація ключів автоматизована; аудит і права доступу обмежені.
  • Тест-набори на канонікалізацію і міжмовну сумісність.
  • Документація для інтеграторів з прикладом на 3-4 мовах і фікстурами.
  • mTLS включений для чутливих інтеграцій; JWT використовується тільки як доповнення, не заміна підпису тіла.

Висновок

Підпис і верифікація запитів - це не «один заголовок», а дисципліна: чітка канонікалізація, короткі вікна часу, анти-реплей, ротація ключів і спостережуваність. Побудуйте єдиний стандарт для всіх інтеграцій (API і вебхуки), використовуйте'kid '/KMS, приймайте два ключі при ротації, і ваші контури стануть стійкими до підмінам, передбачуваними і зручними для аудиту.

Contact

Зв’яжіться з нами

Звертайтеся з будь-яких питань або за підтримкою.Ми завжди готові допомогти!

Telegram
@Gamble_GC
Розпочати інтеграцію

Email — обов’язковий. Telegram або WhatsApp — за бажанням.

Ваше ім’я необов’язково
Email необов’язково
Тема необов’язково
Повідомлення необов’язково
Telegram необов’язково
@
Якщо ви вкажете Telegram — ми відповімо й там, додатково до Email.
WhatsApp необов’язково
Формат: +код країни та номер (наприклад, +380XXXXXXXXX).

Натискаючи кнопку, ви погоджуєтесь на обробку даних.