aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests/test_desktop_keyring.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests/test_desktop_keyring.py')
-rw-r--r--packages/meshbay-hub/tests/test_desktop_keyring.py34
1 files changed, 33 insertions, 1 deletions
diff --git a/packages/meshbay-hub/tests/test_desktop_keyring.py b/packages/meshbay-hub/tests/test_desktop_keyring.py
index 963ee55..e55e6d0 100644
--- a/packages/meshbay-hub/tests/test_desktop_keyring.py
+++ b/packages/meshbay-hub/tests/test_desktop_keyring.py
@@ -119,10 +119,33 @@ const v = JSON.parse(fs.readFileSync(input, 'utf8'));
await K.nodeBundleKey(sk, 'NODE-P'), { userId: v.userId, nodePk: 'NODE-P' });
out.sealed_here_opens_in_page = back.skX === pageId.skXB64;
+ // 3b. TRANSITIONAL: an MBK2 bundle, sealed under the Argon2 key alone as
+ // 0.16 wrote it, is opened with the legacy key kept beside M.
+ {
+ const nc = require('crypto');
+ const salt = nc.createHash('sha256').update(`meshbay:bundle:v2:${v.user}`).digest().subarray(0, 16);
+ const a = await argon2(v.password, salt,
+ { memory: 131072, passes: 3, parallelism: 1, tagLength: 32 });
+ const ed = nc.generateKeyPairSync('ed25519').privateKey.export({ format: 'der', type: 'pkcs8' });
+ const x = nc.generateKeyPairSync('x25519').privateKey.export({ format: 'der', type: 'pkcs8' });
+ const nonce = nc.randomBytes(12);
+ const c = nc.createCipheriv('aes-256-gcm', Buffer.from(a), nonce);
+ const body = Buffer.concat([c.update(JSON.stringify({ skEd: ed.toString('base64'),
+ skX: x.toString('base64') })), c.final()]);
+ const mbk2 = Buffer.concat([Buffer.from('MBK2'), nonce, body, c.getAuthTag()]).toString('base64');
+ out.legacy_open = ring.openBundle(v.userId, 'NODE-L', { bundleEnc: mbk2 });
+ out.legacy_kept = ring.identity(v.userId, 'NODE-L');
+ const keptLegacy = store.masters[v.userId].legacy;
+ delete store.masters[v.userId].legacy;
+ try { ring.openBundle(v.userId, 'NODE-M', { bundleEnc: mbk2 }); out.legacy_missing = 'opened'; }
+ catch (e) { out.legacy_missing = e.message; }
+ store.masters[v.userId].legacy = keptLegacy;
+ }
+
// 4. nothing but public keys come out of the keyring's answers.
out.identity_answer = ring.identity(v.userId, v.node);
out.retired = (() => { try { ring.openBundle(v.userId, 'NODE-R',
- { bundleEnc: Buffer.from('MBK2' + 'x'.repeat(40)).toString('base64') }); }
+ { bundleEnc: Buffer.from('y'.repeat(44)).toString('base64') }); }
catch (e) { return e.code; } })();
out.access_default = ring.browserAccess('someone-else');
ring.setBrowserAccess(v.userId, false);
@@ -284,3 +307,12 @@ def test_the_application_never_asks_its_own_crypto_for_argon2():
source = (KEYRING.parent / name).read_text(encoding="utf-8")
assert "crypto.argon2" not in source, name
assert "wasmArgon2(" in (KEYRING.parent / "main.js").read_text(encoding="utf-8")
+
+
+def test_an_mbk2_bundle_is_opened_with_the_kept_legacy_key(out):
+ """TRANSITIONAL. Kept unsealed, so the next settle replaces the node's copy
+ with MBK3 or withdraws it; without the legacy key the passphrase is asked
+ for, rather than the identity being given up."""
+ assert set(out["legacy_open"]) == {"pkEdB64", "pkXB64"}
+ assert out["legacy_kept"]["sealedWith"] is None
+ assert out["legacy_missing"] == "no_legacy_key"