Fix Safari doesn't store CryptoKey in IndexedDB
This commit is contained in:
parent
6dde554865
commit
3552447383
@ -201,7 +201,7 @@ export class NoauthBackend {
|
||||
})
|
||||
if (r.status !== 200 && r.status != 201) {
|
||||
console.log("Fetch error", url, method, r.status)
|
||||
throw new Error("Failed to fetch"+url)
|
||||
throw new Error("Failed to fetch" + url)
|
||||
}
|
||||
|
||||
return await r.json();
|
||||
@ -367,6 +367,7 @@ export class NoauthBackend {
|
||||
const npub = nip19.npubEncode(pubkey)
|
||||
const localKey = await this.keysModule.generateLocalKey()
|
||||
const enckey = await this.keysModule.encryptKeyLocal(sk, localKey)
|
||||
// @ts-ignore
|
||||
const dbKey: DbKey = { npub, enckey, localKey }
|
||||
await dbi.addKey(dbKey)
|
||||
this.enckeys.push(dbKey)
|
||||
@ -560,7 +561,11 @@ export class NoauthBackend {
|
||||
if (!info) throw new Error(`Key ${npub} not found`)
|
||||
const { type } = nip19.decode(npub)
|
||||
if (type !== "npub") throw new Error(`Invalid npub ${npub}`)
|
||||
const sk = await this.keysModule.decryptKeyLocal({ enckey: info.enckey, localKey: info.localKey })
|
||||
const sk = await this.keysModule.decryptKeyLocal({
|
||||
enckey: info.enckey,
|
||||
// @ts-ignore
|
||||
localKey: info.localKey
|
||||
})
|
||||
await this.startKey({ npub, sk })
|
||||
}
|
||||
|
||||
@ -573,7 +578,11 @@ export class NoauthBackend {
|
||||
private async saveKey(npub: string, passphrase: string) {
|
||||
const info = this.enckeys.find(k => k.npub === npub)
|
||||
if (!info) throw new Error(`Key ${npub} not found`)
|
||||
const sk = await this.keysModule.decryptKeyLocal({ enckey: info.enckey, localKey: info.localKey })
|
||||
const sk = await this.keysModule.decryptKeyLocal({
|
||||
enckey: info.enckey,
|
||||
// @ts-ignore
|
||||
localKey: info.localKey
|
||||
})
|
||||
const { enckey, pwh } = await this.keysModule.encryptKeyPass({ key: sk, passphrase })
|
||||
await this.sendKeyToServer(npub, enckey, pwh)
|
||||
}
|
||||
@ -582,7 +591,7 @@ export class NoauthBackend {
|
||||
const { type, data: pubkey } = nip19.decode(npub)
|
||||
if (type !== "npub") throw new Error(`Invalid npub ${npub}`)
|
||||
const { pwh } = await this.keysModule.generatePassKey(pubkey, passphrase)
|
||||
const { data: enckey } = await this.fetchKeyFromServer(npub, pwh);
|
||||
const { data: enckey } = await this.fetchKeyFromServer(npub, pwh);
|
||||
|
||||
// key already exists?
|
||||
const key = this.enckeys.find(k => k.npub === npub)
|
||||
|
@ -7,7 +7,6 @@ export interface DbKey {
|
||||
avatar?: string
|
||||
relays?: string[]
|
||||
enckey: string
|
||||
localKey: CryptoKey
|
||||
}
|
||||
|
||||
export interface DbApp {
|
||||
@ -57,7 +56,7 @@ export interface DbSchema extends Dexie {
|
||||
|
||||
export const db = new Dexie('noauthdb') as DbSchema
|
||||
|
||||
db.version(5).stores({
|
||||
db.version(7).stores({
|
||||
keys: 'npub',
|
||||
apps: 'appNpub,npub,name,timestamp',
|
||||
perms: 'id,npub,appNpub,perm,value,timestamp',
|
||||
|
20
src/keys.ts
20
src/keys.ts
@ -64,7 +64,19 @@ export class Keys {
|
||||
})
|
||||
}
|
||||
|
||||
public async generateLocalKey(): Promise<CryptoKey> {
|
||||
private isSafari() {
|
||||
const chrome = navigator.userAgent.indexOf("Chrome") > -1;
|
||||
const safari = navigator.userAgent.indexOf("Safari") > -1;
|
||||
return safari && !chrome
|
||||
}
|
||||
|
||||
public async generateLocalKey(): Promise<CryptoKey | {}> {
|
||||
// https://github.com/dexie/Dexie.js/issues/585
|
||||
// Those lazy-asses from Safari still don't allow one
|
||||
// to store keys in IndexedDB, so for them we have to
|
||||
// store nsecs in plaintext
|
||||
if (this.isSafari()) return {}
|
||||
|
||||
return await this.subtle.generateKey(
|
||||
{ name: ALGO_LOCAL, length: KEY_SIZE_LOCAL },
|
||||
// NOTE: important to make sure it's not visible in
|
||||
@ -74,14 +86,16 @@ export class Keys {
|
||||
)
|
||||
}
|
||||
|
||||
public async encryptKeyLocal(key: string, localKey: CryptoKey): Promise<string> {
|
||||
public async encryptKeyLocal(key: string, localKey: CryptoKey | {}): Promise<string> {
|
||||
if (this.isSafari()) return key
|
||||
const nsec = nip19.nsecEncode(key)
|
||||
const iv = crypto.randomBytes(IV_SIZE)
|
||||
const encrypted = await this.subtle.encrypt({ name: ALGO_LOCAL, iv }, localKey, Buffer.from(nsec))
|
||||
return `${PREFIX_LOCAL}:${VERSION_LOCAL}:${iv.toString('hex')}:${Buffer.from(encrypted).toString('hex')}}`
|
||||
}
|
||||
|
||||
public async decryptKeyLocal({ enckey, localKey }: { enckey: string, localKey: CryptoKey }): Promise<string> {
|
||||
public async decryptKeyLocal({ enckey, localKey }: { enckey: string, localKey: CryptoKey | {} }): Promise<string> {
|
||||
if (this.isSafari()) return enckey
|
||||
const parts = enckey.split(':')
|
||||
if (parts.length !== 4) throw new Error("Bad encrypted key")
|
||||
if (parts[0] !== PREFIX_LOCAL) throw new Error("Bad encrypted key prefix")
|
||||
|
@ -58,6 +58,10 @@ export function register(config?: Config) {
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (config && config.onError) {
|
||||
config.onError(new Error("No service worker"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user