Блог · Для розробників

Кілька підписантів одного документа: як реалізувати мультипідпис

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

Договір підписують дві сторони, наказ погоджують директор і бухгалтер, протокол — усі учасники зборів. Розповідаємо, як влаштований мультипідпис усередині CMS-контейнера і як накласти другий підпис одним викликом `coSign`.

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


Коротка відповідь. Мультипідпис — це кілька підписів різних людей на одному документі, зібраних в одному файлі. У CMS-контейнері (CAdES, .p7s) для цього передбачено кілька записів підписантів, тож «накласти другий підпис» означає додати ще один запис у наявний контейнер, не чіпаючи перший. У DSTUcrypt це один виклик coSign(existingSignature, data) — він доступний із платною опцією «Кілька підписантів» (+700 грн/міс або +6 048 грн/рік за домен), а перевірка verify повертає масив signers із даними кожного, хто підписав.

Коли підписів має бути кілька: типові сценарії

Один підпис закриває далеко не всі документообіги. У реальних застосунках найчастіше трапляються три сценарії:

  • Договір двох сторін. Замовник і виконавець підписують той самий текст договору — кожен своїм ключем. Документ вважається укладеним, коли в контейнері є обидва підписи.
  • Погодження ланцюжком. Наказ чи платіжний документ спершу підписує директор, потім бухгалтер (або навпаки — за вашим регламентом). Кожен наступний учасник додає свій підпис до вже підписаного файлу.
  • Протоколи зборів. Рішення загальних зборів чи засідання комісії підписують усі присутні — підписантів може бути й п'ять, і десять.

В усіх трьох випадках технічна задача та сама: до документа, на якому вже є чинний підпис, треба додати ще один — так, щоб попередні не зламалися, а перевіряльник бачив повний список підписантів.

Як мультипідпис влаштований усередині CMS-контейнера

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

Ключовий наслідок такої будови: записи підписантів не залежать один від одного. Другий підписант не «підписує підпис» першого — він додає до списку власний запис над тими самими даними. Тому додавання нового підписанта не робить недійсними попередні підписи, а перевірка проходить по кожному запису окремо. Саме тому один файл .p7s може нести і два, і десять рівноправних підписів.

coSign: додати другого підписанта одним викликом

Вручну дописувати запис підписанта в ASN.1-структуру — робота для криптобібліотеки, а не для продуктового коду. У DSTUcrypt віджет підпису має для цього окремий метод coSign(existingSignature, data): ви передаєте наявний CMS-контейнер і вихідні дані документа, користувач підписує своїм ключем у нашому iframe — і назад повертається оновлений контейнер, де підписантів уже двоє.

другий підписант — один виклик coSign

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

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

// Мультипідпис: додати підписанта до готового CMS
try {
  const { signature, accredited } = await s.coSign(existingSignature, data);
  signature.download('contract.p7s'); // оновлений контейнер: підписів уже два
} catch (e) {
  if (e.code === 'MULTISIGN_NOT_ENABLED') {
    // опція «Кілька підписантів» не активна для домену
  }
}

Важлива деталь ліцензування: coSign — це платна опція «Кілька підписантів», яка коштує +700 грн/міс або +6 048 грн/рік за домен додатково до базової підписки. Якщо опцію для домену не оплачено, виклик відхиляється з помилкою error.code === 'MULTISIGN_NOT_ENABLED' — обробіть цей код і покажіть користувачу зрозуміле повідомлення.

Чому це зручно саме у DSTUcrypt. Уся криптографія виконується в браузері підписанта (WebAssembly) всередині нашого iframe: ключ і пароль не потрапляють ні на ваш сервер, ні до нас. Вам не треба розбирати ASN.1, зшивати записи підписантів чи хостити криптобібліотеку — coSign ховає все це за одним промісом, а verify одразу віддає готовий список підписантів з ознакою КЕП по кожному.

Повний потік у застосунку: від першого підпису до останнього

Мультипідпис — це завжди процес у часі: підписанти діють по черзі, часто з різних пристроїв і в різні дні. Ваш застосунок виступає «поштарем» контейнера між ними:

  1. Перший підписант підписує документ звичайним sign(data, { format: 'CAdES-T' }) — отримуєте CMS-контейнер.
  2. Збережіть контейнер (signature.bytes або signature.base64) у своїй базі чи файловому сховищі разом зі статусом «очікує другого підписанта».
  3. Запросіть другого підписанта — листом, повідомленням або задачею в кабінеті вашого застосунку.
  4. Другий підписант відкриває документ у вашому інтерфейсі; ви викликаєте coSign(existingSignature, data) з збереженим контейнером і вихідними даними.
  5. Збережіть оновлений контейнер замість попереднього. Якщо підписантів більше двох — повторюйте кроки 3–5 для кожного наступного.

