В SJCL обработка ошибок построена вокруг собственного набора
исключений, расширяющих стандартный механизм Error в
JavaScript. Библиотека стремится не возвращать “тихие” некорректные
результаты при криптографических операциях, поэтому большинство
критических ситуаций приводит к генерации исключений с фиксированными
типами и сообщениями.
В основе лежит базовый класс sjcl.exception, от которого
наследуются специализированные ошибки. Такая структура позволяет не
только перехватывать все ошибки библиотеки единым блоком, но и различать
их по типу.
Основные категории:
sjcl.exception.invalid — некорректные входные
параметрыsjcl.exception.corrupt — повреждённые или неверно
сформированные данныеsjcl.exception.notReady — использование алгоритма до
его инициализацииsjcl.exception.bug — внутренняя ошибка библиотеки,
указывающая на невозможное состояниеКаждый тип наследуется от общего исключения SJCL, что позволяет строить как точечную, так и глобальную обработку.
Большинство функций SJCL не возвращают коды ошибок в стиле C или Node.js callback-стиль. Вместо этого используется выбрасывание исключений:
sjcl.exception.invalid = function(message) {
this.toString = function() {
return "sjcl.exception.invalid: " + message;
};
this.message = message;
};
sjcl.exception.invalid.prototype = new Error();
Подобная модель делает ошибки неизбежно явными: выполнение прерывается сразу при нарушении условий криптографической корректности.
Хотя SJCL не использует числовые error codes в классическом смысле, логика классификации ошибок фактически выполняет ту же роль.
Возникают при нарушении контрактов функций:
Типичный пример:
if (!key || key.length === 0) {
throw new sjcl.exception.invalid("key cannot be empty");
}
Такие ошибки указывают на неправильное использование API.
Используются при декодировании или расшифровке:
Пример:
if (!this._isValidMac(data)) {
throw new sjcl.exception.corrupt("message authentication failed");
}
Эта категория особенно важна для криптографической целостности: данные считаются недоверенными и не должны интерпретироваться.
Возникают при попытке использовать алгоритм до завершения подготовки:
Пример:
if (!this._keySchedule) {
throw new sjcl.exception.notReady("key schedule not initialized");
}
Такие ошибки характерны для потоковых режимов и классов с ленивой инициализацией.
Используются как сигнал о невозможном состоянии:
Пример:
throw new sjcl.exception.bug("unexpected state in bitArray processing");
Появление таких ошибок рассматривается как дефект реализации, а не неправильное использование API.
SJCL не скрывает ошибки, поэтому стандартный подход строится на
try/catch:
try {
var decrypted = sjcl.decrypt(password, ciphertext);
} catch (e) {
if (e instanceof sjcl.exception.corrupt) {
// данные повреждены или ключ неверный
} else if (e instanceof sjcl.exception.invalid) {
// ошибка параметров
} else {
// непредвиденное состояние
}
}
Разделение типов позволяет точно определять природу сбоя без анализа строк сообщений.
В сложных системах SJCL-исключения часто оборачиваются в доменные ошибки приложения:
try {
sjcl.encrypt(key, data);
} catch (e) {
throw new Error("Encryption pipeline failed: " + e.toString());
}
При этом важно сохранять оригинальный объект ошибки, поскольку именно он содержит точный тип сбоя.
Внутренний тип sjcl.bitArray является частым источником
исключений:
В таких случаях обычно выбрасывается
sjcl.exception.invalid или sjcl.exception.bug,
в зависимости от контекста.
Пример:
if (a.length % 32 !== 0) {
throw new sjcl.exception.invalid("bitArray length must be multiple of 32");
}
SJCL поддерживает различные кодеки (Base64, Hex, JSON). Ошибки здесь возникают при:
throw new sjcl.exception.corrupt("invalid base64 encoding");
Такие ошибки особенно важны при восстановлении ключей и ciphertext из хранилищ.
В криптографических системах важно не различать слишком подробно
некоторые ошибки на уровне логики приложения. Например,
corrupt может означать как повреждение данных, так и
неверный пароль, и разделение этих случаев может привести к утечке
информации о системе.
Поэтому часто применяется унификация:
try {
sjcl.decrypt(key, data);
} catch (e) {
throw new Error("Decryption failed");
}
Если исключения SJCL не перехватываются, они полностью прерывают выполнение скрипта. В браузерных средах это приводит к остановке текущего потока выполнения, в Node.js — к аварийному завершению процесса при отсутствии глобального обработчика.
Глобальная обработка:
process.on("uncaughtException", function(e) {
console.error("Unhandled SJCL error:", e);
});
Модель исключений библиотеки ориентирована на несколько принципов:
Такая структура делает поведение алгоритмов предсказуемым и облегчает аудит безопасности, поскольку каждая ошибка имеет явную причину и класс.