Experimental sealing
This commit is contained in:
parent
9c85ac5a85
commit
333f743114
|
@ -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';
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||
|
||||
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<Ref>): Promise<Sealed> {
|
||||
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 }; }
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue