Модуль работает с расширениями CMS/PKCS
Основная задача слоя ASN.1 в контексте CAdES заключается не просто в сериализации данных, а в точном соблюдении спецификаций X.690/X.690 DER, поскольку любые отклонения приводят к невозможности верификации подписи в внешних системах. Именно поэтому модуль ASN.1 в Jsrsasign рассматривается как фундамент для построения доверенных криптографических структур.
CAdES-подпись базируется на CMS (Cryptographic Message Syntax), где основной контейнер представляет собой последовательность ASN.1-объектов:
Каждый из этих элементов представлен ASN.1 SEQUENCE с вложенными структурами. Например, SignedData содержит список сертификатов, алгоритмов и подписанных данных, закодированных строго по DER.
Ключевая особенность заключается в том, что даже изменение порядка атрибутов или способа кодирования INTEGER/OBJECT IDENTIFIER приводит к невалидной подписи.
В библиотеке Jsrsasign ASN.1-дерево представлено объектной моделью, основанной на классах DER:
KJUR.asn1.DERSequenceKJUR.asn1.DERSetKJUR.asn1.DERIntegerKJUR.asn1.DERUTF8StringKJUR.asn1.DERTaggedObjectКаждый узел дерева соответствует ASN.1 типу и может быть вложен в другие структуры. Например:
var seq = new KJUR.asn1.DERSequence({
array: [
new KJUR.asn1.DERInteger({ int: 1 }),
new KJUR.asn1.DERUTF8String({ str: "test" })
]
});
Такое представление позволяет формировать сложные структуры CMS без ручного кодирования байтов.
CAdES требует строго DER-совместимого кодирования. Основные ограничения:
Jsrsasign автоматически применяет DER-правила при вызове
getEncodedHex() у ASN.1-объектов. Это критично при
формировании подписей, так как даже один лишний байт нарушает
криптографическую проверку.
SignedAttributes в CAdES — это набор ASN.1 атрибутов, которые включаются в процесс хэширования перед подписью. Они всегда кодируются как DER SET OF, где порядок элементов должен быть строго отсортирован по DER-правилам.
Типичная структура включает:
В Jsrsasign это представляется как DERSet:
var attrs = new KJUR.asn1.DERSet({
array: [
new KJUR.asn1.DERSequence({
array: [
new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.9.3" }),
new KJUR.asn1.DERSet({
array: [
new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.7.1" })
]
})
]
})
]
});
Каждый атрибут является ASN.1 SEQUENCE из OID и значения, что полностью соответствует PKCS#9.
OID (Object Identifier) является фундаментальным элементом ASN.1. В CAdES они определяют алгоритмы, атрибуты и типы контейнеров.
Jsrsasign использует DERObjectIdentifier:
new KJUR.asn1.DERObjectIdentifier({
oid: "2.5.4.3"
});
Бинарные данные (например, хэш или подпись) кодируются через DEROctetString:
new KJUR.asn1.DEROctetString({
hex: "deadbeef"
});
При этом hex-строка должна быть строго парной и не содержать префиксов.
CMS/CAdES активно использует вложенность ASN.1. Например:
SignedData
Каждый уровень реализуется через DERSequence с массивом вложенных объектов. Jsrsasign позволяет строить такие деревья рекурсивно, не ограничивая глубину.
Пример базовой структуры:
var signedData = new KJUR.asn1.DERSequence({
array: [
new KJUR.asn1.DERInteger({ int: 1 }),
new KJUR.asn1.DERSet({ array: [] }),
new KJUR.asn1.DERSequence({ array: [] })
]
});
На практике такие структуры значительно сложнее, но принцип остаётся неизменным: дерево DER-объектов.
ASN.1 в CAdES часто использует контекстные теги [0], [1], [2] для обозначения опциональных полей. В Jsrsasign это реализовано через DERTaggedObject:
new KJUR.asn1.DERTaggedObject({
tag: "a0",
explicit: false,
obj: new KJUR.asn1.DERSequence({ array: [] })
});
Параметр tag задаёт HEX-представление ASN.1 тега, где
a0 соответствует [0] CONSTRUCTED.
Правильная работа с тегами критична для совместимости с внешними криптопровайдерами.
Базовый профиль CAdES-BES включает:
ASN.1 дерево строится снизу вверх. Сначала формируются атрибуты, затем вычисляется хэш, затем создаётся SignerInfo.
SignerInfo в ASN.1 выглядит как:
Каждое поле является DER-объектом, а порядок строго фиксирован стандартом.
Jsrsasign предоставляет методы:
getEncodedHex() — сериализация в DER HEXfromBER() — разбор бинарного ASN.1Пример сериализации:
var hex = seq.getEncodedHex();
При обратном разборе:
var asn1 = ASN1HEX.decode(hex);
ASN1HEX позволяет навигацию по дереву без полной десериализации, что полезно для анализа подписанных контейнеров.
При работе с ASN.1 в CAdES наиболее частые проблемы:
Jsrsasign частично предотвращает ошибки, но ответственность за структуру лежит на разработчике, поскольку библиотека оперирует низкоуровневым представлением.
Сертификаты X.509 также являются ASN.1 структурами и часто включаются в CAdES контейнер как CertificateSet.
Структура сертификата:
Jsrsasign позволяет как разбирать, так и включать сертификаты в CMS через DERSequence.
При создании CAdES-структур используется подход постепенного построения дерева:
Каждый шаг зависит от предыдущего, что делает ASN.1 не просто форматом, а процессной моделью данных.
ASN.1 слой в Jsrsasign активно взаимодействует с бинарными структурами CMS. Это означает, что любые изменения в байтовом представлении отражаются на криптографической валидности.
Особое внимание уделяется:
Любая нестабильность приводит к различию signature value при повторном вычислении.
ASN.1 модуль тесно связан с:
Алгоритмы кодируются через AlgorithmIdentifier:
new KJUR.asn1.DERSequence({
array: [
new KJUR.asn1.DERObjectIdentifier({ oid: "1.2.840.113549.1.1.11" }),
new KJUR.asn1.DERNull()
]
});
Такой подход обеспечивает универсальность криптографических операций внутри ASN.1 дерева.
Jsrsasign допускает модификацию узлов после создания, однако это опасная операция в контексте CAdES, так как нарушает целостность подписи.
Типичные операции:
Любое изменение требует пересчёта подписи, иначе структура становится недействительной.
При верификации CAdES подписи ASN.1 используется для:
Без корректного ASN.1 разбора невозможно восстановить оригинальные данные подписи, что делает этот модуль ключевым элементом всей криптографической цепочки.