概述加密存储可保护本地数据安全。本文展示密钥导入派生、加解密封装与轮换迁移流程。能力检测与密钥管理const supportsWebCrypto = !!(crypto && crypto.subtle); async function deriveKey(passphrase, salt) { const enc = new TextEncoder(); const base = await crypto.subtle.importKey('raw', enc.encode(passphrase), 'PBKDF2', false, ['deriveKey']); return crypto.subtle.deriveKey({ name: 'PBKDF2', hash: 'SHA-256', salt: enc.encode(salt), iterations: 100000 }, base, { name: 'AES-GCM', length: 256 }, true, ['encrypt','decrypt']); } async function exportRaw(key) { const raw = await crypto.subtle.exportKey('raw', key); return new Uint8Array(raw); } async function importRaw(raw) { return crypto.subtle.importKey('raw', raw, { name: 'AES-GCM' }, true, ['encrypt','decrypt']); } 加解密与存储function openDB(name) { return new Promise((resolve, reject) => { const r = indexedDB.open(name, 1); r.onupgradeneeded = () => { const db = r.result; if (!db.objectStoreNames.contains('items')) db.createObjectStore('items', { keyPath: 'id' }); if (!db.objectStoreNames.contains('keys')) db.createObjectStore('keys', { keyPath: 'version' }); }; r.onsuccess = () => resolve(r.result); r.onerror = () => reject(r.error); }); } async function encrypt(key, obj) { const iv = crypto.getRandomValues(new Uint8Array(12)); const data = new TextEncoder().encode(JSON.stringify(obj)); const buf = await crypto.subtle.encrypt({ name:'AES-GCM', iv }, key, data); return { iv, cipher: new Uint8Array(buf) }; } async function decrypt(key, payload) { const buf = await crypto.subtle.decrypt({ name:'AES-GCM', iv: payload.iv }, key, payload.cipher); return JSON.parse(new TextDecoder().decode(new Uint8Array(buf))); } async function putEncrypted(record, keyVersion, key) { const db = await openDB('secdb'); const tx = db.transaction('items','readwrite'); const payload = await encrypt(key, record); tx.objectStore('items').put({ id: record.id, v: keyVersion, payload }); await new Promise((res, rej) => { tx.oncomplete = res; tx.onerror = () => rej(tx.error); }); db.close(); } async function getDecrypted(id, versions) { const db = await openDB('secdb'); const tx = db.transaction('items','readonly'); const req = tx.objectStore('items').get(id); const rec = await new Promise((res, rej) => { req.onsuccess = () => res(req.result); req.onerror = () => rej(req.error); }); db.close(); if (!rec) return null; const key = versions[rec.v]; return decrypt(key, rec.payload); } 密钥轮换与迁移async function rotateKey(newVersion, newKey, loadKeyByVersion) { const db = await openDB('secdb'); const tx = db.transaction('items','readwrite'); const store = tx.objectStore('items'); const req = store.openCursor(); await new Promise((resolve, reject) => { req.onsuccess = async e => { const c = e.target.result; if (c) { const oldKey = await loadKeyByVersion(c.value.v); const obj = await decrypt(oldKey, c.value.payload); const payload = await encrypt(newKey, obj); c.update({ id: c.value.id, v: newVersion, payload }); c.continue(); } else { resolve(); } }; req.onerror = () => reject(req.error); }); await new Promise((res, rej) => { tx.oncomplete = res; tx.onerror = () => rej(tx.error); }); db.close(); }

发表评论 取消回复