Библиотека jsrsasign реализует криптографические операции высокого
уровня поверх JavaScript, включая RSA, ECDSA, HMAC и работу с X.509.
Центральным элементом для формирования цифровой подписи выступает класс
KJUR.crypto.Signature, который инкапсулирует процесс
хеширования сообщения и последующего подписания приватным ключом.
Объект подписи создаётся через конструктор, в который передаётся строка, определяющая алгоритм:
SHA256withRSASHA1withRSASHA512withRSASHA256withECDSAАлгоритм задаёт связку: хеш-функция + криптосистема подписи.
Например, SHA256withRSA означает сначала вычисление
SHA-256, затем применение RSA-подписи.
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
После создания объекта требуется инициализация ключом.
Jsrsasign использует объект KEYUTIL для загрузки и
преобразования ключей в формат, пригодный для подписи.
Приватный ключ может быть представлен в PEM-формате:
const privateKeyPem = `
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...
-----END PRIVATE KEY-----`;
Преобразование в объект ключа:
const privateKey = KEYUTIL.getKey(privateKeyPem);
После выбора алгоритма и загрузки ключа выполняется инициализация:
sig.init(privateKey);
На этом этапе объект подписи готов принимать данные.
Данные передаются в виде строки. Важно учитывать, что библиотека работает с байтовым представлением строки, поэтому кодировка UTF-8 играет ключевую роль.
sig.updateString("Hello world");
Метод updateString удобен для текстовых данных. Для
бинарных данных используется:
sig.updateHex("a1b2c3");
После передачи всех данных вызывается метод sign(),
который возвращает криптографическую подпись.
const signature = sig.sign();
Результат обычно возвращается в виде шестнадцатеричной строки (hex). Это значение является итоговым криптографическим маркером целостности и подлинности данных.
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
const privateKey = KEYUTIL.getKey(privateKeyPem);
sig.init(privateKey);
sig.updateString("Message for signing");
const signature = sig.sign();
console.log(signature);
Jsrsasign поддерживает несколько представлений результата:
Преобразование в Base64:
const b64 = hextob64(signature);
При работе с JSON важно сохранять детерминированность строки. Любое изменение порядка ключей изменяет подпись.
const payload = JSON.stringify({
user: "alice",
role: "admin"
});
sig.updateString(payload);
const signature = sig.sign();
RSA-подпись является наиболее распространённой в jsrsasign. Используется в сочетании с PKCS#1 v1.5 или PSS.
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });
ECDSA обеспечивает меньший размер подписи при сопоставимой криптографической стойкости.
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withECDSA" });
Особенность ECDSA заключается в зависимости от кривой (P-256, P-384 и т.д.), заданной в ключе.
Более современный режим RSA-подписи использует вероятностное дополнение PSS.
const sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSAandMGF1" });
Такой вариант повышает устойчивость к криптоаналитическим атакам за счёт случайного компонента.
Метод updateString можно вызывать многократно, формируя
подпись по частям:
sig.init(privateKey);
sig.updateString("part1");
sig.updateString("part2");
sig.updateString("part3");
const signature = sig.sign();
Финальный результат эквивалентен подписи конкатенации всех частей.
RSA-ключ нельзя использовать с ECDSA-алгоритмом и наоборот. Это приводит к исключениям при инициализации или генерации подписи.
Любое изменение строки после updateString делает подпись
недействительной.
Несоответствие UTF-8 приводит к различию байтового представления и, как следствие, к неверной подписи при проверке.
При работе с байтовыми массивами используется hex-представление:
sig.updateHex("deadbeef");
const signature = sig.sign();
Этот режим применяется при подписи файлов, хешей или уже подготовленных дайджестов.
В некоторых сценариях подписывается не исходное сообщение, а его хеш:
sig.init(privateKey);
sig.updateHex(sha256Digest);
const signature = sig.sign();
Такой подход используется в низкоуровневых протоколах и кастомных реализациях.
Метод sign() выполняет несколько этапов:
Подписи, созданные jsrsasign, часто используются в:
При интеграции важно учитывать формат кодирования (Base64URL vs Base64 vs Hex), так как несоответствие приводит к ошибкам верификации.
Типичные исключения возникают при:
Каждая из этих ситуаций прерывает выполнение sign() до
генерации результата.