Жизненный цикл ключа в Web Crypto API начинается с его создания. Для
этого используется метод crypto.subtle.generateKey(),
который позволяет генерировать как симметричные, так и асимметричные
ключи.
Симметричные ключи применяются в алгоритмах шифрования (например, AES), а асимметричные — в алгоритмах подписи и обмена ключами (RSA, ECDSA, ECDH).
Пример генерации симметричного ключа:
const key = await crypto.subtle.generateKey(
{
name: "AES-GCM",
length: 256
},
true,
["encrypt", "decrypt"]
);
Ключевые параметры:
name — алгоритмlength — длина ключа (в битах)extractable — возможность экспорта ключаkeyUsages — допустимые операцииПример генерации асимметричной пары ключей:
const keyPair = await crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
["encrypt", "decrypt"]
);
Результат — объект с publicKey и
privateKey.
Ключи в Web Crypto API представлены объектами типа
CryptoKey. Они не являются обычными JavaScript-объектами и
не могут быть напрямую сериализованы.
Свойства CryptoKey:
type: "secret", "public",
"private"extractable: можно ли экспортироватьalgorithm: параметры алгоритмаusages: список разрешённых операцийВажно: ключи хранятся в защищённой форме и не доступны для прямого чтения.
Экспорт используется для сохранения или передачи ключа. Доступен
только если extractable: true.
Метод: crypto.subtle.exportKey()
Форматы:
"raw" — для симметричных ключей"pkcs8" — для приватных ключей"spki" — для публичных ключей"jwk" — JSON Web KeyПример:
const exported = await crypto.subtle.exportKey("jwk", key);
JWK-формат удобен для передачи через JSON:
{
"kty": "oct",
"k": "base64url-encoded-key",
"alg": "A256GCM",
"ext": true
}
Импорт выполняется через crypto.subtle.importKey(). Это
позволяет восстановить ключ из внешнего представления.
Пример импорта JWK:
const key = await crypto.subtle.importKey(
"jwk",
jwkObject,
{
name: "AES-GCM"
},
true,
["encrypt", "decrypt"]
);
Важно соблюдать соответствие:
Ключи применяются в операциях шифрования, дешифрования, подписи и верификации.
Пример шифрования:
const encrypted = await crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: crypto.getRandomValues(new Uint8Array(12))
},
key,
data
);
Пример подписи:
const signature = await crypto.subtle.sign(
{
name: "RSASSA-PKCS1-v1_5"
},
privateKey,
data
);
Ограничения:
usagesWeb Crypto API не предоставляет встроенного постоянного хранилища. Для этого используются внешние механизмы:
IndexedDB — основной способ хранения:
const dbRequest = indexedDB.open("crypto-store", 1);
Перед сохранением ключ необходимо экспортировать (если он extractable).
Альтернатива:
Ключи с extractable: false невозможно сохранить напрямую
— это повышает безопасность.
При создании или импорте задаётся список keyUsages,
который строго ограничивает операции:
Примеры:
"encrypt", "decrypt""sign", "verify""deriveKey", "deriveBits"Попытка использовать ключ вне этих разрешений приведёт к ошибке.
Это важный элемент модели безопасности:
В Web Crypto API отсутствует явный метод удаления ключа. Жизненный цикл завершается через:
Пример удаления из IndexedDB:
const transaction = db.transaction("keys", "readwrite");
transaction.objectStore("keys").delete(keyId);
Для повышения безопасности:
extractable: falseПрактика регулярной смены ключей (key rotation) критична для безопасности.
Подход:
Пример сценария:
Это позволяет избежать потери доступа к данным.
Иногда ключ не хранится напрямую, а выводится из пароля или другого секрета.
Используется deriveKey:
const derivedKey = await crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: salt,
iterations: 100000,
hash: "SHA-256"
},
baseKey,
{
name: "AES-GCM",
length: 256
},
false,
["encrypt", "decrypt"]
);
Преимущества:
Ключевые принципы:
Минимизация доступности
extractable: falsekeyUsagesИзоляция
Контроль хранения
Ротация и удаление
Типичный жизненный цикл ключа:
Каждый этап влияет на безопасность всей системы. Ошибки на любом уровне могут привести к компрометации данных.