CAdES-BES представляет собой базовый профиль усовершенствованной электронной подписи CMS (Cryptographic Message Syntax), в котором подпись дополняется минимально необходимым набором атрибутов, обеспечивающих юридическую и криптографическую значимость. В контексте JavaScript реализация чаще всего опирается на библиотеку jsrsasign, предоставляющую инструменты для работы с X.509, CMS/PKCS
CAdES-BES (Basic Electronic Signature) строится на CMS SignedData и включает:
Ключевая особенность — целостность и идентификация подписанта без необходимости внешних сервисов времени.
В jsrsasign работа с CAdES-BES реализуется через пространство имён
KJUR.crypto.CMS.
Библиотека может быть подключена через CDN или npm:
import * as jsrsasign from "jsrsasign";
или в браузере:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/10.8.6/jsrsasign-all-min.js"></script>
После подключения становятся доступны:
KEYUTIL — работа с ключамиX509 — обработка сертификатовKJUR.crypto.CMS — создание CMS SignedDataДля формирования CAdES-BES требуется закрытый ключ и X.509 сертификат.
Пример генерации ключа RSA:
const kp = KEYUTIL.generateKeypair("RSA", 2048);
const prvKey = kp.prvKeyObj;
const pubKey = kp.pubKeyObj;
Создание самоподписанного сертификата (для демонстрации):
const cert = KJUR.asn1.x509.X509Util.newCertPEM({
serial: { int: 1 },
sigalg: "SHA256withRSA",
notbefore: "20250101000000Z",
notafter: "20300101000000Z",
issuer: { str: "/CN=Test CA" },
subject: { str: "/CN=Signer" },
sbjpubkey: pubKey,
ext: [
{ basicConstraints: { cA: false } }
],
cakey: prvKey
});
В реальных системах сертификат поступает из PKI и не генерируется в приложении.
CAdES-BES подписывает произвольные бинарные данные, чаще всего:
Пример текстового сообщения:
const data = "Confidential message";
Для CMS структура требует кодирования данных:
const contentInfo = {
contentType: "data",
content: data
};
CAdES-BES требует минимум набора signed attributes:
jsrsasign формирует их автоматически при использовании CMS API, но возможно ручное управление.
Основной механизм формирования подписи реализуется через:
KJUR.crypto.CMS.sign
Пример формирования CAdES-BES:
const cms = new KJUR.crypto.CMS();
const signedData = cms.sign({
content: {
str: data
},
certs: [cert],
signerPrvKey: prvKey,
signerCert: cert,
hashAlg: "sha256",
econtentType: "data"
});
Результат — CMS SignedData в формате DER/PEM.
По умолчанию jsrsasign может возвращать PEM:
console.log(signedData);
Для DER:
const signedDer = cms.sign({
content: { str: data },
certs: [cert],
signerPrvKey: prvKey,
signerCert: cert,
hashAlg: "sha256",
econtentType: "data",
detached: false,
asn1obj: true
}).getContentInfo().getContent().getContentInfo().toHex();
CAdES-BES поддерживает два режима:
Подписанные данные включены в CMS:
detached: false
Подпись хранится отдельно:
detached: true
Пример:
const cmsDetached = cms.sign({
content: { str: data },
certs: [cert],
signerPrvKey: prvKey,
signerCert: cert,
hashAlg: "sha256",
detached: true
});
Detached используется в системах документооборота, где оригинал и подпись хранятся отдельно.
Сгенерированная CMS структура включает:
Разбор SignerInfo:
const si = cms.signerInfoList[0];
console.log(si.signerCert.issuer.str);
console.log(si.signerCert.subject.str);
Проверка осуществляется через verify:
const isValid = cms.verify({
cms: signedData,
certs: [cert]
});
При успешной проверке подтверждается:
Загрузка PEM сертификата:
const x509 = new X509();
x509.readCertPEM(certPem);
const parsedCert = x509;
Извлечение ключа:
const pubKey = KEYUTIL.getKey(certPem);
Алгоритм хеширования критичен для подписи:
В jsrsasign:
hashAlg: "sha256"
В CAdES-BES автоматически включаются:
signingTime)contentType)messageDigest)Расширенные атрибуты (не обязательные для BES):
Механизм проверки включает:
Типичная структура:
SignedData
├── version
├── digestAlgorithms
├── encapContentInfo
├── certificates
├── signerInfos
├── version
├── signerIdentifier
├── digestAlgorithm
├── signedAttributes
├── signatureAlgorithm
├── signatureValue
jsrsasign абстрагирует ASN.1, но позволяет извлекать любые узлы.
Типовые ошибки:
Диагностика:
try {
cms.sign({...});
} catch(e) {
console.log(e.message);
}
При работе с CAdES-BES в браузере ключи часто оказываются в памяти приложения. Это создаёт риски:
В серверной реализации предпочтительно:
Подписи, созданные jsrsasign, совместимы с:
При условии корректного выбора алгоритмов и кодировки (DER/PEM).
CAdES-BES базируется на PKCS#7 SignedData, где jsrsasign предоставляет низкоуровневый доступ:
const pkcs7 = new KJUR.crypto.PKCS7();
Однако для CAdES предпочтительнее CMS API, так как он корректнее обрабатывает атрибуты.
Сценарии:
Особенность — выполнение криптографии на клиенте без передачи приватного ключа на сервер.
CAdES-BES часто используется как базовый уровень перед добавлением:
jsrsasign сам по себе не реализует полноценный ETSI lifecycle, но служит фундаментом для BES-уровня.