RecipientInfo в CMS (Cryptographic Message Syntax, PKCS
В jsrsasign работа с CMS реализована через пространство имён
KJUR.asn1.cms, где структуры данных соответствуют
ASN.1-описанию стандарта RFC 5652.
KeyTransRecipientInfo применяется в случаях, когда отправитель заранее знает публичный ключ получателя и использует его для шифрования содержимого ключа (Content Encryption Key, CEK). В отличие от KeyAgreeRecipientInfo, здесь не выполняется протокол согласования ключа, а происходит прямое шифрование.
Формальная структура CMS определяет KeyTransRecipientInfo следующим образом:
KeyTransRecipientInfo ::= SEQUENCE {
version CMSVersion, -- integer
rid RecipientIdentifier,
keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
encryptedKey EncryptedKey
}
Поле version определяет версию структуры:
Это значение зависит от способа идентификации получателя.
RecipientIdentifier может быть двух типов:
RecipientIdentifier ::= CHOICE {
issuerAndSerialNumber IssuerAndSerialNumber,
subjectKeyIdentifier [0] SubjectKeyIdentifier
}
Наиболее распространённый вариант в PKI:
Используется идентификатор открытого ключа, извлечённый из сертификата.
Описывает алгоритм шифрования симметричного ключа.
Чаще всего используется:
Пример OID:
1.2.840.113549.1.1.1 — RSA encryption1.2.840.113549.1.1.7 — RSAES-OAEPСодержит симметричный ключ (CEK), зашифрованный публичным ключом получателя.
В jsrsasign структура KeyTransRecipientInfo создаётся через ASN.1 конструкторы:
var KJUR = require("jsrsasign");
var ri = new KJUR.asn1.cms.RecipientIdentifier({
type: "issuerAndSerialNumber",
issuer: {
str: "/C=US/O=Test/CN=Test CA"
},
serial: { int: 123456 }
});
Пример создания структуры KeyTransRecipientInfo с RSA:
var KJUR = require("jsrsasign");
// алгоритм шифрования ключа
var alg = new KJUR.asn1.x509.AlgorithmIdentifier({
name: "rsaEncryption"
});
// идентификатор получателя
var rid = new KJUR.asn1.cms.RecipientIdentifier({
type: "issuerAndSerialNumber",
issuer: {
str: "/C=RU/O=Example/CN=Recipient"
},
serial: {
int: 10001
}
});
// зашифрованный симметричный ключ (пример байтов)
var encryptedKeyHex = "a1b2c3d4e5f6";
// KeyTransRecipientInfo
var ktri = new KJUR.asn1.cms.KeyTransRecipientInfo({
version: 0,
rid: rid,
keyEncryptionAlgorithm: alg,
encryptedKey: {
hex: encryptedKeyHex
}
});
Альтернативный вариант идентификации:
var ridSKI = new KJUR.asn1.cms.RecipientIdentifier({
type: "subjectKeyIdentifier",
ski: {
hex: "1a2b3c4d5e6f"
}
});
В этом случае версия структуры меняется на 2, поскольку используется SKI вместо IssuerAndSerialNumber.
KeyTransRecipientInfo является частью массива RecipientInfos внутри EnvelopedData:
EnvelopedData ::= SEQUENCE {
version CMSVersion,
originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
recipientInfos RecipientInfos,
encryptedContentInfo EncryptedContentInfo,
...
}
В jsrsasign:
var env = new KJUR.asn1.cms.EnvelopedData({
version: 2,
recipientInfos: [ktri],
encryptedContentInfo: {
contentType: "data",
contentEncryptionAlgorithm: {
name: "aes-256-cbc",
iv: { hex: "00112233445566778899aabbccddeeff" }
},
encryptedContent: {
hex: "deadbeef..."
}
}
});
Процесс формирования структуры включает несколько этапов:
Библиотека строго следует DER-кодированию:
KeyTransRecipientInfo в jsrsasign ориентирован на базовые сценарии CMS:
Если используется SKI, но version остаётся 0, структура становится некорректной для строгих CMS-парсеров.
encryptedKey должен быть:
При разборе CMS в jsrsasign:
var cms = new KJUR.asn1.cms.ContentInfo({
hextStr: cmsHex
});
var recipientInfos = cms.asn1.recipientInfos;
KeyTransRecipientInfo извлекается как элемент SEQUENCE внутри RecipientInfos, где каждый элемент соответствует отдельному получателю.
RecipientIdentifier напрямую связан с сертификатом:
Пример получения SKI из сертификата:
var x509 = new X509();
x509.readCertPEM(certPem);
var ski = x509.getExtSubjectKeyIdentifier();
KeyTransRecipientInfo соответствует:
Структура остаётся совместимой с OpenSSL, Java CMS, .NET System.Security.Cryptography.Pkcs.
KeyTransRecipientInfo реализует классическую гибридную схему:
В CMS это основная модель для EnvelopedData без использования соглашений о ключах.