Цифровой сертификат X.509 содержит подпись удостоверяющего центра (CA), подтверждающую подлинность содержащихся в нём данных. Проверка подписи — это криптографическая операция, гарантирующая, что сертификат:
Библиотека jsrsasign предоставляет полный набор инструментов для разбора сертификатов и проверки их подписей с использованием различных алгоритмов (RSA, ECDSA, DSA).
Сертификат включает три ключевых компонента:
Проверка подписи заключается в следующем:
tbsCertificateСертификат может быть представлен в формате PEM или DER. В jsrsasign
используется класс X509.
const { X509 } = require('jsrsasign');
const certPEM = `-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----`;
const x509 = new X509();
x509.readCertPEM(certPEM);
После загрузки объект x509 содержит доступ ко всем полям
сертификата.
const sigAlg = x509.getSignatureAlgorithmField();
Примеры значений:
SHA256withRSASHA384withECDSAЭто важно для корректной проверки подписи.
const signatureHex = x509.getSignatureValueHex();
const tbsHex = x509.getTBSCertificateHex();
signatureHex — подписьtbsHex — исходные данныеПроверка выполняется с использованием публичного ключа CA. Этот ключ может быть:
const { KEYUTIL } = require('jsrsasign');
const caCertPEM = `-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----`;
const caX509 = new X509();
caX509.readCertPEM(caCertPEM);
const pubKey = caX509.getPublicKey();
jsrsasign предоставляет класс KJUR.crypto.Signature.
const { KJUR } = require('jsrsasign');
const sig = new KJUR.crypto.Signature({
alg: sigAlg
});
sig.init(pubKey);
sig.updateHex(tbsHex);
const isValid = sig.verify(signatureHex);
true — подпись корректнаfalse — подпись недействительнаПричины ошибки:
jsrsasign предоставляет упрощённый метод:
const isValid = x509.verifySignature(pubKey);
Этот способ:
Одиночная проверка подписи недостаточна. В реальных системах используется цепочка:
Root CA → Intermediate CA → End Entity Certificate
Каждый сертификат проверяется:
Пример ручной проверки цепочки:
function verifyChain(cert, issuerCert) {
const issuerKey = issuerCert.getPublicKey();
return cert.verifySignature(issuerKey);
}
Самоподписанный сертификат подписывает сам себя:
const pubKey = x509.getPublicKey();
const isSelfSigned = x509.verifySignature(pubKey);
Такой сертификат:
Важно учитывать криптостойкость:
| Алгоритм | Статус |
|---|---|
| SHA1withRSA | устарел |
| SHA256withRSA | рекомендуется |
| SHA384withECDSA | безопасный |
Получение алгоритма:
const alg = x509.getSignatureAlgorithmField();
Проверка подписи не гарантирует, что сертификат актуален:
const now = new Date();
const notBefore = x509.getNotBefore();
const notAfter = x509.getNotAfter();
const isValidTime = now >= new Date(notBefore) && now <= new Date(notAfter);
jsrsasign не выполняет автоматическую проверку CRL или OCSP, но можно:
const cdp = x509.getExtCRLDistributionPointsURI();
1. Неправильный публичный ключ
Используется ключ не того CA.
2. Несоответствие алгоритма
Алгоритм подписи не совпадает с инициализацией
Signature.
3. Повреждённый PEM
Ошибки форматирования:
4. DER/HEX путаница
Некорректная интерпретация бинарных данных.
const { X509 } = require('jsrsasign');
function verifyCertificate(certPEM, caCertPEM) {
const cert = new X509();
cert.readCertPEM(certPEM);
const caCert = new X509();
caCert.readCertPEM(caCertPEM);
const pubKey = caCert.getPublicKey();
return cert.verifySignature(pubKey);
}
Библиотека:
Проверка нескольких сертификатов:
certList.every((cert, index) => {
if (index === certList.length - 1) return true;
return cert.verifySignature(certList[index + 1].getPublicKey());
});
Проверка сертификата клиента (mTLS):
Проверка подписи сертификата используется в: