From 333f743114b2576ab5f252033f19e462729d4c3d Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 29 May 2024 11:50:23 +0200 Subject: [PATCH] Experimental sealing --- packages/core/src/index.ts | 1 + packages/ws-relay/package.json | 3 +- packages/ws-relay/src/index.ts | 5 ++- packages/ws-relay/src/seal.ts | 71 ++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 packages/ws-relay/src/seal.ts diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 2b0cadb..fc759e0 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -20,6 +20,7 @@ export * as Skeleton from './runtime/skeleton.js'; export * from './runtime/space.js'; export * from './runtime/supervise.js'; +export * as SaltyCrypto from 'salty-crypto'; export * as Cryptography from './transport/cryptography.js'; export * as WireProtocol from './transport/protocol.js'; export * as Relay from './transport/relay.js'; diff --git a/packages/ws-relay/package.json b/packages/ws-relay/package.json index feb7951..1f4a0f6 100644 --- a/packages/ws-relay/package.json +++ b/packages/ws-relay/package.json @@ -28,8 +28,7 @@ "@preserves/core": "^0.995.200" }, "dependencies": { - "@syndicate-lang/core": "^0.34.5", - "salty-crypto": "0.3" + "@syndicate-lang/core": "^0.34.5" }, "devDependencies": { "@syndicate-lang/ts-plugin": "^0.36.5", diff --git a/packages/ws-relay/src/index.ts b/packages/ws-relay/src/index.ts index cc3cb80..bd41123 100644 --- a/packages/ws-relay/src/index.ts +++ b/packages/ws-relay/src/index.ts @@ -24,14 +24,15 @@ import { stringify, underlying, Embeddable, + SaltyCrypto, } from "@syndicate-lang/core"; import G = Schemas.gatekeeper; import S = Schemas.sturdy; import N = Schemas.noise; import T = Schemas.transportAddress; import E = Schemas.stdenv; -import * as SaltyCrypto from 'salty-crypto'; -export * as SaltyCrypto from 'salty-crypto'; + +export * from './seal.js'; type TransportState = { addr: T.WebSocket, diff --git a/packages/ws-relay/src/seal.ts b/packages/ws-relay/src/seal.ts new file mode 100644 index 0000000..da17a9e --- /dev/null +++ b/packages/ws-relay/src/seal.ts @@ -0,0 +1,71 @@ +/// SPDX-License-Identifier: GPL-3.0-or-later +/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones + +import { Bytes, Value, encode, decode, isEmbedded, isSequence } from "@preserves/core"; +import { SaltyCrypto, Ref } from "@syndicate-lang/core"; + +const aead = SaltyCrypto.ChaCha20Poly1305_RFC8439; + +export type Sealed = [Bytes, number, number, number]; + +export function makeSeal() { + const key = new DataView(SaltyCrypto.randomBytes(aead.KEYBYTES).buffer); + const n = new SaltyCrypto.Nonce(); + return { + seal(v: Value): Promise { + return new Promise(k => { + at this.sealer { + send message [v, create ({ + message(reply) { k(reply as Sealed); } + })]; + } + }); + }, + + unseal(sealed: Sealed): Promise<{ ok: true, value: Value } | { ok: false }> { + return new Promise(k => { + at this.unsealer { + send message [sealed, create ({ + message(reply) { k(reply as any); } + })]; + } + }); + }, + + sealer: create ({ + message(req) { + if (isSequence(req) && req.length === 2 && isEmbedded(req[1])) { + try { + const [term, k] = req; + const m = encode(term); + const c = aead.encrypt(m._view, key, n); + at k { send message [Bytes.from(c), n.lo, n.hi, n.extra]; } + n.increment(); + } catch (_e) { console.error('Failed sealing: ' + _e); } + } + } + }), + + unsealer: create ({ + message(req) { + if ( + isSequence(req) && req.length === 2 && isEmbedded(req[1]) && + isSequence(req[0]) && req[0].length === 4 && + Bytes.isBytes(req[0][0]) && + typeof req[0][1] === 'number' && + typeof req[0][2] === 'number' && + typeof req[0][3] === 'number' + ) { + const [[c, lo, hi, extra], k] = req; + try { + const n = new SaltyCrypto.Nonce(lo, hi, extra); + const m = aead.decrypt(c._view, key, n); + at k { send message { ok: true, value: decode(Bytes.from(m)) }; } + } catch (e) { + at k { send message { ok: false }; } + } + } + }, + }), + }; +}