Idb-keyval — это легковесная обертка для работы с IndexedDB в браузере, обеспечивающая простое API для хранения ключ-значение. Одним из важных аспектов работы с данными является безопасность, особенно когда необходимо хранить конфиденциальную информацию. В этом контексте шифрование значений перед сохранением становится критически важным.
Для шифрования данных можно использовать встроенный в браузеры Web Crypto API. Он предоставляет безопасные методы для генерации ключей, шифрования и расшифровки данных. Основные операции:
crypto.subtle.generateKey()crypto.subtle.encrypt()crypto.subtle.decrypt()crypto.subtle.importKey(),
crypto.subtle.exportKey()Пример генерации симметричного ключа AES-GCM:
const key = await crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true,
["encrypt", "decrypt"]
);
Idb-keyval предоставляет методы set, get,
del, update для работы с хранилищем. Для
безопасного хранения данных необходимо предварительно зашифровать их, а
затем сохранить.
import { set, get } from 'idb-keyval';
async function encryptAndStore(keyName, value, cryptoKey) {
const encoder = new TextEncoder();
const encodedValue = encoder.encode(JSON.stringify(value));
const iv = crypto.getRandomValues(new Uint8Array(12));
const encryptedValue = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
cryptoKey,
encodedValue
);
// Сохраняем объект с IV и зашифрованными данными
await set(keyName, { iv: Array.from(iv), data: Array.from(new Uint8Array(encryptedValue)) });
}
В этом примере:
{ iv, data }, чтобы
их можно было корректно расшифровать.Для восстановления исходного значения из хранилища выполняется обратный процесс:
async function decryptFromStore(keyName, cryptoKey) {
const stored = await get(keyName);
if (!stored) return null;
const { iv, data } = stored;
const decryptedValue = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: new Uint8Array(iv) },
cryptoKey,
new Uint8Array(data)
);
const decoder = new TextDecoder();
return JSON.parse(decoder.decode(decryptedValue));
}
Ключевые моменты:
Хранение ключей — критический момент безопасности. Основные подходы:
crypto.subtle.wrapKey и
сохранение зашифрованного ключа).const passwordKey = await crypto.subtle.importKey(
"raw",
new TextEncoder().encode(userPassword),
{ name: "PBKDF2" },
false,
["deriveKey"]
);
const derivedKey = await crypto.subtle.deriveKey(
{
name: "PBKDF2",
salt: crypto.getRandomValues(new Uint8Array(16)),
iterations: 100000,
hash: "SHA-256"
},
passwordKey,
{ name: "AES-GCM", length: 256 },
false,
["encrypt", "decrypt"]
);
Этот метод обеспечивает, что ключ для шифрования формируется динамически и зависит от пользовательского пароля, что повышает безопасность.
JSON.stringify обеспечивает совместимость
типов данных.Шифрование значений перед сохранением в Idb-keyval позволяет безопасно хранить конфиденциальные данные в браузере, объединяя простоту API библиотеки и современные возможности Web Crypto API.