SEQUENCE
В ASN.1 SEQUENCE представляет собой упорядоченную коллекцию элементов, где каждый компонент имеет фиксированную позицию. В терминах кодирования это структурный контейнер, в котором важен порядок полей и их типы. В криптографических протоколах SEQUENCE используется практически везде: сертификаты X.509, ключевые структуры PKCS
В Jsrsasign SEQUENCE реализуется через класс
KJUR.asn1.DERSequence. Он позволяет объединять произвольные
ASN.1-объекты в строгую последовательность.
Базовая структура SEQUENCE:
Простейший пример формирования SEQUENCE:
const { ASN1Object, DERInteger, DERUTF8String, DERSequence } = KJUR.asn1;
const seq = new DERSequence({
array: [
new DERInteger({ int: 123 }),
new DERUTF8String({ str: "test" })
]
});
const hex = seq.getEncodedHex();
Внутри SEQUENCE могут находиться вложенные структуры:
const inner = new DERSequence({
array: [
new DERInteger({ int: 1 }),
new DERInteger({ int: 2 })
]
});
const outer = new DERSequence({
array: [
inner,
new DERUTF8String({ str: "nested" })
]
});
SEQUENCE активно применяется при описании алгоритмических параметров. Например, RSA публичный ключ кодируется как последовательность модуль/экспонента.
SET
SET является структурой, похожей на SEQUENCE, но с принципиальным отличием: порядок элементов не является значимым. В ASN.1 это неупорядоченное множество уникальных элементов.
Особенности SET:
В Jsrsasign SET представлен классом
KJUR.asn1.DERSet.
Пример создания SET:
const { DERInteger, DERUTF8String, DERSet } = KJUR.asn1;
const set = new DERSet({
array: [
new DERUTF8String({ str: "B" }),
new DERUTF8String({ str: "A" })
]
});
const hex = set.getEncodedHex();
При DER-кодировании элементы SET автоматически упорядочиваются по байтовому представлению, что обеспечивает детерминированность результата.
SET часто используется в криптографических подписях, особенно в структурах типа Attributes в PKCS#7/CMS, где набор атрибутов не зависит от порядка.
CHOICE
CHOICE представляет собой конструкцию выбора одного варианта из нескольких возможных типов. В отличие от SEQUENCE и SET, CHOICE не содержит одновременно несколько полей — активным является только один вариант.
В ASN.1 это выражение альтернативности:
В Jsrsasign CHOICE не имеет отдельного низкоуровневого класса. Он реализуется через механизм ASN1Object описаний и условной сборки структур.
Типичный подход через KJUR.asn1.ASN1Util.newObject:
const { ASN1Util } = KJUR.asn1;
const obj = ASN1Util.newObject({
utf8str: { str: "text value" }
});
Другой вариант — ручное ветвление:
function buildChoice(type, value) {
const { DERInteger, DERUTF8String } = KJUR.asn1;
if (type === "int") {
return new DERInteger({ int: value });
}
if (type === "str") {
return new DERUTF8String({ str: value });
}
throw new Error("unsupported choice");
}
CHOICE широко используется в протоколах, где формат поля зависит от контекста: алгоритмы подписи, альтернативные идентификаторы, разные типы ключевых параметров.
ANY
ANY в ASN.1 обозначает неопределённый тип, который может принимать любое ASN.1-значение. Это наиболее гибкая, но и наименее строгая конструкция.
Характерные особенности:
В Jsrsasign ANY напрямую не представлен как отдельный класс,
поскольку ASN.1-библиотека ориентирована на конкретные типы. Вместо
этого ANY реализуется через работу с ASN1Object и
динамическую вставку уже закодированных структур.
Пример вставки произвольного ASN.1-объекта:
const { DERSequence, DERInteger, DERUTF8String } = KJUR.asn1;
const anyValue = new DERSequence({
array: [
new DERInteger({ int: 999 }),
new DERUTF8String({ str: "any content" })
]
});
const container = new DERSequence({
array: [
anyValue
]
});
В некоторых случаях ANY кодируется как заранее сериализованный HEX:
const raw = KJUR.asn1.ASN1Util.newObject({
seq: {
array: [
{ int: { int: 1 } }
]
}
}).getEncodedHex();
const wrapped = KJUR.asn1.ASN1Util.newObject({
any: raw
});
ANY часто встречается в расширениях сертификатов X.509, где структура расширения может быть определена внешним стандартом и не фиксирована в базовой схеме.
Сравнение поведения конструкций
SEQUENCE фиксирует структуру и порядок, обеспечивая строгую типизацию данных. SET допускает множество значений без зависимости от порядка, что важно для канонических криптографических представлений. CHOICE вводит альтернативность, позволяя одному полю принимать разные типы в зависимости от контекста. ANY снимает ограничения на структуру, передавая ответственность за интерпретацию внешнему уровню.
В Jsrsasign эти конструкции реализуются неравномерно: SEQUENCE и SET имеют прямые классы DERSequence и DERSet, CHOICE строится через условное создание объектов, ANY — через универсальные ASN1Object или предварительно закодированные данные.
Композиция сложных структур
ASN.1-модели редко существуют изолированно. На практике конструкции комбинируются:
const { DERSequence, DERSet, DERInteger, DERUTF8String } = KJUR.asn1;
const attributes = new DERSet({
array: [
new DERSequence({
array: [
new DERUTF8String({ str: "key" }),
new DERInteger({ int: 1 })
]
}),
new DERSequence({
array: [
new DERUTF8String({ str: "role" }),
new DERUTF8String({ str: "admin" })
]
})
]
});
Такие структуры типичны для PKCS#7, CMS и расширений сертификатов, где вложенность достигает нескольких уровней, а семантика определяется комбинацией SEQUENCE и SET внутри гибких контейнеров ANY и CHOICE.
Каноническое кодирование DER
Все перечисленные типы в контексте Jsrsasign чаще всего кодируются по правилам DER (Distinguished Encoding Rules), что накладывает дополнительные ограничения:
DER-выход можно получить через:
const hex = sequence.getEncodedHex();
Этот механизм является ключевым для совместимости с криптографическими системами, включая проверку цифровых подписей и валидацию сертификатов.