@dxos/keyring 0.9.1-staging.ee54ba693a → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/index.mjs +291 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/types/src/keyring.d.ts +7 -0
- package/dist/types/src/keyring.d.ts.map +1 -1
- package/dist/types/src/sqlite-keyring.d.ts +6 -1
- package/dist/types/src/sqlite-keyring.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -14
- package/src/keyring.ts +7 -0
- package/src/sqlite-keyring.ts +14 -1
- package/dist/lib/neutral/index.mjs +0 -288
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import * as EffectContext from "effect/Context";
|
|
2
|
+
import { Event, synchronized } from "@dxos/async";
|
|
3
|
+
import { subtleCrypto } from "@dxos/crypto";
|
|
4
|
+
import { todo } from "@dxos/debug";
|
|
5
|
+
import { invariant } from "@dxos/invariant";
|
|
6
|
+
import { PublicKey } from "@dxos/keys";
|
|
7
|
+
import { schema } from "@dxos/protocols/proto";
|
|
8
|
+
import { StorageType, createStorage } from "@dxos/random-access-storage";
|
|
9
|
+
import { ComplexMap, arrayToBuffer } from "@dxos/util";
|
|
10
|
+
import * as SqlClient from "@effect/sql/SqlClient";
|
|
11
|
+
import * as Effect from "effect/Effect";
|
|
12
|
+
import * as Layer from "effect/Layer";
|
|
13
|
+
import { RuntimeProvider } from "@dxos/effect";
|
|
14
|
+
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorate.js
|
|
15
|
+
function __decorate(decorators, target, key, desc) {
|
|
16
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
17
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
18
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
19
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/keyring.ts
|
|
23
|
+
var __dxlog_file$1 = "/__w/dxos/dxos/packages/core/halo/keyring/src/keyring.ts";
|
|
24
|
+
var KeyRecord = schema.getCodecForType("dxos.halo.keyring.KeyRecord");
|
|
25
|
+
/**
|
|
26
|
+
* Effect service tag for {@link KeyringApi}.
|
|
27
|
+
*/
|
|
28
|
+
var KeyringApiService = class extends EffectContext.Tag("@dxos/keyring/KeyringApi")() {};
|
|
29
|
+
/**
|
|
30
|
+
* Manages keys.
|
|
31
|
+
*/
|
|
32
|
+
var Keyring = class {
|
|
33
|
+
_storage;
|
|
34
|
+
_keyCache = new ComplexMap(PublicKey.hash);
|
|
35
|
+
keysUpdate = new Event();
|
|
36
|
+
constructor(_storage = createStorage({ type: StorageType.RAM }).createDirectory("keyring")) {
|
|
37
|
+
this._storage = _storage;
|
|
38
|
+
invariant(subtleCrypto, "SubtleCrypto not available in this environment.", {
|
|
39
|
+
"~LogMeta": "~LogMeta",
|
|
40
|
+
F: __dxlog_file$1,
|
|
41
|
+
L: 47,
|
|
42
|
+
S: this,
|
|
43
|
+
A: ["subtleCrypto", "'SubtleCrypto not available in this environment.'"]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async sign(key, message) {
|
|
47
|
+
const keyPair = await this._getKey(key);
|
|
48
|
+
return new Uint8Array(await subtleCrypto.sign({
|
|
49
|
+
name: "ECDSA",
|
|
50
|
+
hash: "SHA-256"
|
|
51
|
+
}, keyPair.privateKey, message));
|
|
52
|
+
}
|
|
53
|
+
async createKey() {
|
|
54
|
+
const keyPair = await subtleCrypto.generateKey({
|
|
55
|
+
name: "ECDSA",
|
|
56
|
+
namedCurve: "P-256"
|
|
57
|
+
}, true, ["sign", "verify"]);
|
|
58
|
+
await this._setKey(keyPair);
|
|
59
|
+
return keyPairToPublicKey$1(keyPair);
|
|
60
|
+
}
|
|
61
|
+
async _getKey(key) {
|
|
62
|
+
if (!this._keyCache.has(key)) {
|
|
63
|
+
const file = this._storage.getOrCreateFile(key.toHex());
|
|
64
|
+
const { size } = await file.stat();
|
|
65
|
+
if (size === 0) throw new Error(`Key not found: ${key.toHex()}`);
|
|
66
|
+
const recordBytes = await file.read(0, size);
|
|
67
|
+
await file.close();
|
|
68
|
+
const record = KeyRecord.decode(recordBytes);
|
|
69
|
+
const publicKey = PublicKey.from(record.publicKey);
|
|
70
|
+
invariant(key.equals(publicKey), "Corrupted keyring: Key mismatch", {
|
|
71
|
+
"~LogMeta": "~LogMeta",
|
|
72
|
+
F: __dxlog_file$1,
|
|
73
|
+
L: 94,
|
|
74
|
+
S: this,
|
|
75
|
+
A: ["key.equals(publicKey)", "'Corrupted keyring: Key mismatch'"]
|
|
76
|
+
});
|
|
77
|
+
invariant(record.privateKey, "Corrupted keyring: Missing private key", {
|
|
78
|
+
"~LogMeta": "~LogMeta",
|
|
79
|
+
F: __dxlog_file$1,
|
|
80
|
+
L: 95,
|
|
81
|
+
S: this,
|
|
82
|
+
A: ["record.privateKey", "'Corrupted keyring: Missing private key'"]
|
|
83
|
+
});
|
|
84
|
+
const keyPair = {
|
|
85
|
+
publicKey: await subtleCrypto.importKey("raw", record.publicKey, {
|
|
86
|
+
name: "ECDSA",
|
|
87
|
+
namedCurve: "P-256"
|
|
88
|
+
}, true, ["verify"]),
|
|
89
|
+
privateKey: await subtleCrypto.importKey("pkcs8", record.privateKey, {
|
|
90
|
+
name: "ECDSA",
|
|
91
|
+
namedCurve: "P-256"
|
|
92
|
+
}, true, ["sign"])
|
|
93
|
+
};
|
|
94
|
+
this._keyCache.set(publicKey, keyPair);
|
|
95
|
+
}
|
|
96
|
+
return this._keyCache.get(key);
|
|
97
|
+
}
|
|
98
|
+
async _setKey(keyPair) {
|
|
99
|
+
const publicKey = await keyPairToPublicKey$1(keyPair);
|
|
100
|
+
this._keyCache.set(publicKey, keyPair);
|
|
101
|
+
const record = {
|
|
102
|
+
publicKey: publicKey.asUint8Array(),
|
|
103
|
+
privateKey: new Uint8Array(await subtleCrypto.exportKey("pkcs8", keyPair.privateKey))
|
|
104
|
+
};
|
|
105
|
+
const file = this._storage.getOrCreateFile(publicKey.toHex());
|
|
106
|
+
await file.write(0, arrayToBuffer(KeyRecord.encode(record)));
|
|
107
|
+
await file.close();
|
|
108
|
+
await file.flush?.();
|
|
109
|
+
this.keysUpdate.emit();
|
|
110
|
+
}
|
|
111
|
+
deleteKey(key) {
|
|
112
|
+
return todo("We need a method to delete a file.");
|
|
113
|
+
}
|
|
114
|
+
async list() {
|
|
115
|
+
const keys = [];
|
|
116
|
+
for (const path of await this._storage.list()) {
|
|
117
|
+
const fileName = path.split("/").pop();
|
|
118
|
+
invariant(fileName, "Invalid file name", {
|
|
119
|
+
"~LogMeta": "~LogMeta",
|
|
120
|
+
F: __dxlog_file$1,
|
|
121
|
+
L: 151,
|
|
122
|
+
S: this,
|
|
123
|
+
A: ["fileName", "'Invalid file name'"]
|
|
124
|
+
});
|
|
125
|
+
keys.push({ publicKey: PublicKey.fromHex(fileName).asUint8Array() });
|
|
126
|
+
}
|
|
127
|
+
return keys;
|
|
128
|
+
}
|
|
129
|
+
async importKeyPair(keyPair) {
|
|
130
|
+
await this._setKey(keyPair);
|
|
131
|
+
return keyPairToPublicKey$1(keyPair);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
__decorate([synchronized], Keyring.prototype, "_getKey", null);
|
|
135
|
+
__decorate([synchronized], Keyring.prototype, "_setKey", null);
|
|
136
|
+
var keyPairToPublicKey$1 = async (keyPair) => {
|
|
137
|
+
return PublicKey.from(new Uint8Array(await subtleCrypto.exportKey("raw", keyPair.publicKey)));
|
|
138
|
+
};
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region src/sqlite-keyring.ts
|
|
141
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/core/halo/keyring/src/sqlite-keyring.ts";
|
|
142
|
+
var KeyRecordCodec = schema.getCodecForType("dxos.halo.keyring.KeyRecord");
|
|
143
|
+
/**
|
|
144
|
+
* SQLite-backed Keyring.
|
|
145
|
+
* Stores ECDSA key pairs in the `keyring` table.
|
|
146
|
+
*/
|
|
147
|
+
var SqliteKeyring = class {
|
|
148
|
+
#runtime;
|
|
149
|
+
#keyCache = new ComplexMap(PublicKey.hash);
|
|
150
|
+
keysUpdate = new Event();
|
|
151
|
+
constructor({ runtime }) {
|
|
152
|
+
invariant(subtleCrypto, "SubtleCrypto not available in this environment.", {
|
|
153
|
+
"~LogMeta": "~LogMeta",
|
|
154
|
+
F: __dxlog_file,
|
|
155
|
+
L: 41,
|
|
156
|
+
S: this,
|
|
157
|
+
A: ["subtleCrypto", "'SubtleCrypto not available in this environment.'"]
|
|
158
|
+
});
|
|
159
|
+
this.#runtime = runtime;
|
|
160
|
+
}
|
|
161
|
+
migrate = Effect.fn("SqliteKeyring.migrate")(() => Effect.gen(function* () {
|
|
162
|
+
yield* (yield* SqlClient.SqlClient)`CREATE TABLE IF NOT EXISTS keyring (
|
|
163
|
+
public_key TEXT PRIMARY KEY,
|
|
164
|
+
record BLOB NOT NULL
|
|
165
|
+
)`;
|
|
166
|
+
}).pipe(Effect.withSpan("SqliteKeyring.migrate")))();
|
|
167
|
+
async sign(key, message) {
|
|
168
|
+
const keyPair = await this._getKey(key);
|
|
169
|
+
return new Uint8Array(await subtleCrypto.sign({
|
|
170
|
+
name: "ECDSA",
|
|
171
|
+
hash: "SHA-256"
|
|
172
|
+
}, keyPair.privateKey, message));
|
|
173
|
+
}
|
|
174
|
+
async createKey() {
|
|
175
|
+
const keyPair = await subtleCrypto.generateKey({
|
|
176
|
+
name: "ECDSA",
|
|
177
|
+
namedCurve: "P-256"
|
|
178
|
+
}, true, ["sign", "verify"]);
|
|
179
|
+
await this._setKey(keyPair);
|
|
180
|
+
return keyPairToPublicKey(keyPair);
|
|
181
|
+
}
|
|
182
|
+
async importKeyPair(keyPair) {
|
|
183
|
+
await this._setKey(keyPair);
|
|
184
|
+
return keyPairToPublicKey(keyPair);
|
|
185
|
+
}
|
|
186
|
+
async list() {
|
|
187
|
+
return (await RuntimeProvider.runPromise(this.#runtime)(Effect.gen(function* () {
|
|
188
|
+
return yield* (yield* SqlClient.SqlClient)`SELECT record FROM keyring`;
|
|
189
|
+
}))).map((row) => {
|
|
190
|
+
return { publicKey: KeyRecordCodec.decode(row.record).publicKey };
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
async _getKey(key) {
|
|
194
|
+
if (this.#keyCache.has(key)) return this.#keyCache.get(key);
|
|
195
|
+
const keyHex = key.toHex();
|
|
196
|
+
const rows = await RuntimeProvider.runPromise(this.#runtime)(Effect.gen(function* () {
|
|
197
|
+
return yield* (yield* SqlClient.SqlClient)`SELECT record FROM keyring WHERE public_key = ${keyHex}`;
|
|
198
|
+
}));
|
|
199
|
+
if (rows.length === 0) throw new Error(`Key not found: ${keyHex}`);
|
|
200
|
+
const record = KeyRecordCodec.decode(rows[0].record);
|
|
201
|
+
const publicKey = PublicKey.from(record.publicKey);
|
|
202
|
+
invariant(key.equals(publicKey), "Corrupted keyring: key mismatch", {
|
|
203
|
+
"~LogMeta": "~LogMeta",
|
|
204
|
+
F: __dxlog_file,
|
|
205
|
+
L: 113,
|
|
206
|
+
S: this,
|
|
207
|
+
A: ["key.equals(publicKey)", "'Corrupted keyring: key mismatch'"]
|
|
208
|
+
});
|
|
209
|
+
invariant(record.privateKey, "Corrupted keyring: missing private key", {
|
|
210
|
+
"~LogMeta": "~LogMeta",
|
|
211
|
+
F: __dxlog_file,
|
|
212
|
+
L: 114,
|
|
213
|
+
S: this,
|
|
214
|
+
A: ["record.privateKey", "'Corrupted keyring: missing private key'"]
|
|
215
|
+
});
|
|
216
|
+
const keyPair = {
|
|
217
|
+
publicKey: await subtleCrypto.importKey("raw", record.publicKey, {
|
|
218
|
+
name: "ECDSA",
|
|
219
|
+
namedCurve: "P-256"
|
|
220
|
+
}, true, ["verify"]),
|
|
221
|
+
privateKey: await subtleCrypto.importKey("pkcs8", record.privateKey, {
|
|
222
|
+
name: "ECDSA",
|
|
223
|
+
namedCurve: "P-256"
|
|
224
|
+
}, true, ["sign"])
|
|
225
|
+
};
|
|
226
|
+
this.#keyCache.set(publicKey, keyPair);
|
|
227
|
+
return keyPair;
|
|
228
|
+
}
|
|
229
|
+
async _setKey(keyPair) {
|
|
230
|
+
const publicKey = await keyPairToPublicKey(keyPair);
|
|
231
|
+
this.#keyCache.set(publicKey, keyPair);
|
|
232
|
+
const record = {
|
|
233
|
+
publicKey: publicKey.asUint8Array(),
|
|
234
|
+
privateKey: new Uint8Array(await subtleCrypto.exportKey("pkcs8", keyPair.privateKey))
|
|
235
|
+
};
|
|
236
|
+
const keyHex = publicKey.toHex();
|
|
237
|
+
const encodedRecord = arrayToBuffer(KeyRecordCodec.encode(record));
|
|
238
|
+
await RuntimeProvider.runPromise(this.#runtime)(Effect.gen(function* () {
|
|
239
|
+
yield* (yield* SqlClient.SqlClient)`INSERT OR REPLACE INTO keyring (public_key, record) VALUES (${keyHex}, ${encodedRecord})`;
|
|
240
|
+
}));
|
|
241
|
+
this.keysUpdate.emit();
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
__decorate([synchronized], SqliteKeyring.prototype, "_getKey", null);
|
|
245
|
+
__decorate([synchronized], SqliteKeyring.prototype, "_setKey", null);
|
|
246
|
+
var keyPairToPublicKey = async (keyPair) => PublicKey.from(new Uint8Array(await subtleCrypto.exportKey("raw", keyPair.publicKey)));
|
|
247
|
+
/**
|
|
248
|
+
* Effect Layer constructing a {@link SqliteKeyring} from the ambient SQL runtime.
|
|
249
|
+
*/
|
|
250
|
+
var SqliteKeyringLayer = () => Layer.effect(KeyringApiService, Effect.gen(function* () {
|
|
251
|
+
return new SqliteKeyring({ runtime: yield* RuntimeProvider.currentRuntime() });
|
|
252
|
+
}));
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region src/testing.ts
|
|
255
|
+
/**
|
|
256
|
+
* Generate a key pair which for testing purposes.
|
|
257
|
+
* @returns {Promise<TestKeyPair>}
|
|
258
|
+
*/
|
|
259
|
+
var generateJWKKeyPair = async () => {
|
|
260
|
+
const keyPair = await subtleCrypto.generateKey({
|
|
261
|
+
name: "ECDSA",
|
|
262
|
+
namedCurve: "P-256"
|
|
263
|
+
}, true, ["sign", "verify"]);
|
|
264
|
+
const privateKeyExported = await subtleCrypto.exportKey("jwk", keyPair.privateKey);
|
|
265
|
+
const publicKeyExported = await subtleCrypto.exportKey("jwk", keyPair.publicKey);
|
|
266
|
+
const publicKeyBuffer = new Uint8Array(await subtleCrypto.exportKey("raw", keyPair.publicKey));
|
|
267
|
+
return {
|
|
268
|
+
privateKey: privateKeyExported,
|
|
269
|
+
publicKey: publicKeyExported,
|
|
270
|
+
publicKeyHex: Array.from(publicKeyBuffer).map((byte) => byte.toString(16).padStart(2, "0")).join("")
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* Parse a key pair from JWK format.
|
|
275
|
+
*/
|
|
276
|
+
var parseJWKKeyPair = async (privateKey, publicKey) => {
|
|
277
|
+
return {
|
|
278
|
+
privateKey: await subtleCrypto.importKey("jwk", privateKey, {
|
|
279
|
+
name: "ECDSA",
|
|
280
|
+
namedCurve: "P-256"
|
|
281
|
+
}, true, ["sign"]),
|
|
282
|
+
publicKey: await subtleCrypto.importKey("jwk", publicKey, {
|
|
283
|
+
name: "ECDSA",
|
|
284
|
+
namedCurve: "P-256"
|
|
285
|
+
}, true, ["verify"])
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
//#endregion
|
|
289
|
+
export { Keyring, KeyringApiService, SqliteKeyring, SqliteKeyringLayer, generateJWKKeyPair, parseJWKKeyPair };
|
|
290
|
+
|
|
291
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/keyring.ts","../../src/sqlite-keyring.ts","../../src/testing.ts"],"sourcesContent":["//\n// Copyright 2022 DXOS.org\n//\n\nimport * as EffectContext from 'effect/Context';\n\nimport { Event, synchronized } from '@dxos/async';\nimport { type ProtoCodec } from '@dxos/codec-protobuf';\nimport { type Signer, subtleCrypto } from '@dxos/crypto';\nimport { todo } from '@dxos/debug';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { schema } from '@dxos/protocols/proto';\nimport { type KeyRecord } from '@dxos/protocols/proto/dxos/halo/keyring';\nimport { type Directory, StorageType, createStorage } from '@dxos/random-access-storage';\nimport { ComplexMap, arrayToBuffer } from '@dxos/util';\n\nconst KeyRecord: ProtoCodec<KeyRecord> = schema.getCodecForType('dxos.halo.keyring.KeyRecord');\n\n/**\n * Shared public API for keyring implementations.\n */\nexport interface KeyringApi extends Signer {\n readonly keysUpdate: Event;\n createKey(): Promise<PublicKey>;\n importKeyPair(keyPair: CryptoKeyPair): Promise<PublicKey>;\n list(): Promise<KeyRecord[]>;\n}\n\n/**\n * Effect service tag for {@link KeyringApi}.\n */\nexport class KeyringApiService extends EffectContext.Tag('@dxos/keyring/KeyringApi')<KeyringApiService, KeyringApi>() {}\n\n/**\n * Manages keys.\n */\nexport class Keyring implements KeyringApi {\n private readonly _keyCache = new ComplexMap<PublicKey, CryptoKeyPair>(PublicKey.hash);\n readonly keysUpdate = new Event();\n\n constructor(\n private readonly _storage: Directory = createStorage({\n type: StorageType.RAM,\n }).createDirectory('keyring'),\n ) {\n invariant(subtleCrypto, 'SubtleCrypto not available in this environment.');\n }\n\n async sign(key: PublicKey, message: Uint8Array): Promise<Uint8Array> {\n const keyPair = await this._getKey(key);\n\n return new Uint8Array(\n await subtleCrypto.sign(\n {\n name: 'ECDSA',\n hash: 'SHA-256',\n },\n keyPair.privateKey,\n message as Uint8Array<ArrayBuffer>,\n ),\n );\n }\n\n async createKey(): Promise<PublicKey> {\n const keyPair = await subtleCrypto.generateKey(\n {\n name: 'ECDSA',\n namedCurve: 'P-256',\n },\n true,\n ['sign', 'verify'],\n );\n\n await this._setKey(keyPair);\n\n return keyPairToPublicKey(keyPair);\n }\n\n @synchronized\n private async _getKey(key: PublicKey): Promise<CryptoKeyPair> {\n if (!this._keyCache.has(key)) {\n const file = this._storage.getOrCreateFile(key.toHex());\n const { size } = await file.stat();\n if (size === 0) {\n throw new Error(`Key not found: ${key.toHex()}`);\n }\n\n const recordBytes = await file.read(0, size);\n await file.close();\n\n const record = KeyRecord.decode(recordBytes);\n const publicKey = PublicKey.from(record.publicKey);\n invariant(key.equals(publicKey), 'Corrupted keyring: Key mismatch');\n invariant(record.privateKey, 'Corrupted keyring: Missing private key');\n const keyPair: CryptoKeyPair = {\n publicKey: await subtleCrypto.importKey(\n 'raw',\n record.publicKey as Uint8Array<ArrayBuffer>,\n {\n name: 'ECDSA',\n namedCurve: 'P-256',\n },\n true,\n ['verify'],\n ),\n privateKey: await subtleCrypto.importKey(\n 'pkcs8',\n record.privateKey as Uint8Array<ArrayBuffer>,\n {\n name: 'ECDSA',\n namedCurve: 'P-256',\n },\n true,\n ['sign'],\n ),\n };\n\n this._keyCache.set(publicKey, keyPair);\n }\n\n return this._keyCache.get(key)!; // TODO(burdon): Fail if null?\n }\n\n @synchronized\n private async _setKey(keyPair: CryptoKeyPair): Promise<void> {\n const publicKey = await keyPairToPublicKey(keyPair);\n this._keyCache.set(publicKey, keyPair);\n\n const record: KeyRecord = {\n publicKey: publicKey.asUint8Array(),\n privateKey: new Uint8Array(await subtleCrypto.exportKey('pkcs8', keyPair.privateKey)),\n };\n\n const file = this._storage.getOrCreateFile(publicKey.toHex());\n await file.write(0, arrayToBuffer(KeyRecord.encode(record)));\n await file.close();\n await file.flush?.();\n this.keysUpdate.emit();\n }\n\n // TODO(burdon): ???\n deleteKey(key: PublicKey): Promise<void> {\n return todo('We need a method to delete a file.');\n }\n\n async list(): Promise<KeyRecord[]> {\n const keys: KeyRecord[] = [];\n for (const path of await this._storage.list()) {\n const fileName = path.split('/').pop(); // get last portion of the path\n invariant(fileName, 'Invalid file name');\n keys.push({ publicKey: PublicKey.fromHex(fileName).asUint8Array() });\n }\n return keys;\n }\n\n async importKeyPair(keyPair: CryptoKeyPair): Promise<PublicKey> {\n await this._setKey(keyPair);\n return keyPairToPublicKey(keyPair);\n }\n}\n\nconst keyPairToPublicKey = async (keyPair: CryptoKeyPair): Promise<PublicKey> => {\n return PublicKey.from(new Uint8Array(await subtleCrypto.exportKey('raw', keyPair.publicKey)));\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport * as SqlClient from '@effect/sql/SqlClient';\nimport type * as SqlError from '@effect/sql/SqlError';\nimport * as Effect from 'effect/Effect';\nimport * as Layer from 'effect/Layer';\n\nimport { Event, synchronized } from '@dxos/async';\nimport { subtleCrypto } from '@dxos/crypto';\nimport { RuntimeProvider } from '@dxos/effect';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { schema } from '@dxos/protocols/proto';\nimport { type KeyRecord } from '@dxos/protocols/proto/dxos/halo/keyring';\nimport { SqlTransaction } from '@dxos/sql-sqlite';\nimport { ComplexMap, arrayToBuffer } from '@dxos/util';\n\nimport { type KeyringApi, KeyringApiService } from './keyring';\n\nconst KeyRecordCodec = schema.getCodecForType('dxos.halo.keyring.KeyRecord');\n\n// SqlTransaction.SqlTransaction is the Tag class exported from the SqlTransaction namespace.\ntype SqlTransactionTag = SqlTransaction.SqlTransaction;\n\nexport type SqliteKeyringOptions = {\n runtime: RuntimeProvider.RuntimeProvider<SqlClient.SqlClient | SqlTransactionTag>;\n};\n\n/**\n * SQLite-backed Keyring.\n * Stores ECDSA key pairs in the `keyring` table.\n */\nexport class SqliteKeyring implements KeyringApi {\n readonly #runtime: RuntimeProvider.RuntimeProvider<SqlClient.SqlClient | SqlTransactionTag>;\n readonly #keyCache = new ComplexMap<PublicKey, CryptoKeyPair>(PublicKey.hash);\n readonly keysUpdate = new Event();\n\n constructor({ runtime }: SqliteKeyringOptions) {\n invariant(subtleCrypto, 'SubtleCrypto not available in this environment.');\n this.#runtime = runtime;\n }\n\n readonly migrate: Effect.Effect<void, SqlError.SqlError, SqlClient.SqlClient | SqlTransactionTag> = Effect.fn(\n 'SqliteKeyring.migrate',\n )(() =>\n Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n yield* sql`CREATE TABLE IF NOT EXISTS keyring (\n public_key TEXT PRIMARY KEY,\n record BLOB NOT NULL\n )`;\n }).pipe(Effect.withSpan('SqliteKeyring.migrate')),\n )();\n\n async sign(key: PublicKey, message: Uint8Array): Promise<Uint8Array> {\n const keyPair = await this._getKey(key);\n return new Uint8Array(\n await subtleCrypto.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n keyPair.privateKey,\n message as Uint8Array<ArrayBuffer>,\n ),\n );\n }\n\n async createKey(): Promise<PublicKey> {\n const keyPair = await subtleCrypto.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign', 'verify']);\n await this._setKey(keyPair);\n return keyPairToPublicKey(keyPair);\n }\n\n async importKeyPair(keyPair: CryptoKeyPair): Promise<PublicKey> {\n await this._setKey(keyPair);\n return keyPairToPublicKey(keyPair);\n }\n\n async list(): Promise<KeyRecord[]> {\n const rows = await RuntimeProvider.runPromise(this.#runtime)(\n Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n return yield* sql<{ record: Uint8Array }>`SELECT record FROM keyring`;\n }),\n );\n return rows.map((row) => {\n const record = KeyRecordCodec.decode(row.record);\n // Never expose private key material to callers.\n return { publicKey: record.publicKey };\n });\n }\n\n @synchronized\n private async _getKey(key: PublicKey): Promise<CryptoKeyPair> {\n if (this.#keyCache.has(key)) {\n return this.#keyCache.get(key)!;\n }\n\n const keyHex = key.toHex();\n const rows = await RuntimeProvider.runPromise(this.#runtime)(\n Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n return yield* sql<{ record: Uint8Array }>`SELECT record FROM keyring WHERE public_key = ${keyHex}`;\n }),\n );\n\n if (rows.length === 0) {\n throw new Error(`Key not found: ${keyHex}`);\n }\n\n const record = KeyRecordCodec.decode(rows[0].record);\n const publicKey = PublicKey.from(record.publicKey);\n invariant(key.equals(publicKey), 'Corrupted keyring: key mismatch');\n invariant(record.privateKey, 'Corrupted keyring: missing private key');\n\n const keyPair: CryptoKeyPair = {\n publicKey: await subtleCrypto.importKey(\n 'raw',\n record.publicKey as Uint8Array<ArrayBuffer>,\n { name: 'ECDSA', namedCurve: 'P-256' },\n true,\n ['verify'],\n ),\n privateKey: await subtleCrypto.importKey(\n 'pkcs8',\n record.privateKey as Uint8Array<ArrayBuffer>,\n { name: 'ECDSA', namedCurve: 'P-256' },\n true,\n ['sign'],\n ),\n };\n\n this.#keyCache.set(publicKey, keyPair);\n return keyPair;\n }\n\n @synchronized\n private async _setKey(keyPair: CryptoKeyPair): Promise<void> {\n const publicKey = await keyPairToPublicKey(keyPair);\n this.#keyCache.set(publicKey, keyPair);\n\n const record: KeyRecord = {\n publicKey: publicKey.asUint8Array(),\n privateKey: new Uint8Array(await subtleCrypto.exportKey('pkcs8', keyPair.privateKey)),\n };\n\n const keyHex = publicKey.toHex();\n const encodedRecord = arrayToBuffer(KeyRecordCodec.encode(record));\n await RuntimeProvider.runPromise(this.#runtime)(\n Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n yield* sql`INSERT OR REPLACE INTO keyring (public_key, record) VALUES (${keyHex}, ${encodedRecord})`;\n }),\n );\n this.keysUpdate.emit();\n }\n}\n\nconst keyPairToPublicKey = async (keyPair: CryptoKeyPair): Promise<PublicKey> =>\n PublicKey.from(new Uint8Array(await subtleCrypto.exportKey('raw', keyPair.publicKey)));\n\n/**\n * Effect Layer constructing a {@link SqliteKeyring} from the ambient SQL runtime.\n */\nexport const SqliteKeyringLayer = (): Layer.Layer<KeyringApiService, never, SqlClient.SqlClient | SqlTransactionTag> =>\n Layer.effect(\n KeyringApiService,\n Effect.gen(function* () {\n const runtime = yield* RuntimeProvider.currentRuntime<SqlClient.SqlClient | SqlTransactionTag>();\n return new SqliteKeyring({ runtime });\n }),\n );\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport { subtleCrypto } from '@dxos/crypto';\n\nexport type TestKeyPair = {\n privateKey: JsonWebKey;\n publicKey: JsonWebKey;\n publicKeyHex: string;\n};\n\n/**\n * Generate a key pair which for testing purposes.\n * @returns {Promise<TestKeyPair>}\n */\nexport const generateJWKKeyPair = async (): Promise<TestKeyPair> => {\n const keyPair = await subtleCrypto.generateKey(\n {\n name: 'ECDSA',\n namedCurve: 'P-256',\n },\n true,\n ['sign', 'verify'],\n );\n\n const privateKeyExported = await subtleCrypto.exportKey('jwk', keyPair.privateKey);\n const publicKeyExported = await subtleCrypto.exportKey('jwk', keyPair.publicKey);\n\n // Convert the public key to hex format\n const publicKeyBuffer = new Uint8Array(await subtleCrypto.exportKey('raw', keyPair.publicKey));\n const publicKeyHex = Array.from(publicKeyBuffer)\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('');\n\n return {\n privateKey: privateKeyExported,\n publicKey: publicKeyExported,\n publicKeyHex,\n };\n};\n\n/**\n * Parse a key pair from JWK format.\n */\nexport const parseJWKKeyPair = async (privateKey: JsonWebKey, publicKey: JsonWebKey): Promise<CryptoKeyPair> => {\n return {\n privateKey: await subtleCrypto.importKey('jwk', privateKey, { name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign']),\n publicKey: await subtleCrypto.importKey('jwk', publicKey, { name: 'ECDSA', namedCurve: 'P-256' }, true, ['verify']),\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as EffectContext from 'effect/Context';
|
|
1
2
|
import { Event } from '@dxos/async';
|
|
2
3
|
import { type ProtoCodec } from '@dxos/codec-protobuf';
|
|
3
4
|
import { type Signer } from '@dxos/crypto';
|
|
@@ -14,6 +15,12 @@ export interface KeyringApi extends Signer {
|
|
|
14
15
|
importKeyPair(keyPair: CryptoKeyPair): Promise<PublicKey>;
|
|
15
16
|
list(): Promise<KeyRecord[]>;
|
|
16
17
|
}
|
|
18
|
+
declare const KeyringApiService_base: EffectContext.TagClass<KeyringApiService, "@dxos/keyring/KeyringApi", KeyringApi>;
|
|
19
|
+
/**
|
|
20
|
+
* Effect service tag for {@link KeyringApi}.
|
|
21
|
+
*/
|
|
22
|
+
export declare class KeyringApiService extends KeyringApiService_base {
|
|
23
|
+
}
|
|
17
24
|
/**
|
|
18
25
|
* Manages keys.
|
|
19
26
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyring.d.ts","sourceRoot":"","sources":["../../../src/keyring.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAgB,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,SAAS,EAA8B,MAAM,6BAA6B,CAAC;AAGzF,QAAA,MAAM,SAAS,EAAE,UAAU,CAAC,SAAS,CAAyD,CAAC;AAE/F;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,MAAM;IACxC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3B,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1D,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CAC9B
|
|
1
|
+
{"version":3,"file":"keyring.d.ts","sourceRoot":"","sources":["../../../src/keyring.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,aAAa,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,KAAK,EAAgB,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,SAAS,EAA8B,MAAM,6BAA6B,CAAC;AAGzF,QAAA,MAAM,SAAS,EAAE,UAAU,CAAC,SAAS,CAAyD,CAAC;AAE/F;;GAEG;AACH,MAAM,WAAW,UAAW,SAAQ,MAAM;IACxC,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC;IAC3B,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1D,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CAC9B;;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,sBAA8E;CAAG;AAExH;;GAEG;AACH,qBAAa,OAAQ,YAAW,UAAU;IAKtC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4D;IACtF,QAAQ,CAAC,UAAU,cAAe;IAElC,YACmB,QAAQ,GAAE,SAEE,EAG9B;IAEK,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAanE;IAEK,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAapC;YAGa,OAAO;YA6CP,OAAO;IAiBrB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvC;IAEK,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAQjC;IAEK,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAG9D;CACF"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as SqlClient from '@effect/sql/SqlClient';
|
|
2
2
|
import type * as SqlError from '@effect/sql/SqlError';
|
|
3
3
|
import * as Effect from 'effect/Effect';
|
|
4
|
+
import * as Layer from 'effect/Layer';
|
|
4
5
|
import { Event } from '@dxos/async';
|
|
5
6
|
import { RuntimeProvider } from '@dxos/effect';
|
|
6
7
|
import { PublicKey } from '@dxos/keys';
|
|
7
8
|
import { type KeyRecord } from '@dxos/protocols/proto/dxos/halo/keyring';
|
|
8
9
|
import { SqlTransaction } from '@dxos/sql-sqlite';
|
|
9
|
-
import { type KeyringApi } from './keyring';
|
|
10
|
+
import { type KeyringApi, KeyringApiService } from './keyring';
|
|
10
11
|
type SqlTransactionTag = SqlTransaction.SqlTransaction;
|
|
11
12
|
export type SqliteKeyringOptions = {
|
|
12
13
|
runtime: RuntimeProvider.RuntimeProvider<SqlClient.SqlClient | SqlTransactionTag>;
|
|
@@ -27,5 +28,9 @@ export declare class SqliteKeyring implements KeyringApi {
|
|
|
27
28
|
private _getKey;
|
|
28
29
|
private _setKey;
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Effect Layer constructing a {@link SqliteKeyring} from the ambient SQL runtime.
|
|
33
|
+
*/
|
|
34
|
+
export declare const SqliteKeyringLayer: () => Layer.Layer<KeyringApiService, never, SqlClient.SqlClient | SqlTransactionTag>;
|
|
30
35
|
export {};
|
|
31
36
|
//# sourceMappingURL=sqlite-keyring.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-keyring.d.ts","sourceRoot":"","sources":["../../../src/sqlite-keyring.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite-keyring.d.ts","sourceRoot":"","sources":["../../../src/sqlite-keyring.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,KAAK,EAAgB,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,OAAO,EAAE,KAAK,UAAU,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAK/D,KAAK,iBAAiB,GAAG,cAAc,CAAC,cAAc,CAAC;AAEvD,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,eAAe,CAAC,eAAe,CAAC,SAAS,CAAC,SAAS,GAAG,iBAAiB,CAAC,CAAC;CACnF,CAAC;AAEF;;;GAGG;AACH,qBAAa,aAAc,YAAW,UAAU;;IAG9C,QAAQ,CAAC,UAAU,cAAe;IAElC,YAAY,EAAE,OAAO,EAAE,EAAE,oBAAoB,EAG5C;IAED,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,GAAG,iBAAiB,CAAC,CAU7F;IAEE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CASnE;IAEK,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC,CAIpC;IAEK,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAG9D;IAEK,IAAI,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAYjC;YAGa,OAAO;YA4CP,OAAO;CAmBtB;AAKD;;GAEG;AACH,eAAO,MAAM,kBAAkB,QAAO,KAAK,CAAC,KAAK,CAAC,iBAAiB,EAAE,KAAK,EAAE,SAAS,CAAC,SAAS,GAAG,iBAAiB,CAOhH,CAAC"}
|