PEM (Privacy Enhanced Mail) — текстовый формат представления криптографических объектов, основанный на кодировании бинарных данных в Base64 с добавлением заголовков и разделителей. В JavaScript-библиотеке Jsrsasign PEM используется как основной способ передачи ключей, сертификатов и других ASN.1-структур.
Ключевая идея PEM заключается в том, что бинарный DER-объект преобразуется в удобочитаемую строку, пригодную для хранения в файлах и передачи через текстовые протоколы.
Типичная форма PEM-объекта:
-----BEGIN CERTIFICATE-----
MIIC+TCCAeGgAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDApUZXN0
...
-----END CERTIFICATE-----
Основные элементы:
Jsrsasign рассматривает PEM как контейнер, из которого извлекается DER-структура для последующего ASN.1-разбора.
PEM можно разложить на логические части:
Формат:
-----BEGIN <TYPE>-----
Тип определяет содержимое:
Основная часть — это DER, закодированный в Base64.
Характерные особенности:
-----END <TYPE>-----
Тип должен строго совпадать с BEGIN.
PEM — это лишь упаковка. Реальные данные находятся в формате DER (Distinguished Encoding Rules), который является бинарным представлением ASN.1-структур.
Jsrsasign работает следующим образом:
В Jsrsasign ключевую роль играет объект KEYUTIL.
Пример извлечения ключа:
const key = KEYUTIL.getKey(pemString);
Что происходит внутри:
Содержит публичный ключ и метаданные.
Структура:
В Jsrsasign:
const x509 = new X509();
x509.readCertPEM(pemCert);
Доступ к данным:
x509.getSubjectString();
x509.getIssuerString();
x509.getPublicKey();
Начинается с:
-----BEGIN RSA PRIVATE KEY-----
ASN.1 структура:
Jsrsasign автоматически распознаёт этот формат через
KEYUTIL.
Универсальный формат:
-----BEGIN PRIVATE KEY-----
или зашифрованный:
-----BEGIN ENCRYPTED PRIVATE KEY-----
Структура:
В Jsrsasign:
const key = KEYUTIL.getKey(pemPrivateKey);
-----BEGIN PUBLIC KEY-----
Содержит SubjectPublicKeyInfo:
Некоторые PEM включают дополнительные метаданные:
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,AB12CD34EF...
Jsrsasign использует эти поля для:
Удаляются:
Внутренние функции:
b64tohexhextorstrРезультат — hex-представление DER.
Используется модуль:
ASN1HEXПример:
const hex = pemToHex(pem);
const seq = ASN1HEX.getChildIdx(hex, 0);
Пример сертификата:
SEQUENCE
├── TBSCertificate
│ ├── Version
│ ├── SerialNumber
│ ├── Signature
│ ├── Issuer
│ ├── Validity
│ ├── Subject
│ └── SubjectPublicKeyInfo
├── SignatureAlgorithm
└── SignatureValue
Jsrsasign предоставляет методы для обхода дерева без ручного парсинга.
Jsrsasign определяет тип автоматически:
KEYUTIL.getKey(pem)
или вручную:
KEYUTIL.getPEMType(pem)
Возможные значения:
Если:
-----BEGIN CERTIFICATE-----
...
-----END PUBLIC KEY-----
парсер выдаёт ошибку структуры.
Причины:
Например, RSA ключ передан как EC.
Jsrsasign не сможет построить корректный объект.
const hex = KJUR.asn1.ASN1Util.pemToHex(pem);
const der = Buffer.from(b64, 'base64');
const key = KEYUTIL.getKey(pem);
Приватный RSA ключ:
const kp = KEYUTIL.generateKeypair("RSA", 2048);
const pem = KEYUTIL.getPEM(kp.prvKeyObj, "PKCS1PRV");
Публичный ключ:
const pub = KEYUTIL.getPEM(kp.pubKeyObj);
PEM рассматривается как:
PEM = header + base64(DER) + footer
DER затем интерпретируется как:
ASN.1 → структурированное дерево → криптографический объект
После разбора PEM объект используется для:
Пример подписи:
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
sig.init(privateKey);
sig.updateString("data");
const hex = sig.sign();
PEM является базовым транспортным форматом в инфраструктуре открытых ключей:
Jsrsasign использует PEM как универсальный входной слой для PKI-операций.