Криптографические ключи в схемах цифровой подписи представляют собой пару математически связанных значений: закрытый (private) и открытый (public) ключ. В контексте SJCL основное внимание уделяется эллиптическим кривым и реализации ECDSA, где безопасность основана на сложности задачи дискретного логарифмирования на эллиптических кривых.
В схемах на эллиптических кривых закрытый ключ представляет собой случайное число из диапазона порядка группы кривой. Открытый ключ получается как результат умножения базовой точки кривой на это число:
Q = d G
где:
d — закрытый ключG — базовая точка кривойQ — открытый ключБезопасность системы опирается на невозможность восстановления
d по известным Q и G.
В SJCL работа с ключами цифровой подписи реализована через модуль
sjcl.ecc и конкретно через механизмы ECDSA. Генерация
ключевой пары происходит на основе криптографически стойкого генератора
случайных чисел sjcl.random.
Пример создания ключевой пары:
const curve = sjcl.ecc.curves.c256;
const keys = sjcl.ecc.ecdsa.generateKeys(curve, 0);
В этом процессе:
c256 — secp256r1)Второй параметр generateKeys может задавать уровень
случайности или источник энтропии, но в большинстве случаев используется
значение 0, означающее стандартный поток энтропии
библиотеки.
Ключевой элемент безопасности — sjcl.random. Он
аккумулирует энтропию из различных источников среды выполнения (движения
мыши, системные события, таймеры).
Перед генерацией ключей важно убедиться, что пул энтропии достаточен:
sjcl.random.isReady();
Если энтропии недостаточно, генерация блокируется до её накопления. Это критически важно, так как слабый генератор случайных чисел полностью компрометирует ключевую пару.
После генерации возвращается объект, содержащий:
pub — открытый ключ в виде точки на кривойsec — закрытый ключ (скалярное значение)Пример структуры:
{
pub: sjcl.ecc.point,
sec: sjcl.bn,
_curve: sjcl.ecc.curves.c256
}
Закрытый ключ хранится в виде большого числа (bn),
реализованного в SJCL для операций с произвольной точностью.
Для хранения или передачи ключи часто преобразуются в сериализованный формат.
Открытый ключ обычно кодируется как точка:
const pubHex = keys.pub.toBits();
Закрытый ключ требует особой осторожности и обычно экспортируется только в защищённом виде:
const secHex = keys.sec.toString();
Любое хранение закрытого ключа в открытом виде считается нарушением модели безопасности.
После генерации ключей объект используется для создания цифровых подписей:
const message = sjcl.hash.sha256.hash("data");
const signature = keys.sign(message);
Проверка подписи выполняется с использованием открытого ключа:
const isValid = keys.pub.verify(message, signature);
Таким образом, закрытый ключ никогда не покидает сторону подписи, а открытый используется исключительно для верификации.
В браузере генерация ключей имеет дополнительные ограничения:
sjcl.randomТипичный паттерн ожидания:
sjcl.random.addEventListener('ready', function () {
const keys = sjcl.ecc.ecdsa.generateKeys(sjcl.ecc.curves.c256);
});
Без достаточной энтропии любые криптографические операции становятся предсказуемыми.
SJCL поддерживает несколько кривых, но наиболее распространённая —
c256. Она соответствует уровню безопасности примерно 128
бит.
2^{128}
что считается достаточным для большинства прикладных криптографических задач.
Более крупные кривые увеличивают безопасность, но снижают производительность операций подписи и проверки.
Типичные проблемы:
sjcl.randomКаждая из этих ошибок приводит к компрометации всей схемы цифровой подписи.
ECDSA в SJCL использует следующую схему:
k для каждой подписиR = kGr = (kG)_x
Если k повторяется или предсказуем, закрытый ключ может
быть восстановлен, что делает генерацию ключей и временных значений
критически важной частью всей системы.
SJCL не навязывает формат хранения, но типовой подход включает сериализацию:
Пример логики восстановления:
const restoredPub = sjcl.ecc.ecdsa.publicKey.fromBits(pubBits);
const restoredSec = sjcl.bn.fromBits(secBits);
При этом безопасность зависит не только от криптографии, но и от дисциплины хранения ключевых материалов.
Жизненный цикл ключа в SJCL-ориентированных системах обычно включает:
Каждый этап связан с рисками, но наиболее критичны первые два — именно они определяют качество всей криптографической системы.