В структуре CMS/PKCS
Подписанные атрибуты всегда хэшируются вместе с содержимым косвенным образом: фактически подпись вычисляется не над исходными данными напрямую, а над DER-кодировкой набора атрибутов. Это делает их критически важной частью структуры SignedData.
SignedAttributes представляют собой ASN.1 структуру:
тип: SET OF Attribute
каждый Attribute содержит:
В Jsrsasign они формируются как объект, который затем кодируется в DER перед вычислением подписи.
OID: 1.2.840.113549.1.9.3
Атрибут contentType указывает тип подписываемого содержимого. Он обязателен в SignedAttributes согласно RFC 5652.
В контексте CMS он определяет, что именно было подписано: данные, вложенный CMS-объект или другой тип структуры.
Типичные значения:
1.2.840.113549.1.7.1 — data1.2.840.113549.1.7.2 — signedDataВ Jsrsasign значение задаётся как часть структуры атрибутов:
var signedAttrs = [
{
type: "1.2.840.113549.1.9.3",
value: "1.2.840.113549.1.7.1"
}
];
При формировании CMS библиотека преобразует это в DER SET и включает в хэш подписи.
OID: 1.2.840.113549.1.9.4
messageDigest содержит хэш исходного содержимого, вычисленный до подписания. Это ключевой элемент, обеспечивающий целостность данных.
Алгоритм:
В Jsrsasign это обычно выполняется автоматически, но логика эквивалентна следующей:
var md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("data to sign");
var digestHex = md.digest();
Далее digestHex включается в signedAttributes:
var signedAttrs = [
{
type: "1.2.840.113549.1.9.4",
valueHex: digestHex
}
];
Внутри CMS происходит важная операция: подпись вычисляется не над messageDigest напрямую, а над DER-кодировкой всего SignedAttributes SET, где messageDigest является одним из элементов.
Это защищает от подмены данных между этапом хэширования и подписания.
OID: 1.2.840.113549.1.9.5
signingTime фиксирует момент создания подписи. Это атрибут, который не влияет на криптографическую стойкость, но имеет значение для юридической и временной валидации.
Формат значения — UTCTime или GeneralizedTime в ASN.1.
В Jsrsasign время обычно задаётся автоматически:
var signedAttrs = [
{
type: "1.2.840.113549.1.9.5",
value: new Date()
}
];
Библиотека сама преобразует JavaScript Date в ASN.1 формат:
Пример DER-структуры:
SigningTime ::= Time
Time ::= CHOICE {
utcTime UTCTime,
generalizedTime GeneralizedTime
}
В Jsrsasign работа с CMS реализуется через пространство имён
KJUR.crypto.CMS.
При создании SignedData библиотека автоматически включает стандартные атрибуты, если используется режим signed attributes.
Пример базового формирования подписи:
var cmsSigned = new KJUR.crypto.CMS.CMSSignedData();
cmsSigned.addSigner({
cert: certPEM,
key: privateKeyPEM,
pass: password,
digestAlg: "sha256"
});
cmsSigned.updateData("Hello world");
var cms = cmsSigned.sign();
Внутри этого процесса формируется:
Перед вычислением подписи Jsrsasign выполняет:
Важно, что изменение порядка атрибутов приводит к изменению подписи.
Это соответствует требованиям CMS:
Подпись вычисляется по следующей модели:
signature = Sign( hash( DER(SignedAttributes) ) )
Таким образом:
При верификации Jsrsasign выполняет обратную процедуру:
Псевдологика:
var md2 = new KJUR.crypto.MessageDigest({alg: "sha256"});
md2.updateString(originalData);
var calcDigest = md2.digest();
if (calcDigest !== messageDigestFromAttr) {
throw "Digest mismatch";
}
Некорректная работа часто связана с:
В CMS это приводит к:
Jsrsasign скрывает ASN.1 сложность за JavaScript-структурами, но внутри использует:
KJUR.asn1.cms.AttributeKJUR.asn1.DERSetKJUR.crypto.UtilSigned attributes формируются автоматически, но могут быть расширены пользовательскими OID.
Пример добавления пользовательского атрибута:
signedAttrs.push({
type: "1.2.3.4.5.6.7.8.1",
valueHex: "0a0b0c0d"
});
Signed attributes являются обязательным элементом в:
Без них многие реализации (OpenSSL, Java BouncyCastle) отклоняют подпись как некорректную.
Особенно критичны:
messageDigest выполняет роль контрольной точки:
Любое несоответствие между вычисленным и подписанным digest делает подпись недействительной, даже если криптографическая подпись формально корректна.