Робота з підписанням

Структура JWS

Типовий JWS складається з трьох частин, розділених крапками (.):

{Base64Url(header)}.{Base64Url(payload)}.{Base64Url(signature)}

Де:

  • header — описує загальні мета данні

{
    "alg": "ES256",  // Алгоритм підписання 
    "kid": "uuid",  // Ідентифікатор публічного ключа (надається від співробітника банку)
    "ts" : "1763034308", // Дата та час у форматі timestamp
    "targetUrl" : "/ecom/jws/payments/create/purchase_v3" // URL на який надсилається запит
}
  • payload — дані, які потрібно передати (наприклад, інформація про користувача або дані запит).

  • signature — цифровий підпис, створений за допомогою приватного ключа відправника.

Приклад JWS:

eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.
MEYCIQDmG...

Як виконується підписання

  1. Формується header (мета дані) payload (дані запиту).

  2. Обидві частини кодуються у формат Base64Url.

  3. Об’єднуються в одне повідомлення:

    signingInput = base64Url(header) + "." + base64Url(payload)
  4. Це повідомлення підписується приватним ключем (детальніше як отирмати ключ - Генерація ключів) за вказаним алгоритмом .

  5. Результат (signature) додається як третя частина JWS.

Приклад генерації JWS можна переглянути на сайті https://www.jwt.io/

Приклад коду для генерації підпису:

import { CompactSign, importPKCS8 } from 'jose';

// === Дані ===
const privateKeyPem = `
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBOS+Xg3qgYSe5T4H2AoB0zWrhb0jNmcdW6o2bTXXWlQoAoGCCqGSM49
AwEHoUQDQgAEMO4qQsgPskZ4E1X6nHZU9yHnJrZ97K3QAjQ1oG1zgrht3mA4+lf5
aMqTIk1glXZpMT4pAzTURmmP2+prvQul3g==
-----END EC PRIVATE KEY-----
`;

const header = {
  alg: "ES256",
  kid: "9a3f6e6d-4f56-4b8b-99d3-24db19f54d8a",
  ts: Math.floor(Date.now() / 1000),
  targetUrl: "/ecom/jws/payments/create/purchase_v3"
};

// payload — це тіло запиту
const payload = {
  merchantId: "12345",
  amount: "1000.00",
  currency: "UAH",
  orderId: "ORD-2025-001"
};

// === Генерація JWS ===
const privateKey = await importPKCS8(privateKeyPem, 'ES256');
const encoder = new TextEncoder();

const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64url');
const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64url');
const signingInput = `${encodedHeader}.${encodedPayload}`;

const sign = new CompactSign(encoder.encode(JSON.stringify(payload)))
  .setProtectedHeader(header);

const jws = await sign.sign(privateKey);

console.log("JWS:", jws);

Вимоги до JWS

Частина header JWS :

  • Токен має термін дії в 1 хвилину, якщо буде передано параметр ts з значенням більше 1 хвилини від поточного часу, винекне помилка

  • Якщо в параметрі targetUrl буде передане неіснуюче або невалідне значення - виникне помилка

  • Якщо в параметрі alg буде значення, що не відповідає алгоритмку згенерованого ключа - виникне помилка

  • Якщо в параметі kid буде передане неіснуюче або невалідне значення - виникне помилка

Частина payload JWS:

  • Передається тіло запиту, що повинно відповідати вимогам самого запиту та його обов'язкових параметрів

  • Якщо в тілі запиту буде вказане значення merchantId , що неіснує - виникне помилка

Last updated