Структура TimeStampRequest

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

Поле version фиксирует версию протокола. В актуальных реализациях используется значение 1. Несмотря на формальную возможность расширения, практически все современные TSA ожидают именно v1.

В Jsrsasign это значение задаётся автоматически при создании объекта запроса, но может быть переопределено вручную при необходимости совместимости с нестандартными реализациями.


messageImprint

Ключевой компонент структуры — messageImprint, представляющий собой хэшируемое содержимое запроса. Он включает два обязательных элемента:

  • hashAlgorithm — идентификатор алгоритма хэширования (например, SHA-256)
  • hashedMessage — результат хэширования исходных данных

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

Поле 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

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

Поле certReq определяет, должен ли TSA включать свой сертификат в ответ (TSTInfo + PKIStatusInfo).

  • true — сертификат TSA включается
  • false — сертификат не обязателен

ASN.1 тип BOOLEAN, по умолчанию значение FALSE.

В Jsrsasign:

certReq: true

Это поле часто используется в сценариях, где клиенту необходимо самостоятельно проверить цепочку доверия TSA без внешнего хранилища сертификатов.


extensions

Расширения (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, поддерживающих дополнительные метаданные: источник запроса, требования к алгоритмам или политики аудита.


Кодирование структуры в DER

После формирования объект 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).


Формирование запроса через Jsrsasign

Типовой процесс создания 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 тесно связан с другими элементами протокола:

  • TimeStampResp — ответ TSA
  • TSTInfo — информация о временной метке
  • MessageImprint — криптографическое ядро запроса

MessageImprint является связующим звеном между клиентскими данными и серверной подписью. Ошибка в выборе алгоритма хэширования или некорректное значение hashedMessage приводит к отказу TSA в обработке запроса.


Особенности реализации в Jsrsasign

Jsrsasign реализует TimeStampRequest как объект высокого уровня, инкапсулирующий ASN.1 структуру. Внутри используется модуль KJUR.asn1.tsp, который строит последовательность через базовые ASN.1 классы:

  • DERSequence
  • DERInteger
  • DERBoolean
  • DEROctetString
  • AlgorithmIdentifier

Особенность реализации заключается в строгом соответствии RFC 3161, без добавления неформальных расширений, что делает библиотеку совместимой с большинством TSA серверов.


Типовые ошибки при формировании запроса

При работе со структурой часто возникают ошибки, связанные с некорректной подготовкой данных:

  • использование неподдерживаемого хэш-алгоритма TSA
  • передача raw-данных вместо hashedMessage
  • отсутствие nonce в системах, требующих защиты от replay
  • неправильное DER-кодирование из-за ручной модификации ASN.1 объектов

Корректная реализация требует строгого соблюдения последовательности формирования messageImprint до создания структуры запроса.


Сравнение с другими ASN.1 структурами

TimeStampRequest по своей природе проще, чем большинство PKI структур:

  • не содержит подписи клиента
  • не включает сертификаты пользователя
  • ограничен минимальным набором обязательных полей

Это делает его лёгким для генерации, но критически зависимым от корректности криптографического хэша.


Итоговая логическая модель структуры

TimeStampRequest можно рассматривать как фиксированный контейнер:

  • идентификация версии протокола
  • криптографическое представление данных через messageImprint
  • параметры политики TSA
  • механизм защиты nonce
  • опциональные настройки сертификатов и расширений

В Jsrsasign эта модель реализуется как компактный объект, который преобразуется в ASN.1 DER без промежуточных ручных операций над бинарными структурами