SHA256
Обновление архитектуры ключей и кошельков
This commit is contained in:
@@ -12,6 +12,15 @@ function normalizeLoginStorageKey(login) {
|
||||
return String(login || '').trim().toLowerCase();
|
||||
}
|
||||
|
||||
function sanitizePersistentSecrets(keys) {
|
||||
const source = keys && typeof keys === 'object' ? keys : {};
|
||||
const safe = { ...source };
|
||||
// Recovery/root private key is intentionally ephemeral: it may exist in RAM
|
||||
// during a protected operation, but must never be persisted on the device.
|
||||
delete safe.rootKey;
|
||||
return safe;
|
||||
}
|
||||
|
||||
function openDb() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
||||
@@ -53,7 +62,8 @@ async function get(storeName, key) {
|
||||
}
|
||||
|
||||
export async function saveEncryptedUserSecrets(login, storagePwd, keys) {
|
||||
const encrypted = await encryptJsonWithStoragePwd(keys, storagePwd);
|
||||
const safeKeys = sanitizePersistentSecrets(keys);
|
||||
const encrypted = await encryptJsonWithStoragePwd(safeKeys, storagePwd);
|
||||
const normalizedLogin = normalizeLoginStorageKey(login);
|
||||
await put(STORE_SECRETS, {
|
||||
login: normalizedLogin,
|
||||
@@ -71,7 +81,22 @@ export async function loadEncryptedUserSecrets(login, storagePwd) {
|
||||
if (!row?.encrypted) {
|
||||
throw new Error('На устройстве нет сохранённых ключей для этого логина');
|
||||
}
|
||||
return decryptJsonWithStoragePwd(row.encrypted, storagePwd);
|
||||
|
||||
const decrypted = await decryptJsonWithStoragePwd(row.encrypted, storagePwd);
|
||||
const safe = sanitizePersistentSecrets(decrypted);
|
||||
|
||||
// Одноразовая очистка контейнеров, созданных старыми версиями UI, где rootKey
|
||||
// мог быть сохранён. Перезаписываем тем же storagePwd уже без Recovery private key.
|
||||
if (decrypted && typeof decrypted === 'object' && Object.prototype.hasOwnProperty.call(decrypted, 'rootKey')) {
|
||||
const encrypted = await encryptJsonWithStoragePwd(safe, storagePwd);
|
||||
await put(STORE_SECRETS, {
|
||||
login: normalizedLogin,
|
||||
encrypted,
|
||||
updatedAtMs: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
return safe;
|
||||
}
|
||||
|
||||
export async function updateEncryptedUserSecrets(login, storagePwd, updater) {
|
||||
@@ -84,8 +109,9 @@ export async function updateEncryptedUserSecrets(login, storagePwd, updater) {
|
||||
if (!next || typeof next !== 'object') {
|
||||
throw new Error('updateEncryptedUserSecrets: updater должен вернуть объект secrets');
|
||||
}
|
||||
await saveEncryptedUserSecrets(login, storagePwd, next);
|
||||
return next;
|
||||
const safe = sanitizePersistentSecrets(next);
|
||||
await saveEncryptedUserSecrets(login, storagePwd, safe);
|
||||
return safe;
|
||||
}
|
||||
|
||||
export async function saveSessionMaterial(login, material) {
|
||||
|
||||
Reference in New Issue
Block a user