Зверніть увагу: для coSign потрібні і наявний підпис, і самі дані документа — тож зберігайте вихідний файл поруч із контейнером до завершення всього ланцюжка.

Як перевірити документ з кількома підписами

Перевірка мультипідписного файлу нічим не відрізняється від звичайної: віджет verify сам визначає формат за вмістом і повертає результат по кожному підписанту окремо — масивом signers.

verify: масив signers — по одному запису на підписанта

const v = await embed('verify', { mount: 'modal' });
// вкладений (attached) підпис — другим аргументом null
const { valid, signers } = await v.verify(signatureBytes, null);

for (const signer of signers) {
  console.log(signer.valid, signer.accredited,
              signer.signerName, signer.signerCode, signer.signingTime);
}

Найкорисніші поля кожного елемента signers:

Поле Що означає
valid / status чи чинний підпис цього підписанта (статус на кшталт TOTAL-VALID )
accredited true — сертифікат від акредитованого надавача, тобто це КЕП; false — підпис дійсний, але не КЕП; null — дані довіри недоступні
signerName / signerOrg ПІБ підписанта та його організація
signerCode РНОКПП або ЄДРПОУ — щоб звірити підписанта з очікуваним у вашій системі
signingTime / timestampTime час підпису і час мітки TSP — за ними видно порядок підписання
ocspStatus / crlStatus статус сертифіката за даними відкликання

Якщо рішення про допуск документа ухвалює ваш бекенд (а не фронтенд), продублюйте перевірку авторитетним серверним POST /api/verify — він так само повертає масив signers з accredited і qualified по кожному, але нативним ядром на сервері, куди фронтенд не має доступу.

Обмеження й поради

  • Формат — родина CAdES. coSign додає підписанта саме до готового CMS-контейнера, тож для сценаріїв мультипідпису плануйте документообіг на форматах CAdES (.p7s).
  • Фіксуйте час. Підписуйте на рівні з міткою часу (наприклад, CAdES-T): тоді на кожного підписанта буде незалежний доказ моменту підписання, а порядок ланцюжка легко відновити з signingTime/timestampTime.
  • Порядок контролює застосунок. Криптографічно записи підписантів рівноправні — якщо регламент вимагає «спершу директор, потім бухгалтер», цю черговість забезпечує ваша бізнес-логіка, а перевіряється вона за часовими мітками.
  • Звіряйте підписантів за кодом. Після кожного coSign корисно прогнати verify і зіставити signerCode з очікуваним РНОКПП/ЄДРПОУ — так ви впіймаєте випадок, коли документ підписала не та людина.
  • Зберігайте вихідні дані до кінця ланцюжка. Вони потрібні для кожного наступного виклику coSign.

Поширені запитання

Скільки коштує опція «Кілька підписантів»?

Опція «Кілька підписантів» коштує +700 грн/міс або +6 048 грн/рік за домен — додатково до базової підписки. Без активної опції виклик coSign відхиляється з помилкою error.code === 'MULTISIGN_NOT_ENABLED'.

Чи «ламає» другий підпис перший?

Ні. coSign додає в наявний CMS-контейнер новий запис підписанта, не змінюючи попередні. Перший підпис лишається чинним, а verify перевіряє кожного підписанта окремо й показує valid, accredited, ПІБ і код по кожному.

Як передати документ другому підписанту?

Після першого підпису збережіть CMS-контейнер (наприклад, файл .p7s) у своєму застосунку — у базі чи сховищі. Коли другий підписант відкриє документ у вашому інтерфейсі, викличте coSign(existingSignature, data): віджет DSTUcrypt відкриється в його браузері й поверне оновлений контейнер уже з двома підписами.

Як дізнатися, хто вже підписав документ?

Викличте verify: результат містить масив signers, де на кожного підписанта є valid, accredited (чи це КЕП), signerName (ПІБ), signerOrg, signerCode (РНОКПП/ЄДРПОУ) і signingTime. За цим масивом легко побудувати чек-лист «хто підписав, кого ще чекаємо».

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

Мультипідпис на вашому сайті — за 10 хвилин

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

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

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

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