Устаревшие функции jsrsasign и их замена

Переход от KEYUTIL.getKey старого формата к современным методам работы с ключами

В ранних версиях Jsrsasign для работы с криптографическими ключами активно использовался универсальный метод:

var key = KEYUTIL.getKey(pem);

Он принимал строку PEM и автоматически пытался определить тип ключа (RSA, EC, DSA). Однако со временем подход стал считаться слишком неявным: при сложных сценариях парсинга или работе с нестандартными ключами возникали неоднозначности.

Современный подход предполагает явное указание типа ключа или использование специализированных функций:

var rsaKey = KEYUTIL.getKey(pem, null, "RSAKEY");
var ecKey  = KEYUTIL.getKey(pem, null, "EC");

Также рекомендуется использовать раздельные функции для повышения читаемости и предсказуемости поведения:

  • KEYUTIL.getRSAKeyFromPlainPrivatePKCS8PEM
  • KEYUTIL.getECPublicKeyFromPEM
  • KEYUTIL.getKeyInfo

Это позволяет избежать автоматического определения типа и снижает вероятность ошибок при обработке нестандартных PEM-структур.


Устаревание KJUR.jws.JWS.parse без проверки подписи

Ранние реализации разбора JWT через:

var result = KJUR.jws.JWS.parse(token);

возвращали структуру токена без обязательной проверки подписи. Это часто приводило к ошибочному восприятию безопасности: разработчики считали, что декодирование эквивалентно валидации.

В актуальной версии библиотеки предпочтительным является разделение операций:

var isValid = KJUR.jws.JWS.verifyJWT(token, key, { alg: ["RS256"] });

и только после этого:

var payloadObj = KJUR.jws.JWS.parse(token).payloadObj;

Либо использование:

KJUR.jws.JWS.verify(token, key, { alg: ["RS256"] });

с последующим разбором payload через b64utoutf8.

Основная причина отказа от старого подхода — предотвращение сценариев, при которых декодированный JWT воспринимается как доверенный.


Замена KJUR.jws.IntDate.get и устаревшие преобразования времени

Ранее для работы с UNIX-временем в JWT использовались методы:

KJUR.jws.IntDate.get("now");
KJUR.jws.IntDate.get("now + 3600");

Такой строковый парсинг времени был удобен, но приводил к скрытым ошибкам в сложных вычислениях.

Современный подход исключает строковые выражения:

var now = Math.floor(Date.now() / 1000);
var exp = now + 3600;

При необходимости форматирования используется явное преобразование:

var intDate = KJUR.jws.IntDate.getUnixTime(exp);

Функции с парсингом строк считаются устаревшими из-за низкой прозрачности вычислений.


Устаревший KJUR.crypto.Signature.init в пользу явной конфигурации алгоритма

Старый способ инициализации подписи выглядел так:

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

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

Современный подход требует фиксировать алгоритм заранее:

var sig = new KJUR.crypto.Signature({ alg: "SHA256withRSA" });
sig.init(privateKey);
sig.updateString(data);
var signature = sig.sign();

Изменение алгоритма после создания объекта больше не поддерживается как безопасная практика.


Замена KJUR.asn1.ASN1Util.newObject на специализированные классы

Ранее:

var obj = KJUR.asn1.ASN1Util.newObject({
  seq: [
    { int: 3 },
    { octstr: "abcd" }
  ]
});

Такой универсальный конструктор позволял описывать ASN.1 через JSON-подобную структуру, но страдал от слабой типизации и высокой вероятности ошибок.

Современная модель предполагает использование конкретных классов:

var seq = new KJUR.asn1.DERSequence({
  array: [
    new KJUR.asn1.DERInteger({ int: 3 }),
    new KJUR.asn1.DEROctetString({ str: "abcd" })
  ]
});

Переход к классовой модели улучшает читаемость и упрощает отладку ASN.1-структур.


Отказ от KJUR.jws.JWS.verifyJWT с автоматическим выбором ключа

Старый вариант:

KJUR.jws.JWS.verifyJWT(token, key);

допускал сценарии, в которых ключ подбирался без явного указания алгоритма, что создавало риск атак типа algorithm confusion.

Современный подход требует строгого указания допустимых алгоритмов:

KJUR.jws.JWS.verifyJWT(token, key, {
  alg: ["RS256", "ES256"]
});

Также рекомендуется предварительная проверка заголовка:

var header = KJUR.jws.JWS.readSafeJSONString(b64utoutf8(token.split(".")[0]));

Это позволяет исключить несоответствие алгоритма до проверки подписи.


Устаревшие методы работы с Base64

Ранее широко использовались:

hextob64(str);
b64tohex(str);

Эти функции не учитывали URL-safe variant Base64, что критично для JWT.

Современная замена:

KJUR.lang.String.prototype.b64u;
KJUR.lang.String.prototype.b64utohex;

или прямые утилиты:

hextob64u(str);
b64utohex(str);

Использование URL-safe Base64 стало стандартом, поэтому старые методы считаются устаревшими в контексте JWS/JWT.


Устаревание глобальных пространств имён KJUR.crypto, KJUR.jws без модульной изоляции

Ранее Jsrsasign активно использовал глобальный объект KJUR, что приводило к конфликтам в браузерных окружениях и при сборке через bundler’ы:

KJUR.crypto.Signature
KJUR.jws.JWS

Современная практика предполагает импорт через модули:

import { KEYUTIL, KJUR } from "jsrsasign";

или использование ESM-сборок библиотеки.

Это позволяет избежать загрязнения глобального пространства и улучшает совместимость с Webpack, Vite и Node.js ESM.


Замена KJUR.crypto.Mac старой инициализации на явное указание алгоритма

Ранее:

var mac = new KJUR.crypto.Mac({ alg: "HmacSHA256" });
mac.init(secret);

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

Современный вариант фиксирует алгоритм при создании:

var mac = new KJUR.crypto.Mac({ alg: "HmacSHA256" });
mac.updateString(message);
var hmac = mac.doFinal();

Повторная инициализация с другим алгоритмом требует создания нового объекта.


Устаревший KJUR.jws.JWS.parse для не-JWT токенов

Ранее метод применялся для разбора любых JWS-подобных структур:

KJUR.jws.JWS.parse(compactJWS);

Однако отсутствие строгой проверки структуры приводило к ошибкам при обработке некорректных токенов.

Современная практика:

KJUR.jws.JWS.isSafeJSONString(headerSegment)
KJUR.jws.JWS.verify(token, key)

Парсинг и валидация разделены на отдельные шаги, что снижает вероятность обработки повреждённых или поддельных токенов.


Устаревание автоматического выбора алгоритма в JWS.sign

Ранее:

var jws = KJUR.jws.JWS.sign(null, header, payload, key);

Алгоритм мог быть определён из header, что создавало риск подмены alg.

Современный подход:

var jws = KJUR.jws.JWS.sign("RS256", header, payload, key);

Явное указание алгоритма стало обязательной практикой, исключающей зависимость от входных данных заголовка.