Использование в Node.js

Установка библиотеки в среде Node.js выполняется через npm и подключение пакета в проект:

npm install jsrsasign

В Node.js библиотека используется как CommonJS-модуль, при этом доступ к основным компонентам осуществляется через require:

const jsrsasign = require("jsrsasign");
const { KEYUTIL, KJUR, hextob64, b64tohex } = jsrsasign;

В некоторых версиях и конфигурациях пакет также поддерживает частичный ESM-импорт, однако на практике в серверной среде Node.js чаще применяется именно CommonJS-форма из-за стабильности и предсказуемости экспорта.


Библиотека построена вокруг нескольких ключевых пространств имён:

  • KEYUTIL — работа с ключами (PEM, DER, генерация, импорт)
  • KJUR.crypto — криптографические алгоритмы (RSA, ECDSA, хэширование)
  • KJUR.jws — JSON Web Signature (JWS)
  • KJUR.jwe — JSON Web Encryption (JWE)
  • ASN1 — работа с ASN.1 структурами
  • утилиты кодирования: base64, hex и преобразования

В Node.js Jsrsasign не использует нативный crypto напрямую для всех операций, а реализует собственную криптографическую обёртку на чистом JavaScript. Это позволяет использовать одинаковое поведение как в браузере, так и на сервере.


Работа с ключами RSA в Node.js

Основной объект для управления ключами — KEYUTIL. Он позволяет создавать, импортировать и экспортировать ключи в формате PEM.

Генерация пары ключей

const kp = KEYUTIL.generateKeypair("RSA", 2048);

const publicKey = kp.pubKeyObj;
const privateKey = kp.prvKeyObj;

После генерации ключи можно преобразовать в PEM:

const pubPEM = KEYUTIL.getPEM(publicKey);
const prvPEM = KEYUTIL.getPEM(privateKey, "PKCS8PRV");

PEM-формат используется для хранения и передачи ключей между системами.


Загрузка ключей из PEM

В Node.js часто требуется загрузка ключей из файлов или переменных окружения:

const fs = require("fs");

const privatePEM = fs.readFileSync("./private.pem", "utf8");
const publicPEM = fs.readFileSync("./public.pem", "utf8");

const privateKey = KEYUTIL.getKey(privatePEM);
const publicKey = KEYUTIL.getKey(publicPEM);

KEYUTIL.getKey автоматически определяет тип ключа (RSA, EC) и преобразует PEM в внутреннее представление Jsrsasign.


Подпись данных (RSA)

Криптографическая подпись выполняется через KJUR.crypto.Signature.

Создание подписи

const sig = new KJUR.crypto.Signature({
    alg: "SHA256withRSA"
});

sig.init(privateKey);
sig.updateString("Hello Node.js");
const signatureHex = sig.sign();

Результат возвращается в hex-формате. Для передачи по сети обычно используется base64:

const signatureBase64 = hextob64(signatureHex);

Проверка подписи

const verifier = new KJUR.crypto.Signature({
    alg: "SHA256withRSA"
});

verifier.init(publicKey);
verifier.updateString("Hello Node.js");

const isValid = verifier.verify(b64tohex(signatureBase64));

Проверка основана на сравнении вычисленного и переданного значения хэша.


Работа с ECDSA в Node.js

Помимо RSA, Jsrsasign поддерживает эллиптические кривые.

Генерация ключей EC

const kp = KEYUTIL.generateKeypair("EC", "secp256r1");
const prv = kp.prvKeyObj;
const pub = kp.pubKeyObj;

Подпись ECDSA

const sig = new KJUR.crypto.Signature({
    alg: "SHA256withECDSA"
});

sig.init(prv);
sig.updateString("data for EC signing");
const sigHex = sig.sign();

ECDSA-подписи компактнее RSA, что делает их удобными для токенов и мобильных приложений.


JWT (JSON Web Token) в Node.js

Одно из наиболее практичных применений Jsrsasign — создание и проверка JWT без дополнительных зависимостей.

Формирование JWT

const header = {
    alg: "HS256",
    typ: "JWT"
};

const payload = {
    sub: "user123",
    role: "admin",
    iat: Math.floor(Date.now() / 1000)
};

const secret = "my-secret-key";

