TimeStampRequest в протоколе RFC 3161 представляет собой ASN.1 структуру, используемую для формирования запроса на криптографическую метку времени. В библиотеке Jsrsasign этот объект выступает как программная модель запроса к TSA (Time Stamping Authority), содержащая данные о хэш-значении документа, политике подписи и дополнительных параметрах, влияющих на генерацию временной метки.
На уровне спецификации RFC 3161 структура определяется следующим образом:
TimeStampReq ::= SEQUENCE {
version INTEGER { v1(1) },
messageImprint MessageImprint,
reqPolicy TSAPolicyId OPTIONAL,
nonce INTEGER OPTIONAL,
certReq BOOLEAN DEFAULT FALSE,
extensions [0] IMPLICIT Extensions OPTIONAL
}
Каждое поле играет строго определённую роль в процессе формирования запроса и последующей валидации ответа от TSA.
Поле version фиксирует версию протокола. В актуальных
реализациях используется значение 1. Несмотря на формальную
возможность расширения, практически все современные TSA ожидают именно
v1.
В Jsrsasign это значение задаётся автоматически при создании объекта запроса, но может быть переопределено вручную при необходимости совместимости с нестандартными реализациями.
Ключевой компонент структуры — messageImprint,
представляющий собой хэшируемое содержимое запроса. Он включает два
обязательных элемента:
ASN.1 структура:
MessageImprint ::= SEQUENCE {
hashAlgorithm AlgorithmIdentifier,
hashedMessage OCTET STRING
}
В Jsrsasign формирование messageImprint обычно выполняется через криптографические утилиты:
var hashHex = KJUR.crypto.Util.hashHex("data", "sha256");
var req = new KJUR.asn1.tsp.TimeStampReq({
hashAlg: "sha256",
hashValue: hashHex
});
Важно, что TSA никогда не получает исходные данные — только их хэш.
Поле reqPolicy задаёт идентификатор политики временной
метки. Это OID (Object Identifier), определяющий правила обработки
запроса на стороне TSA.
Пример:
1.2.3.4.5.6.7.8.1
Если значение отсутствует, TSA применяет политику по умолчанию.
В Jsrsasign параметр задаётся строкой:
reqPolicy: "1.2.3.4.5.6.7.8.1"
Использование политики критично в корпоративных PKI, где разные TSA могут поддерживать разные правила подписи, уровни доверия или требования к алгоритмам.
nonce представляет собой случайное число, используемое
для защиты от атак повторного воспроизведения (replay attack). TSA
обязана включить это значение в ответ, что позволяет клиенту убедиться в
актуальности ответа.
ASN.1 тип — INTEGER, но на практике значение часто генерируется как большое случайное число:
nonce: new KJUR.crypto.MessageDigest({alg: "sha256"}).digest()
или проще:
nonce: String(new Date().getTime())
В Jsrsasign nonce может передаваться как строка или BigInteger-подобное значение, в зависимости от контекста кодирования ASN.1.
Поле certReq определяет, должен ли TSA включать свой
сертификат в ответ (TSTInfo +
PKIStatusInfo).
true — сертификат TSA включаетсяfalse — сертификат не обязателенASN.1 тип BOOLEAN, по умолчанию значение FALSE.
В Jsrsasign:
certReq: true
Это поле часто используется в сценариях, где клиенту необходимо самостоятельно проверить цепочку доверия TSA без внешнего хранилища сертификатов.
Расширения (extensions) позволяют добавлять
дополнительные параметры, не входящие в базовую спецификацию. Они
кодируются как список ASN.1 Extension структур:
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Каждое расширение включает:
extnID — идентификатор расширения (OID)critical — флаг критичностиextnValue — значениеВ Jsrsasign работа с extensions обычно выполняется через низкоуровневые ASN.1 классы:
extensions: [{
extnID: "1.3.6.1.5.5.7.48.3",
critical: false,
extnValue: "..."
}]
Использование расширений характерно для специализированных TSA, поддерживающих дополнительные метаданные: источник запроса, требования к алгоритмам или политики аудита.
После формирования объект TimeStampRequest сериализуется в ASN.1 DER формат. Jsrsasign выполняет кодирование автоматически:
var req = new KJUR.asn1.tsp.TimeStampReq({
hashAlg: "sha256",
hashValue: hashHex,
nonce: "123456",
certReq: true
});
var derHex = req.getEncodedHex();
DER-структура является бинарным представлением, передаваемым в TSA
через HTTP (обычно POST с content-type
application/timestamp-query).
Типовой процесс создания TimeStampRequest в Jsrsasign включает несколько шагов:
var msg = "Hello world";
var hash = KJUR.crypto.Util.hashHex(msg, "sha256");
var tsq = new KJUR.asn1.tsp.TimeStampReq({
hashAlg: "sha256",
hashValue: hash,
nonce: "987654321",
certReq: true,
reqPolicy: "1.2.3.4.5.6.7.8.1"
});
var requestHex = tsq.getEncodedHex();
Результирующий requestHex отправляется на TSA
сервер.
TimeStampRequest тесно связан с другими элементами протокола:
MessageImprint является связующим звеном между клиентскими данными и серверной подписью. Ошибка в выборе алгоритма хэширования или некорректное значение hashedMessage приводит к отказу TSA в обработке запроса.
Jsrsasign реализует TimeStampRequest как объект высокого уровня,
инкапсулирующий ASN.1 структуру. Внутри используется модуль
KJUR.asn1.tsp, который строит последовательность через
базовые ASN.1 классы:
Особенность реализации заключается в строгом соответствии RFC 3161, без добавления неформальных расширений, что делает библиотеку совместимой с большинством TSA серверов.
При работе со структурой часто возникают ошибки, связанные с некорректной подготовкой данных:
Корректная реализация требует строгого соблюдения последовательности формирования messageImprint до создания структуры запроса.
TimeStampRequest по своей природе проще, чем большинство PKI структур:
Это делает его лёгким для генерации, но критически зависимым от корректности криптографического хэша.
TimeStampRequest можно рассматривать как фиксированный контейнер:
В Jsrsasign эта модель реализуется как компактный объект, который преобразуется в ASN.1 DER без промежуточных ручных операций над бинарными структурами