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