1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
"""
Nothing in the interface reads an identity private key except the identity.
The transport sees an identity on a node as two public keys, a signature and an
X25519 agreement (`transport.js`, `_identityFromKeys`). In a browser that object
wraps keys held in the page; in the desktop application the keys stay in the
main process and the same object asks it to sign. That only holds if no other
code reaches past the object for a key — which is what every admin op, device
link, chat message and app used to do, twenty times over, and is what this
test refuses.
"""
import re
from spa_source import STATIC
# Where a private key may be named: minted and sealed (keyderive.js), wrapped
# into an identity (transport.js), re-sealed during a passphrase change in a
# browser (transport-rewrap.js).
ALLOWED = {"keyderive.js", "transport.js", "transport-rewrap.js"}
def test_only_the_identity_touches_a_private_key():
offenders = []
for path in STATIC.glob("*.js"):
if path.name in ALLOWED:
continue
text = path.read_text(encoding="utf-8")
if re.search(r"skEdB64|skXB64|sessionKeys|signBytes\(", text):
offenders.append(path.name)
assert not offenders, f"these read a private key directly: {offenders}"
def test_in_the_transport_only_the_identity_factory_signs_with_a_raw_key():
text = (STATIC / "transport.js").read_text(encoding="utf-8")
factory = text[text.index("async function _identityFromKeys"):]
factory = factory[:factory.index("\n}\n")]
rest = text.replace(factory, "")
assert "signBytes(" in factory
assert "signBytes(" not in rest, "the transport signs with a raw key outside the identity"
assert "skXB64" not in rest.replace("id.skXB64", ""), \
"the transport reads the X25519 private key outside the identity"
def test_a_group_key_is_unwrapped_through_the_identity():
crypto = (STATIC / "crypto.js").read_text(encoding="utf-8")
unwrap = crypto[crypto.index("async function unwrapGEK"):]
unwrap = unwrap[:unwrap.index("\n}\n")]
assert "shared(pkEphRaw)" in unwrap and "pkcs8" not in unwrap
|