Клиентская аутентификация на основе сертификатов строится вокруг криптографической пары ключей и X.509-сертификата, в котором публичный ключ связывается с идентичностью пользователя или устройства. В классическом сценарии TLS (mTLS) сервер запрашивает сертификат клиента на уровне транспортного соединения, после чего выполняется взаимная проверка доверия.
В браузерной среде прямой контроль над TLS-рукопожатием ограничен, поэтому библиотека Jsrsasign используется в основном для реализации прикладной (application-layer) аутентификации, где криптографическая подпись запросов заменяет или дополняет mTLS.
Jsrsasign предоставляет набор инструментов для работы с PKI:
Ключевые пространства имён:
KEYUTIL — импорт и экспорт ключейX509 — работа с сертификатамиKJUR.crypto — криптографические операцииKJUR.asn1 — построение ASN.1 структурРаспространённый формат для клиентской аутентификации —
.p12 (или .pfx), содержащий приватный ключ и
сертификат.
const p12Der = ...; // ArrayBuffer или base64
const password = "secret";
const keyObj = KEYUTIL.getKey(p12Der, password);
const certB64 = KEYUTIL.getPEM(keyObj.getCertificate());
const privateKey = keyObj;
В результате получается:
const cert = new X509();
cert.readCertPEM(certB64);
const subject = cert.getSubjectString();
const issuer = cert.getIssuerString();
const serial = cert.getSerialNumberHex();
Ключевые элементы сертификата:
Поскольку браузер не управляет TLS-рукопожатием, используется схема challenge-response.
Сервер отправляет случайное значение:
{
"nonce": "8f3a91c2b7d4..."
}
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
sig.init(privateKey);
sig.updateString(nonce);
const signature = sig.sign();
const signatureBase64 = hextob64(signature);
fetch("/auth/verify", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
nonce,
signature: signatureBase64,
certificate: certB64
})
});
Сервер выполняет:
const x509 = new X509();
x509.readCertPEM(certB64);
const pubKey = x509.getPublicKey();
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
sig.init(pubKey);
sig.updateString(nonce);
const isValid = sig.verify(b64tohex(signature));
Аутентификация считается полной только при проверке цепочки доверия:
Jsrsasign позволяет частично валидировать структуру сертификата, но проверка цепочки доверия обычно реализуется на сервере через PKI-библиотеки.
Jsrsasign поддерживает ECDSA подписи:
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withECDSA" });
sig.init(privateKey);
sig.updateString(data);
const sigValue = sig.sign();
ECDSA используется в современных мобильных и аппаратных сертификатах.
При регистрации клиента может формироваться запрос на сертификат.
const kp = KEYUTIL.generateKeypair("RSA", 2048);
const csr = new KJUR.asn1.csr.CSR({
subject: { str: "/CN=user@example.com" },
sbjpubkey: kp.pubKeyObj,
sigalg: "SHA256withRSA",
sbjprvkey: kp.prvKeyObj
});
const pem = csr.getPEM();
CSR передаётся в центр сертификации для выпуска клиентского сертификата.
После успешной проверки сертификата его данные используются как стабильный идентификатор:
const thumbprint = KJUR.crypto.Util.hashHex(certB64, "sha256");
Сервер может привязывать токен к отпечатку сертификата:
session_id + cert_fingerprint
Это предотвращает повторное использование токенов без приватного ключа.
Часто применяется комбинированная схема:
Работа с сертификатами в JavaScript имеет ограничения:
Jsrsasign не предоставляет аппаратной защиты ключей, поэтому применяются подходы:
WebCrypto может генерировать ключи, а Jsrsasign — обрабатывать сертификаты:
const keyPair = await crypto.subtle.generateKey(
{ name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, hash: "SHA-256" },
true,
["sign", "verify"]
);
Экспорт ключа для Jsrsasign:
const exported = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
const key = KEYUTIL.getKey(exported);
Расширенная модель включает подпись параметров запроса:
const data = method + url + body + timestamp;
sig.init(privateKey);
sig.updateString(data);
const signature = sig.sign();
Заголовки:
X-Signature: ...
X-Certificate: ...
X-Timestamp: ...
Сервер повторяет вычисление строки:
method + url + body + timestamp
и сверяет подпись с публичным ключом из сертификата.
Используются:
Jsrsasign позволяет анализировать структуру цепочки:
const chain = cert.getExtSubjectAltName();
const basicConstraints = cert.getExtBasicConstraints();
Эти данные используются для определения:
Типовые ошибки:
Invalid signature — несоответствие ключаExpired certificate — истёк срок действияUnknown CA — не доверенный центр сертификацииMalformed PKCS#12 — повреждённый контейнерСертификатная аутентификация через Jsrsasign часто используется в:
Модель позволяет отказаться от паролей в пользу криптографической идентичности пользователя.