Блог · Стандарти ДСТУ

Як підписати документ КЕП з гешем «Купина» у браузері: практичний гайд

Опубліковано

Підпис із сучасним гешем ДСТУ 7564 — без десктопних програм, драйверів і бекенд-криптографії. Показуємо повний шлях: від імпорту SDK до готового файлу підпису, з прикладами для CAdES і XAdES.

Опубліковано 7 серпня 2026


Коротка відповідь. Щоб зробити підпис КЕП з гешем «Купина» (kupyna-256, ДСТУ 7564:2014) просто в браузері, достатньо одного імпорту SDK DSTUcrypt і однієї опції у виклику підпису: signer.sign(fileBytes, { format: 'CAdES-T', digest: 'kupyna-256' }). Уся криптографія виконується у браузері користувача (WebAssembly), ключ і пароль не покидають його. Один нюанс: держвалідатори (Дія, ЦЗО) сьогодні приймають пару «ДСТУ 4145 + ГОСТ 34.311» — тому для документів у держсистеми лишайте геш за замовчуванням, а «Купину» вмикайте там, де приймальна сторона її підтримує.

Що таке «Купина» — за хвилину

«Купина» — українська криптографічна геш-функція, стандартизована як ДСТУ 7564:2014. У підписі вона виконує підготовчу роль: стискає документ будь-якого розміру в короткий відбиток (для «Купини-256» — 256 біт), і саме цей відбиток підписується вашим ключем за ДСТУ 4145. Тобто «дсту 7564 підпис» — це насправді звичайний підпис ДСТУ 4145, у якому геш-функцію ГОСТ 34.311-95 замінили на сучасну «Купину».

Важливий наслідок: новий ключ не потрібен — геш-функція «пристібається» до наявного ключа при кожному підписі. Детальний розбір самого стандарту, його конструкції та порівняння з ГОСТ — у статті ««Купина» (ДСТУ 7564:2014): що це за геш-функція і чому вона замінює ГОСТ 34.311-95».

Коли обирати «Купину», а коли ГОСТ 34.311

Головне практичне правило: дивіться на те, хто перевірятиме підпис. Держвалідатори — застосунок Дія та центральний засвідчувальний орган — сьогодні приймають пару «підпис ДСТУ 4145 + геш ДСТУ ГОСТ 34.311-95»; Дія відхиляє «Купину»-у-CMS. Саме тому в DSTUcrypt геш за замовчуванням — 'gost-34311': підпис без опції digest гарантовано «зайде» у державні системи.

  • Документ піде у Дію, ЦЗО чи держреєстри — підписуйте з ГОСТ 34.311 (замовчування або явно digest: 'gost-34311').
  • Внутрішній документообіг, B2B-обмін, власна система перевірки — вмикайте «Купину» явно: digest: 'kupyna-256'. Це сучасний нацстандарт із запасом криптографічної міцності.
  • Не впевнені — задавайте digest явно в обох випадках: явно заданий геш завжди має пріоритет, і поведінка вашої інтеграції стає передбачуваною.

Коли держсистеми перейдуть на «Купину», зміна дефолту у вашому коді — один рядок, без перезбирання і оновлень.

Покроковий гайд: кеп «Купина» за чотири кроки

Знадобиться лише сторінка вашого сайту і файловий ключ користувача (PKCS#12/PFX, JKS, PKCS#8 або Key-6.dat). Нічого хостити в себе не треба — SDK сам вантажить віджет і WASM-ядро зі свого origin.

Крок 1. Імпортуйте SDK одним рядком. Крок 2. Створіть віджет підпису — embed('sign'). Крок 3. Викличте sign() з опцією digest: 'kupyna-256' — користувач обере ключ і введе пароль усередині iframe віджета. Крок 4. Заберіть результат: signature.download() для користувача або signature.base64 / signature.bytes для бекенда.

підпис CAdES-T із гешем «Купина» — повний приклад

import { embed } from 'https://dstucrypt.io/embed/dstucrypt-embed.mjs';

const signer = await embed('sign', { mount: 'modal' });

const { signature, accredited } = await signer.sign(fileBytes, {
  format: 'CAdES-T',     // з міткою часу TSP
  digest: 'kupyna-256',  // «Купина» ДСТУ 7564; без опції — ГОСТ 34.311
});

signature.download('document.p7s');  // або signature.base64 / .bytes / .blob()

fileBytes може бути File, Blob, ArrayBuffer, Uint8Array або рядком — Base64 у вашому коді не потрібен. Поле accredited підкаже, чи виданий сертифікат підписанта акредитованим надавачем (тобто чи це саме КЕП). Мітку часу для CAdES-T ставлять вбудовані TSP-сервери з автоматичними фолбеками — налаштовувати нічого не треба.

Той самий геш працює і в інших родинах форматів — наприклад, XML-підпис із «Купиною»:

XAdES із «Купиною-256» — рідкісна для вебу можливість

const { signature } = await signer.sign(xmlBytes, {
  format: 'XAdES-B-T',   // XML-DSig: dstu4145-dstu7564-256
  digest: 'kupyna-256',
  fileName: 'contract.xml',
});
signature.download('contract.xml');

«Купина» в різних форматах підпису

Опція digest діє для всіх 16 підтримуваних форматів — від голого CMS до архівних рівнів із мітками часу. Різниця лише в назвах рівнів: CAdES вживає стару номенклатуру (CAdES-T), а XAdES і PAdES — baseline-форму (XAdES-B-T, PAdES-B-T).

Родина Значення format Файл «Купина» через digest:'kupyna-256'
CAdES (CMS) CAdES-BES · CAdES-T · CAdES-C · CAdES-XL .p7s так; є й detached -режим
PAdES (PDF) PAdES-B-B · PAdES-B-T · PAdES-B-LT · PAdES-B-LTA .pdf так — підпис вбудовано просто в PDF
XAdES (XML) XAdES-BES · XAdES-B-T · XAdES-B-LT · XAdES-B-LTA .xml так — ДСТУ 4145 + «Купина-256» у XML-DSig, рідкість для вебу
ASiC-S / ASiC-E ASiC-S-BES · ASiC-S-T · ASiC-E-BES · ASiC-E-T .asics / .asice так — ZIP-контейнер «оригінал + підпис»

Рівні з міткою часу (-T і вище) потребують онлайн-доступу до TSP — SDK ходить туди через вбудований проксі автоматично. Який формат обрати під вашу задачу — розбираємо окремо у статті про формати CAdES, PAdES, XAdES та ASiC.

Чому це безпечно і чому це рідкість. Ключ і пароль вводяться всередині iframe на origin dstucrypt.io і не покидають браузер користувача — вони недоступні ні коду вашої сторінки (навіть за XSS), ні серверам. Криптоядро — перевірена нативна C/C++-бібліотека, скомпільована у WebAssembly. Це повний стек оновлених нацстандартів — «Купина», «Калина», ДСТУ 4145 — у 16 форматах підпису, просто у вебі.

Як перевірити підписане

Перевірка — таким самим віджетом: const v = await embed('verify'), далі v.verify(signatureBytes, null) для вкладеного підпису (дані передавайте лише для detached). Результат містить valid і масив signers — з ПІБ, РНОКПП/ЄДРПОУ, часом підпису, форматом і полем accredited, яке відрізняє КЕП від просто дійсного підпису. Формат визначається автоматично за вмістом — CAdES, PAdES, XAdES чи ASiC.

Швидко глянути підпис руками без коду можна безкоштовним інструментом /verify. А коли рішення про допуск документа ухвалює ваш бекенд — використовуйте авторитетний серверний POST /api/verify: та сама перевірка, але нативним ядром на сервері, куди фронтенд не має доступу.

Типові питання та помилки

Найчастіша «помилка» з «Купиною» — насправді не помилка: підпис валідний, але приймальна сторона (наприклад, Дія) очікує ГОСТ 34.311. Перевірте вимоги отримувача перед вибором геша. З технічних кодів: CANCELLED — користувач закрив модалку, TSP_QUOTA — вичерпано денний ліміт міток часу, not_licensed — на домені немає активної підписки чи тріалу (лоадер сам покаже акуратну модалку).

Чи потрібен окремий ключ, щоб підписувати з «Купиною»?

Ні. Ключ КЕП — це ключ підпису ДСТУ 4145, а «Купина» лише замінює геш-функцію в парі з ним. Достатньо додати опцію digest:'kupyna-256' у виклик sign() — жодного перевипуску ключів.

Чому Дія не приймає мій підпис із «Купиною»?

Держвалідатори (Дія, ЦЗО) сьогодні приймають пару «підпис ДСТУ 4145 + геш ДСТУ ГОСТ 34.311-95» — Дія відхиляє «Купину»-у-CMS. Для документів у державні системи підписуйте з digest:'gost-34311' (це і є замовчування), а «Купину» вмикайте там, де приймальна сторона її підтримує.

Який геш буде, якщо не вказати опцію digest?

Без опції digest підпис гешується ДСТУ ГОСТ 34.311-95 — саме цю пару сьогодні приймають держвалідатори. Для передбачуваності радимо задавати digest явно: 'gost-34311' або 'kupyna-256'. Явно заданий digest завжди має пріоритет і діє для всіх форматів.

Чи працює «Купина» у PDF та XML-підписах?

Так. Опція digest:'kupyna-256' діє для всіх форматів: CAdES, PAdES, XAdES та ASiC. Зокрема XAdES з українськими ключами ДСТУ 4145 підтримує і ГОСТ 34.311, і «Купину-256» — на вебі це рідкісна можливість.

Читайте також

Підпис із «Купиною» на вашому сайті — за 10 хвилин

Готові віджети підпису, перевірки та шифрування за ДСТУ. Ключ і пароль не покидають браузер користувача. На кожному новому домені — 7 днів безкоштовно.

Живе демоЯк підключити

Спробуйте КЕП на своєму сайті

Готові віджети підпису, перевірки та входу за ДСТУ. На кожному новому домені — 7 днів безкоштовно.