encboot.mx raw
1 package main
2
3 import (
4 "git.smesh.lol/nostr/pkg/crypto/hkdf"
5 "git.smesh.lol/musiquay/web/common/helpers"
6 "git.smesh.lol/musiquay/web/common/jsbridge/dom"
7 "git.smesh.lol/musiquay/web/common/jsbridge/localstorage"
8 "git.smesh.lol/musiquay/web/common/jsbridge/signer"
9 "git.smesh.lol/musiquay/web/common/jsbridge/subtle"
10 )
11
12 const lsEncKeyPrefix = "musiquay-enc-epk-"
13
14
15 // bootstrapEncKey derives the IDB encryption key and calls done when ready.
16 // First run: generates ephemeral keypair, ECDH via signer, stores ephemeral pubkey.
17 // Reload: reads stored ephemeral pubkey, ECDH via signer.
18 func bootstrapEncKey(done func()) {
19 lsKey := lsEncKeyPrefix | appSt.pubhex
20 epkHex := localstorage.GetItem(lsKey)
21 if epkHex == "" {
22 // First run: generate ephemeral secret, derive pubkey via signer.
23 var sec [32]byte
24 subtle.RandomBytes(sec[:])
25 secHex := helpers.HexEncode(sec[:])
26 for i := range sec {
27 sec[i] = 0
28 }
29 signer.PubkeyFromSecret(secHex, func(pkHex string) {
30 if pkHex == "" {
31 dom.ConsoleLog("enc: PubkeyFromSecret failed")
32 done()
33 return
34 }
35 localstorage.SetItem(lsKey, pkHex)
36 // ECDH(user_seckey, ephemeral_pubkey) via signer's active identity.
37 signer.GetSharedSecret(pkHex, func(sharedHex string) {
38 if sharedHex == "" {
39 dom.ConsoleLog("enc: getSharedSecret failed")
40 done()
41 return
42 }
43 deriveAndSetEncKey(sharedHex, done)
44 })
45 })
46 return
47 }
48 // Reload: ask signer for ECDH(user_seckey, ephemeral_pubkey).
49 signer.GetSharedSecret(epkHex, func(sharedHex string) {
50 if sharedHex == "" {
51 dom.ConsoleLog("enc: getSharedSecret failed")
52 done()
53 return
54 }
55 deriveAndSetEncKey(sharedHex, done)
56 })
57 }
58
59 func deriveAndSetEncKey(sharedHex string, done func()) {
60 shared := helpers.HexDecode(sharedHex)
61 prk := hkdf.Extract(nil, shared)
62 symKey := hkdf.Expand(prk[:], []byte("musiquay-idb-enc"), 32)
63 appSt.encKeyHex = helpers.HexEncode(symKey)
64 dom.IDBSetEncKey(appSt.encKeyHex)
65 dom.ConsoleLog("enc: IDB encryption key set")
66 done()
67 }
68
69 // sendEncKeyToSW sends the encryption key to the service worker.
70 func sendEncKeyToSW() {
71 if appSt.encKeyHex != "" {
72 dom.PostToSW("[\"ENC_KEY\"," | jstr(appSt.encKeyHex) | "]")
73 }
74 }
75