const token = KJUR.jws.JWS.sign(
    "HS256",
    JSON.stringify(header),
    JSON.stringify(payload),
    secret
);

Проверка JWT

const isValid = KJUR.jws.JWS.verify(token, secret, ["HS256"]);

if (isValid) {
    const parsed = KJUR.jws.JWS.parse(token);
    const payload = parsed.payloadObj;
}

Парсер возвращает структуру с заголовком, полезной нагрузкой и подписью.


RS256 JWT с PEM-ключами

В реальных серверных системах чаще используется асимметричная схема RS256.

Подпись

const token = KJUR.jws.JWS.sign(
    "RS256",
    JSON.stringify(header),
    JSON.stringify(payload),
    privatePEM
);

Проверка

const ok = KJUR.jws.JWS.verify(token, publicPEM, ["RS256"]);

Этот подход позволяет отделить сервис подписи (auth-server) от сервисов проверки.


Работа с хэшированием

Jsrsasign включает реализацию популярных хэш-функций:

const hash = KJUR.crypto.Util.hashString("SHA256", "data");

Также поддерживаются:

  • SHA-1
  • SHA-256
  • SHA-384
  • SHA-512
  • MD5 (устаревший, используется редко)

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


Кодировки и преобразования

В Node.js важно учитывать форматы представления данных.

Hex ↔︎ Base64

const hex = "616263";
const b64 = hextob64(hex);

const backToHex = b64tohex(b64);

UTF-8 строки

const utf8Hex = Buffer.from("тест", "utf8").toString("hex");

Jsrsasign работает преимущественно с hex-строками, поэтому преобразования часто обязательны при интеграции с внешними API.


ASN.1 в Node.js

Jsrsasign содержит собственный ASN.1 парсер, который используется для разбора сертификатов и ключей.

Пример чтения структуры:

const asn1 = ASN1HEX.parse("30...hex...");

ASN.1 используется в:

  • X.509 сертификатах
  • RSA ключах (PKCS#1)
  • EC ключах (SEC1)

Работа с X.509 сертификатами

Node.js часто использует Jsrsasign для анализа сертификатов без OpenSSL.

const certPEM = fs.readFileSync("./cert.pem", "utf8");

const x509 = new X509();
x509.readCertPEM(certPEM);

const subject = x509.getSubjectString();
const issuer = x509.getIssuerString();
const serial = x509.getSerialNumberHex();

Проверка подписи сертификата:

const publicKey = x509.getPublicKey();

Интеграция с Node.js crypto (сравнение подходов)

Node.js имеет встроенный модуль crypto, однако Jsrsasign используется в случаях:

  • кросс-платформенная совместимость (браузер + Node.js)
  • работа с PEM без OpenSSL-обёрток
  • реализация JWT без зависимостей
  • контроль низкоуровневых ASN.1 структур

При этом встроенный crypto обычно быстрее, но менее универсален в переносимых проектах.


Пример серверной логики подписи

const http = require("http");
const { KJUR, KEYUTIL } = require("jsrsasign");

const privateKey = KEYUTIL.getKey(fs.readFileSync("./private.pem", "utf8"));

http.createServer((req, res) => {
    const data = "server-data";

    const sig = new KJUR.crypto.Signature({
        alg: "SHA256withRSA"
    });

    sig.init(privateKey);
    sig.updateString(data);

    const signature = hextob64(sig.sign());

    res.end(JSON.stringify({ data, signature }));
}).listen(3000);

Пример проверки на клиентской стороне Node.js

const { KJUR, KEYUTIL } = require("jsrsasign");

const publicKey = KEYUTIL.getKey(fs.readFileSync("./public.pem", "utf8"));

function verify(data, signature) {
    const sig = new KJUR.crypto.Signature({
        alg: "SHA256withRSA"
    });

    sig.init(publicKey);
    sig.updateString(data);

    return sig.verify(b64tohex(signature));
}

Особенности использования в серверной среде

При работе в Node.js важно учитывать:

  • отсутствие нативной оптимизации OpenSSL в Jsrsasign
  • необходимость ручного управления форматами (hex/base64)
  • детерминированность алгоритмов между средами
  • совместимость JWT между сервисами

Jsrsasign стабильно используется в микросервисных архитектурах, где важна идентичность криптографического поведения в браузере и сервере.