@interop/wallet-core 0.78.1 → 0.79.1
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/README.md +18 -3
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +2 -2
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
- package/dist/clientAnnex/credentialAnchoredGenesis.js +1 -1
- package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -1
- package/dist/clientAnnex/establish.d.ts +2 -2
- package/dist/clientAnnex/establish.d.ts.map +1 -1
- package/dist/clientAnnex/forget.d.ts +1 -1
- package/dist/clientAnnex/forget.d.ts.map +1 -1
- package/dist/clientAnnex/heal.d.ts.map +1 -1
- package/dist/clientAnnex/heal.js +3 -1
- package/dist/clientAnnex/heal.js.map +1 -1
- package/dist/clientAnnex/ladder.d.ts +3 -98
- package/dist/clientAnnex/ladder.d.ts.map +1 -1
- package/dist/clientAnnex/ladder.js +4 -140
- package/dist/clientAnnex/ladder.js.map +1 -1
- package/dist/clientAnnex/log.d.ts +26 -10
- package/dist/clientAnnex/log.d.ts.map +1 -1
- package/dist/clientAnnex/log.js +39 -19
- package/dist/clientAnnex/log.js.map +1 -1
- package/dist/clientAnnex/mend.d.ts +2 -2
- package/dist/clientAnnex/mend.d.ts.map +1 -1
- package/dist/clientAnnex/mend.js +1 -1
- package/dist/clientAnnex/mend.js.map +1 -1
- package/dist/clientAnnex/rosterDeliveredEpochs.d.ts +1 -1
- package/dist/clientAnnex/rosterDeliveredEpochs.d.ts.map +1 -1
- package/dist/clientAnnex/selfEnroll.d.ts +1 -1
- package/dist/clientAnnex/selfEnroll.d.ts.map +1 -1
- package/dist/clientAnnex/selfEnroll.js +2 -1
- package/dist/clientAnnex/selfEnroll.js.map +1 -1
- package/dist/clients/revocation.d.ts +1 -1
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/rosterPolicy.d.ts +1 -1
- package/dist/clients/rosterPolicy.d.ts.map +1 -1
- package/dist/descriptors/logSource.d.ts +2 -1
- package/dist/descriptors/logSource.d.ts.map +1 -1
- package/dist/descriptors/logSource.js +1 -1
- package/dist/descriptors/logSource.js.map +1 -1
- package/dist/enrollment/enrollment.d.ts +2 -2
- package/dist/enrollment/enrollment.d.ts.map +1 -1
- package/dist/enrollment/enrollment.js +2 -1
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/genesis/accountGenesis.d.ts +1 -1
- package/dist/genesis/accountGenesis.d.ts.map +1 -1
- package/dist/genesis/accountGenesis.js +11 -5
- package/dist/genesis/accountGenesis.js.map +1 -1
- package/dist/keyring/fetch.d.ts +1 -1
- package/dist/keyring/fetch.d.ts.map +1 -1
- package/dist/keyring/fetch.js +1 -1
- package/dist/keyring/fetch.js.map +1 -1
- package/dist/keyring/index.d.ts +15 -8
- package/dist/keyring/index.d.ts.map +1 -1
- package/dist/keyring/index.js +11 -6
- package/dist/keyring/index.js.map +1 -1
- package/dist/keyring/kdf.d.ts +0 -69
- package/dist/keyring/kdf.d.ts.map +1 -1
- package/dist/keyring/kdf.js +7 -86
- package/dist/keyring/kdf.js.map +1 -1
- package/dist/keyring/record.d.ts +1 -200
- package/dist/keyring/record.d.ts.map +1 -1
- package/dist/keyring/record.js +5 -251
- package/dist/keyring/record.js.map +1 -1
- package/dist/keyring/recordEnvelope.d.ts +270 -0
- package/dist/keyring/recordEnvelope.d.ts.map +1 -0
- package/dist/keyring/recordEnvelope.js +282 -0
- package/dist/keyring/recordEnvelope.js.map +1 -0
- package/dist/keyring/unlockIdentity.d.ts +71 -0
- package/dist/keyring/unlockIdentity.d.ts.map +1 -0
- package/dist/keyring/unlockIdentity.js +96 -0
- package/dist/keyring/unlockIdentity.js.map +1 -0
- package/dist/keyring/unlockSpace.d.ts +12 -1
- package/dist/keyring/unlockSpace.d.ts.map +1 -1
- package/dist/keyring/unlockSpace.js +15 -2
- package/dist/keyring/unlockSpace.js.map +1 -1
- package/dist/keys/index.d.ts +6 -3
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +6 -3
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/rosterLogStore.d.ts +1 -1
- package/dist/keys/rosterLogStore.d.ts.map +1 -1
- package/dist/keys/rosterLogStore.js +1 -1
- package/dist/keys/rosterLogStore.js.map +1 -1
- package/dist/keys/rosterRecipientKid.d.ts +28 -0
- package/dist/keys/rosterRecipientKid.d.ts.map +1 -0
- package/dist/keys/rosterRecipientKid.js +27 -0
- package/dist/keys/rosterRecipientKid.js.map +1 -0
- package/dist/keys/spaceEpochs.d.ts +1 -1
- package/dist/keys/spaceEpochs.d.ts.map +1 -1
- package/dist/keys/spaceEpochs.js +2 -2
- package/dist/keys/spaceEpochs.js.map +1 -1
- package/dist/keys/userKey.d.ts +4 -46
- package/dist/keys/userKey.d.ts.map +1 -1
- package/dist/keys/userKey.js +8 -60
- package/dist/keys/userKey.js.map +1 -1
- package/dist/keys/userKeyCascade.d.ts +1 -33
- package/dist/keys/userKeyCascade.d.ts.map +1 -1
- package/dist/keys/userKeyCascade.js +2 -49
- package/dist/keys/userKeyCascade.js.map +1 -1
- package/dist/keys/userKeyGenerations.d.ts +47 -0
- package/dist/keys/userKeyGenerations.d.ts.map +1 -0
- package/dist/keys/userKeyGenerations.js +50 -0
- package/dist/keys/userKeyGenerations.js.map +1 -0
- package/dist/keys/userKeyRoster.d.ts +1 -19
- package/dist/keys/userKeyRoster.d.ts.map +1 -1
- package/dist/keys/userKeyRoster.js +13 -19
- package/dist/keys/userKeyRoster.js.map +1 -1
- package/dist/keys/userKeyRosterCascade.d.ts +1 -1
- package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
- package/dist/keys/userKeySigning.d.ts +44 -0
- package/dist/keys/userKeySigning.d.ts.map +1 -0
- package/dist/keys/userKeySigning.js +65 -0
- package/dist/keys/userKeySigning.js.map +1 -0
- package/dist/recovery/recoveryCode.d.ts.map +1 -1
- package/dist/recovery/recoveryCode.js +3 -4
- package/dist/recovery/recoveryCode.js.map +1 -1
- package/dist/recovery/recoveryDelegation.d.ts +1 -1
- package/dist/recovery/recoveryDelegation.d.ts.map +1 -1
- package/dist/space/collections.d.ts +1 -43
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +2 -34
- package/dist/space/collections.js.map +1 -1
- package/dist/space/systemCollections.d.ts +55 -0
- package/dist/space/systemCollections.d.ts.map +1 -0
- package/dist/space/systemCollections.js +46 -0
- package/dist/space/systemCollections.js.map +1 -0
- package/dist/sync/contactsConflict.d.ts +56 -10
- package/dist/sync/contactsConflict.d.ts.map +1 -1
- package/dist/sync/contactsConflict.js +82 -18
- package/dist/sync/contactsConflict.js.map +1 -1
- package/dist/sync/engine.d.ts +9 -3
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/pull.d.ts +25 -4
- package/dist/sync/pull.d.ts.map +1 -1
- package/dist/sync/pull.js +27 -3
- package/dist/sync/pull.js.map +1 -1
- package/dist/sync/remint.d.ts +10 -4
- package/dist/sync/remint.d.ts.map +1 -1
- package/dist/sync/remint.js +28 -6
- package/dist/sync/remint.js.map +1 -1
- package/dist/unlock/ladderDerivation.d.ts +98 -0
- package/dist/unlock/ladderDerivation.d.ts.map +1 -0
- package/dist/unlock/ladderDerivation.js +157 -0
- package/dist/unlock/ladderDerivation.js.map +1 -0
- package/dist/unlock/retire.d.ts +1 -1
- package/dist/unlock/retire.d.ts.map +1 -1
- package/dist/unlock/standingClient.js +1 -1
- package/dist/unlock/standingClient.js.map +1 -1
- package/dist/unlock/standingWebvh.d.ts.map +1 -1
- package/dist/unlock/standingWebvh.js +3 -3
- package/dist/unlock/standingWebvh.js.map +1 -1
- package/dist/unlock/unlockRecord.d.ts +2 -1
- package/dist/unlock/unlockRecord.d.ts.map +1 -1
- package/dist/unlock/unlockRecord.js +11 -2
- package/dist/unlock/unlockRecord.js.map +1 -1
- package/dist/webvh/accountEntry.d.ts +2 -1
- package/dist/webvh/accountEntry.d.ts.map +1 -1
- package/dist/webvh/accountEntry.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +1 -11
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +5 -13
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/updateKeyMultibase.d.ts +12 -0
- package/dist/webvh/updateKeyMultibase.d.ts.map +1 -0
- package/dist/webvh/updateKeyMultibase.js +23 -0
- package/dist/webvh/updateKeyMultibase.js.map +1 -0
- package/dist/webvh/wasIdStore.d.ts +5 -3
- package/dist/webvh/wasIdStore.d.ts.map +1 -1
- package/dist/webvh/wasIdStore.js.map +1 -1
- package/package.json +59 -11
package/dist/keyring/record.js
CHANGED
|
@@ -9,12 +9,9 @@
|
|
|
9
9
|
* material of any kind, so the record locates an account without authorizing
|
|
10
10
|
* anything against it.
|
|
11
11
|
*
|
|
12
|
-
* The
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* unlock key-agreement key. The record stays self-contained -- unlock KAK in,
|
|
16
|
-
* contents out. The cipher's `keyring` collection context labels errors only
|
|
17
|
-
* (the codec is agnostic to it).
|
|
12
|
+
* The envelope half (the record's own key epoch, its ciphers, the frame and
|
|
13
|
+
* plaintext parsing) is `recordEnvelope.ts`. This file is the authenticity
|
|
14
|
+
* layer over it, plus the keyring wrap and unwrap that need both halves.
|
|
18
15
|
*
|
|
19
16
|
* The authenticity layer is the `proof` member, and it is load-bearing: the
|
|
20
17
|
* unlock KAK's public half is derivable from the unlock did:key the server
|
|
@@ -32,30 +29,8 @@
|
|
|
32
29
|
*/
|
|
33
30
|
import { createDataIntegrityProofTemplate, defaultWebvhLogVerifier, signDataIntegrityProof, signerFromExternalKey, verifyEntryProofs } from '@interop/did-method-webvh';
|
|
34
31
|
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key';
|
|
35
|
-
import { createEdvDocCipher, createEdvEncryptOnlyDocCipher, initRecipients, ownerRecipient } from '@interop/was-client/edv';
|
|
36
32
|
import { vmFragmentOf } from '@interop/vh-resource-log';
|
|
37
|
-
import {
|
|
38
|
-
/**
|
|
39
|
-
* The version stamped on the stored `{ version, encryption, wrapped, proof }`
|
|
40
|
-
* keyring envelope: the signed record, whose envelope seals under the record's
|
|
41
|
-
* own key epoch (the `encryption` member) and whose sibling members carry a
|
|
42
|
-
* Data Integrity proof by the unlock identity's signing key. Any other version
|
|
43
|
-
* is refused as unusable -- such accounts are re-provisioned, not migrated.
|
|
44
|
-
*/
|
|
45
|
-
export const KEYRING_RECORD_VERSION = 2;
|
|
46
|
-
/**
|
|
47
|
-
* A record's proof is absent, malformed, signed by a key this client does not
|
|
48
|
-
* accept, or does not verify over the record's own members. Its own class,
|
|
49
|
-
* distinct from a decrypt failure or an unusable-version refusal: this is the
|
|
50
|
-
* refusal that says the storage host forged or tampered with the record, which
|
|
51
|
-
* an app maps to its own login copy.
|
|
52
|
-
*/
|
|
53
|
-
export class RecordProofError extends Error {
|
|
54
|
-
constructor(message, options) {
|
|
55
|
-
super(message, options);
|
|
56
|
-
this.name = 'RecordProofError';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
33
|
+
import { KEYRING_RECORD_VERSION, RecordProofError, checkRecordProofShape, mintRecordEncryption, parseRecordCreatedAt, parseRecordFrame, parseRecordPointer, recordCipher, recordCreatedAtStamp, recordEnvelopeId, recordSealCipher } from './recordEnvelope.js';
|
|
59
34
|
/**
|
|
60
35
|
* Adapts a signing key agent (the unlock identity's `CapabilityAgent`, or an
|
|
61
36
|
* enrolled client's own key agent) to the record signer seam: the agent's
|
|
@@ -133,29 +108,6 @@ export async function signRecordFrame({ version, encryption, wrapped, signer, me
|
|
|
133
108
|
}));
|
|
134
109
|
return { ...frame, proof: proof };
|
|
135
110
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Structural check of a record's `proof` member against the fixed shape,
|
|
138
|
-
* before any cryptography runs.
|
|
139
|
-
*
|
|
140
|
-
* @param options {object}
|
|
141
|
-
* @param options.proof {unknown}
|
|
142
|
-
* @param options.label {string} names the record kind in the refusal
|
|
143
|
-
* @returns {RecordProof}
|
|
144
|
-
*/
|
|
145
|
-
function checkRecordProofShape({ proof, label }) {
|
|
146
|
-
const candidate = proof;
|
|
147
|
-
if (candidate === null ||
|
|
148
|
-
typeof candidate !== 'object' ||
|
|
149
|
-
candidate.type !== 'DataIntegrityProof' ||
|
|
150
|
-
candidate.cryptosuite !== 'eddsa-jcs-2022' ||
|
|
151
|
-
candidate.proofPurpose !== 'assertionMethod' ||
|
|
152
|
-
typeof candidate.verificationMethod !== 'string' ||
|
|
153
|
-
typeof candidate.proofValue !== 'string') {
|
|
154
|
-
throw new RecordProofError(`The ${label} record carries no proof in the fixed shape ` +
|
|
155
|
-
`(DataIntegrityProof / eddsa-jcs-2022 / assertionMethod).`);
|
|
156
|
-
}
|
|
157
|
-
return candidate;
|
|
158
|
-
}
|
|
159
111
|
/**
|
|
160
112
|
* The signing key's public multibase named by a proof's `verificationMethod`:
|
|
161
113
|
* its fragment. The signer emits `did:key:<multibase>#<multibase>`; the DID
|
|
@@ -175,141 +127,6 @@ export function recordProofKeyMultibase({ verificationMethod, label }) {
|
|
|
175
127
|
}
|
|
176
128
|
return keyMultibase;
|
|
177
129
|
}
|
|
178
|
-
/**
|
|
179
|
-
* Mints the one-epoch descriptor a fresh record is sealed under: epoch[0]
|
|
180
|
-
* wrapped to the given KAK alone, built through `initRecipients` against a
|
|
181
|
-
* throwaway in-memory store (the descriptor's home is the record itself).
|
|
182
|
-
* Exported for any consumer sealing a self-contained
|
|
183
|
-
* `{ version, encryption, wrapped }` record -- the keyring and recovery
|
|
184
|
-
* records here, and a wallet app's own locally stored records (e.g.
|
|
185
|
-
* freewallet's client-key record and unlock-methods registry).
|
|
186
|
-
*
|
|
187
|
-
* @param options {object}
|
|
188
|
-
* @param options.keyAgreementKey {IKeyAgreementKey} the wrapping KAK (for
|
|
189
|
-
* the keyring record, the unlock KAK)
|
|
190
|
-
* @returns {Promise<CollectionEncryption>}
|
|
191
|
-
*/
|
|
192
|
-
export async function mintRecordEncryption({ keyAgreementKey }) {
|
|
193
|
-
let stored = null;
|
|
194
|
-
const store = {
|
|
195
|
-
async read() {
|
|
196
|
-
return stored ? { descriptor: stored } : null;
|
|
197
|
-
},
|
|
198
|
-
async replace(next) {
|
|
199
|
-
stored = next;
|
|
200
|
-
},
|
|
201
|
-
async create(next) {
|
|
202
|
-
stored = next;
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
return initRecipients({
|
|
206
|
-
store,
|
|
207
|
-
recipients: [ownerRecipient({ keyAgreementKey })]
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Builds the record's reading cipher: an EDV cipher over the record's own
|
|
212
|
-
* descriptor, from the reader's key-agreement key. The unwrap paths' cipher
|
|
213
|
-
* (and the recovery record's, which reuses the keyring cipher context
|
|
214
|
-
* verbatim); the wrap paths seal through {@link recordSealCipher} instead. An
|
|
215
|
-
* app's own record kind passes its own `collectionId` so its failures name
|
|
216
|
-
* the record kind. The context labels errors only -- the codec is agnostic to
|
|
217
|
-
* it, so a record kind's real swap protection is its contents validation on
|
|
218
|
-
* unwrap.
|
|
219
|
-
*
|
|
220
|
-
* @param options {object}
|
|
221
|
-
* @param options.keyAgreementKey {IKeyAgreementKey} the wrapping KAK (for
|
|
222
|
-
* the keyring record, the unlock KAK)
|
|
223
|
-
* @param options.keyResolver {IKeyResolver}
|
|
224
|
-
* @param options.encryption {CollectionEncryption} the record's descriptor
|
|
225
|
-
* @param [options.collectionId] {string} the cipher context failures are
|
|
226
|
-
* labeled with; defaults to the keyring context
|
|
227
|
-
* @returns {Promise<DocCipher>}
|
|
228
|
-
*/
|
|
229
|
-
export async function recordCipher({ keyAgreementKey, keyResolver, encryption, collectionId = KEYRING_COLLECTION.id }) {
|
|
230
|
-
return createEdvDocCipher({
|
|
231
|
-
keyAgreementKey,
|
|
232
|
-
keyResolver,
|
|
233
|
-
collectionId,
|
|
234
|
-
encryption
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Builds the record's sealing cipher: an encrypt-only EDV cipher over the
|
|
239
|
-
* record's own descriptor, needing no key-agreement secret -- a write seals to
|
|
240
|
-
* the descriptor's epoch public key, reconstructed from the epoch id. This is
|
|
241
|
-
* what lets the recovery re-mint, which holds only the code's unlock KAK
|
|
242
|
-
* public half, re-seal a record it can never open; the issuance wraps go
|
|
243
|
-
* through the same construction and produce the same envelope shape. Decrypt
|
|
244
|
-
* on it refuses with was-client's typed `EncryptOnlyCipherError`.
|
|
245
|
-
*
|
|
246
|
-
* @param options {object}
|
|
247
|
-
* @param options.encryption {CollectionEncryption} the record's descriptor
|
|
248
|
-
* @param [options.collectionId] {string} the cipher context failures are
|
|
249
|
-
* labeled with; defaults to the keyring context
|
|
250
|
-
* @returns {Promise<DocCipher>}
|
|
251
|
-
*/
|
|
252
|
-
export async function recordSealCipher({ encryption, collectionId = KEYRING_COLLECTION.id }) {
|
|
253
|
-
return createEdvEncryptOnlyDocCipher({ collectionId, encryption });
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Validates the common `{ version, encryption, wrapped }` frame of a stored
|
|
257
|
-
* record (keyring or recovery -- `label` names the refusals) and returns its
|
|
258
|
-
* members, the `proof` among them for the signed frame. Exported so an app's
|
|
259
|
-
* own record kinds open their records through the same frame validation the
|
|
260
|
-
* codec here seals with, rather than re-deriving the version and shape checks.
|
|
261
|
-
*
|
|
262
|
-
* A frame at the keyring record version is the signed frame, so it must carry
|
|
263
|
-
* a fixed-shape proof; a record kind stamping its own version is unaffected
|
|
264
|
-
* (its authenticity story is its own). Validating the shape here does not
|
|
265
|
-
* verify it -- {@link verifyRecordProof} does, and every unwrap path in this
|
|
266
|
-
* module runs it before decrypting.
|
|
267
|
-
*
|
|
268
|
-
* @param options {object}
|
|
269
|
-
* @param options.record {unknown}
|
|
270
|
-
* @param options.label {string} `'keyring'`, `'recovery'`, or an app record
|
|
271
|
-
* kind's own label
|
|
272
|
-
* @param [options.version] {number} the version the frame must carry;
|
|
273
|
-
* defaults to the keyring record version
|
|
274
|
-
* @returns {{ encryption: CollectionEncryption, wrapped: unknown,
|
|
275
|
-
* proof?: RecordProof }}
|
|
276
|
-
*/
|
|
277
|
-
export function parseRecordFrame({ record, label, version = KEYRING_RECORD_VERSION }) {
|
|
278
|
-
if (record === null || typeof record !== 'object') {
|
|
279
|
-
throw new Error(`Malformed ${label} record.`);
|
|
280
|
-
}
|
|
281
|
-
const { version: recordVersion, encryption, wrapped, proof } = record;
|
|
282
|
-
if (recordVersion !== version) {
|
|
283
|
-
// Two retired version-1 shapes are named rather than reported as an
|
|
284
|
-
// unsupported number, so neither refusal is read as corruption: the
|
|
285
|
-
// pre-extraction record (a data-seed wrap with no descriptor) and the
|
|
286
|
-
// unsigned envelope this version's proof replaced. Both are unusable.
|
|
287
|
-
if (version === KEYRING_RECORD_VERSION && recordVersion === 1) {
|
|
288
|
-
if (encryption === undefined) {
|
|
289
|
-
throw new Error(`The ${label} record uses the retired pre-extraction version 1 ` +
|
|
290
|
-
'shape (a data-seed wrap with no encryption descriptor); such ' +
|
|
291
|
-
'accounts are re-provisioned, not migrated.');
|
|
292
|
-
}
|
|
293
|
-
throw new Error(`The ${label} record uses the retired unsigned version 1 shape (no ` +
|
|
294
|
-
'proof over its frame, so a storage host could substitute it); ' +
|
|
295
|
-
'such accounts are re-provisioned, not migrated.');
|
|
296
|
-
}
|
|
297
|
-
throw new Error(`Unsupported ${label} record version "${String(recordVersion)}".`);
|
|
298
|
-
}
|
|
299
|
-
if (wrapped === undefined || wrapped === null) {
|
|
300
|
-
throw new Error(`Malformed ${label} record.`);
|
|
301
|
-
}
|
|
302
|
-
if (encryption === null || typeof encryption !== 'object') {
|
|
303
|
-
throw new Error(`The ${label} record is missing its encryption descriptor.`);
|
|
304
|
-
}
|
|
305
|
-
return {
|
|
306
|
-
encryption: encryption,
|
|
307
|
-
wrapped,
|
|
308
|
-
...(version === KEYRING_RECORD_VERSION
|
|
309
|
-
? { proof: checkRecordProofShape({ proof, label }) }
|
|
310
|
-
: {})
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
130
|
/**
|
|
314
131
|
* Verifies a stored record's proof: the fixed proof shape, the signing key
|
|
315
132
|
* against the caller's allowlist, and the signature over the record's sibling
|
|
@@ -448,6 +265,7 @@ export async function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver
|
|
|
448
265
|
encryption
|
|
449
266
|
});
|
|
450
267
|
const plaintext = (await cipher.decrypt({
|
|
268
|
+
id: recordEnvelopeId({ wrapped, label: 'keyring' }),
|
|
451
269
|
envelope: wrapped
|
|
452
270
|
}));
|
|
453
271
|
if (typeof plaintext.controller !== 'string' || !plaintext.controller) {
|
|
@@ -469,68 +287,4 @@ export async function unwrapKeyringRecord({ record, keyAgreementKey, keyResolver
|
|
|
469
287
|
...(pointer ? { pointer } : {})
|
|
470
288
|
};
|
|
471
289
|
}
|
|
472
|
-
/**
|
|
473
|
-
* The bind timestamp a wrap path stamps into a record's plaintext: the
|
|
474
|
-
* caller's, validated as a parseable ISO timestamp, or now. A caller supplies
|
|
475
|
-
* one when it pins record freshness, so it knows the stamp of the record it is
|
|
476
|
-
* writing without reading it back.
|
|
477
|
-
*
|
|
478
|
-
* @param options {object}
|
|
479
|
-
* @param [options.createdAt] {string} the caller's timestamp
|
|
480
|
-
* @returns {string}
|
|
481
|
-
*/
|
|
482
|
-
export function recordCreatedAtStamp({ createdAt }) {
|
|
483
|
-
if (createdAt === undefined) {
|
|
484
|
-
return new Date().toISOString();
|
|
485
|
-
}
|
|
486
|
-
if (typeof createdAt !== 'string' || Number.isNaN(Date.parse(createdAt))) {
|
|
487
|
-
throw new Error(`Invalid record createdAt timestamp "${createdAt}".`);
|
|
488
|
-
}
|
|
489
|
-
return createdAt;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Parses and validates the required `createdAt` member of a record plaintext:
|
|
493
|
-
* the moment the record was bound, as an ISO timestamp that must parse. Apps
|
|
494
|
-
* pin freshness on it, so a record that cannot state its own bind time is
|
|
495
|
-
* refused rather than defaulted.
|
|
496
|
-
*
|
|
497
|
-
* @param options {object}
|
|
498
|
-
* @param options.value {unknown} the plaintext's `createdAt` member
|
|
499
|
-
* @param options.label {string} names the record kind in the refusal
|
|
500
|
-
* @returns {string}
|
|
501
|
-
*/
|
|
502
|
-
export function parseRecordCreatedAt({ value, label }) {
|
|
503
|
-
if (typeof value !== 'string' || Number.isNaN(Date.parse(value))) {
|
|
504
|
-
throw new Error(`${label} record has no valid createdAt timestamp.`);
|
|
505
|
-
}
|
|
506
|
-
return value;
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Parses and validates the optional `pointer` member of a keyring record
|
|
510
|
-
* plaintext. An absent member is a no-WAS record (returns undefined); a
|
|
511
|
-
* present-but-malformed one throws -- a record that claims a pointer but
|
|
512
|
-
* cannot state where the account lives is unusable.
|
|
513
|
-
*
|
|
514
|
-
* @param value {unknown} the record's `pointer` member
|
|
515
|
-
* @returns {AccountPointer | undefined}
|
|
516
|
-
*/
|
|
517
|
-
export function parseRecordPointer(value) {
|
|
518
|
-
if (value === undefined) {
|
|
519
|
-
return undefined;
|
|
520
|
-
}
|
|
521
|
-
if (value === null || typeof value !== 'object') {
|
|
522
|
-
throw new Error('Keyring record has a malformed account pointer.');
|
|
523
|
-
}
|
|
524
|
-
const { did, spaceId, host } = value;
|
|
525
|
-
if (typeof spaceId !== 'string' || !spaceId) {
|
|
526
|
-
throw new Error('Keyring record account pointer is missing its spaceId.');
|
|
527
|
-
}
|
|
528
|
-
if (typeof host !== 'string' || !host) {
|
|
529
|
-
throw new Error('Keyring record account pointer is missing its host.');
|
|
530
|
-
}
|
|
531
|
-
if (did !== undefined && (typeof did !== 'string' || !did)) {
|
|
532
|
-
throw new Error('Keyring record account pointer has a malformed did.');
|
|
533
|
-
}
|
|
534
|
-
return { ...(did ? { did } : {}), spaceId, host };
|
|
535
|
-
}
|
|
536
290
|
//# sourceMappingURL=record.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/keyring/record.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/keyring/record.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EACL,gCAAgC,EAChC,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,2BAA2B,CAAA;AAElC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAM1E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,qBAAqB,CAAA;AAoB5B;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,QAAQ,EAQT;IACC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC7D,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAA;IAC9D,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAA;IACnC,OAAO;QACL,YAAY;QACZ,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAwB;YACvC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;YAC7C,uEAAuE;YACvE,qEAAqE;YACrE,OAAO,IAAI,UAAU,CACnB,SAAS,CAAC,MAAM,EAChB,SAAS,CAAC,UAAU,EACpB,SAAS,CAAC,UAAU,CACrB,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EACzC,IAAI,EAGL;IACC,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/D,OAAO,qBAAqB,CAAC;QAC3B,QAAQ,EAAE;YACR,EAAE,EAAE,WAAW,OAAO,CAAC,kBAAkB,EAAE;YAC3C,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE;SACxC;KACF,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EACpC,OAAO,EACP,UAAU,EACV,OAAO,EACP,MAAM,EACN,OAAO,EAOR;IACC,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAA;IAClE,MAAM,aAAa,GAAG,gCAAgC,CAAC;QACrD,kBAAkB,EAAE,WAAW,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,EAAE;KAC5E,CAAC,CAAA;IACF,MAAM,KAAK,GAAG,MAAM,sBAAsB;IACxC,0EAA0E;IAC1E,oEAAoE;IACpE,qDAAqD;IACrD,KAAoC,EACpC,aAAa,EACb,qBAAqB,CAAC;QACpB,kBAAkB,EAAE,MAAM,CAAC,YAAY;QACvC,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAC,CACH,CAAA;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAoB,EAAE,CAAA;AAClD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,kBAAkB,EAClB,KAAK,EAIN;IACC,MAAM,YAAY,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAA;IACrD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,gBAAgB,CACxB,OAAO,KAAK,0DAA0D;YACpE,WAAW,CACd,CAAA;IACH,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,MAAM,EACN,oBAAoB,EACpB,KAAK,GAAG,SAAS,EAKlB;IACC,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,gBAAgB,CAAC,aAAa,KAAK,UAAU,CAAC,CAAA;IAC1D,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,MAA6B,CAAA;IACzD,MAAM,OAAO,GAAG,qBAAqB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;IACvD,MAAM,YAAY,GAAG,uBAAuB,CAAC;QAC3C,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,KAAK;KACN,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,CAAC,OAAO,oBAAoB,KAAK,QAAQ;QACvC,CAAC,CAAC,CAAC,oBAAoB,CAAC;QACxB,CAAC,CAAC,oBAAoB,CACvB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAC7C,CAAA;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,gBAAgB,CACxB,OAAO,KAAK,yDAAyD;YACnE,YAAY,YAAY,KAAK,CAChC,CAAA;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,iBAAiB,CACrB,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,OAAO,EAA6C,EACvE;YACE,QAAQ,EAAE,uBAAuB;YACjC,8DAA8D;YAC9D,oEAAoE;YACpE,4DAA4D;YAC5D,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;YACnB,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC;SAC9D,CACF,CAAA;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,gBAAgB,CACxB,OAAO,KAAK,oDAAoD,EAChE,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAA;IACH,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,EACtC,UAAU,EACV,KAAK,EACL,OAAO,EACP,eAAe,EACf,MAAM,EACN,SAAS,EAQV;IACC,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,EAAE,eAAe,EAAE,CAAC,CAAA;IAClE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAA;IACrD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QACxC,IAAI,EAAE;YACJ,UAAU;YACV,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,OAAO;gBACT,CAAC,CAAC;oBACE,OAAO,EAAE;wBACP,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC5C,OAAO,EAAE,OAAO,CAAC,OAAO;wBACxB,IAAI,EAAE,OAAO,CAAC,IAAI;qBACnB;iBACF;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,SAAS,EAAE,oBAAoB,CAAC,EAAE,SAAS,EAAE,CAAC;SAC/C;KACF,CAAC,CAAA;IACF,OAAO,eAAe,CAAC;QACrB,OAAO,EAAE,sBAAsB;QAC/B,UAAU;QACV,OAAO,EAAE,QAAQ;QACjB,MAAM;KACP,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EACxC,MAAM,EACN,eAAe,EACf,WAAW,EACX,oBAAoB,EAMrB;IACC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAAC;QAC/C,MAAM;QACN,KAAK,EAAE,SAAS;KACjB,CAAC,CAAA;IACF,MAAM,iBAAiB,CAAC;QACtB,MAAM;QACN,oBAAoB,EAAE,oBAAoB;QAC1C,KAAK,EAAE,SAAS;KACjB,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;QAChC,eAAe;QACf,WAAW;QACX,UAAU;KACX,CAAC,CAAA;IACF,MAAM,SAAS,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC;QACtC,EAAE,EAAE,gBAAgB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACnD,QAAQ,EAAE,OAAgB;KAC3B,CAAC,CAKD,CAAA;IAED,IAAI,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;IACrD,MAAM,SAAS,GAAG,oBAAoB,CAAC;QACrC,KAAK,EAAE,SAAS,CAAC,SAAS;QAC1B,KAAK,EAAE,SAAS;KACjB,CAAC,CAAA;IAEF,OAAO;QACL,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,SAAS;QACT,gEAAgE;QAChE,oCAAoC;QACpC,GAAG,CAAC,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,KAAK;YACxD,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE;YAC5B,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The record envelope: the `{ version, encryption, wrapped }` frame every
|
|
6
|
+
* sealed record shares, without its authenticity layer. It mints the record's
|
|
7
|
+
* one-epoch descriptor, builds the sealing and reading ciphers over it, reads
|
|
8
|
+
* the envelope's addressed id, validates a stored frame's shape, and parses the
|
|
9
|
+
* keyring plaintext's members.
|
|
10
|
+
*
|
|
11
|
+
* The wrap is an EDV document envelope sealed under the record's own key
|
|
12
|
+
* epoch: every EDV envelope seals to an epoch key, so the record carries its
|
|
13
|
+
* one-epoch descriptor in its `encryption` member, epoch[0] wrapped to the
|
|
14
|
+
* unlock key-agreement key. The record stays self-contained -- unlock KAK in,
|
|
15
|
+
* contents out. The cipher's `keyring` collection context labels errors only
|
|
16
|
+
* (the codec is agnostic to it).
|
|
17
|
+
*
|
|
18
|
+
* This file's runtime imports are was-client's EDV subpath and the system
|
|
19
|
+
* collections leaf, and they stay that way. A consumer that opens sealed
|
|
20
|
+
* records offline loads it without the signing and did:webvh graph.
|
|
21
|
+
* Signing and verifying the frame's `proof` member is `record.ts`, which
|
|
22
|
+
* imports this file; nothing here imports it back.
|
|
23
|
+
*/
|
|
24
|
+
import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
|
|
25
|
+
import type { CollectionEncryption } from '@interop/was-client';
|
|
26
|
+
import { type DocCipher } from '@interop/was-client/edv/cipher';
|
|
27
|
+
/**
|
|
28
|
+
* The version stamped on the stored `{ version, encryption, wrapped, proof }`
|
|
29
|
+
* keyring envelope: the signed record, whose envelope seals under the record's
|
|
30
|
+
* own key epoch (the `encryption` member) and whose sibling members carry a
|
|
31
|
+
* Data Integrity proof by the unlock identity's signing key. Any other version
|
|
32
|
+
* is refused as unusable -- such accounts are re-provisioned, not migrated.
|
|
33
|
+
*/
|
|
34
|
+
export declare const KEYRING_RECORD_VERSION = 2;
|
|
35
|
+
/**
|
|
36
|
+
* The fixed proof shape a signed record carries: an eddsa-jcs-2022 Data
|
|
37
|
+
* Integrity proof over the record's sibling members, `assertionMethod`
|
|
38
|
+
* purpose, with the signing key named by a `did:key:<multibase>#<multibase>`
|
|
39
|
+
* verification method.
|
|
40
|
+
*/
|
|
41
|
+
export interface RecordProof {
|
|
42
|
+
type: 'DataIntegrityProof';
|
|
43
|
+
cryptosuite: 'eddsa-jcs-2022';
|
|
44
|
+
verificationMethod: string;
|
|
45
|
+
proofPurpose: 'assertionMethod';
|
|
46
|
+
created?: string;
|
|
47
|
+
proofValue: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A stored signed record: the frame members the proof secures, plus the proof
|
|
51
|
+
* itself.
|
|
52
|
+
*/
|
|
53
|
+
export interface SignedRecord {
|
|
54
|
+
version: number;
|
|
55
|
+
encryption: CollectionEncryption;
|
|
56
|
+
wrapped: unknown;
|
|
57
|
+
proof: RecordProof;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A record's proof is absent, malformed, signed by a key this client does not
|
|
61
|
+
* accept, or does not verify over the record's own members. Its own class,
|
|
62
|
+
* distinct from a decrypt failure or an unusable-version refusal: this is the
|
|
63
|
+
* refusal that says the storage host forged or tampered with the record, which
|
|
64
|
+
* an app maps to its own login copy.
|
|
65
|
+
*/
|
|
66
|
+
export declare class RecordProofError extends Error {
|
|
67
|
+
constructor(message: string, options?: {
|
|
68
|
+
cause?: unknown;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Checks the shape of a record's `proof` member against the fixed shape.
|
|
73
|
+
* Verifies nothing: no cryptography runs here, so a match says only that
|
|
74
|
+
* the member could be a proof, not that it is genuine.
|
|
75
|
+
*
|
|
76
|
+
* @param options {object}
|
|
77
|
+
* @param options.proof {unknown}
|
|
78
|
+
* @param options.label {string} names the record kind in the refusal
|
|
79
|
+
* @returns {RecordProof}
|
|
80
|
+
*/
|
|
81
|
+
export declare function checkRecordProofShape({ proof, label }: {
|
|
82
|
+
proof: unknown;
|
|
83
|
+
label: string;
|
|
84
|
+
}): RecordProof;
|
|
85
|
+
/**
|
|
86
|
+
* Mints the one-epoch descriptor a fresh record is sealed under: epoch[0]
|
|
87
|
+
* wrapped to the given KAK alone, built through `initRecipients` against a
|
|
88
|
+
* throwaway in-memory store (the descriptor's home is the record itself).
|
|
89
|
+
* Exported for any consumer sealing a self-contained
|
|
90
|
+
* `{ version, encryption, wrapped }` record -- the keyring and recovery
|
|
91
|
+
* records here, and a wallet app's own locally stored records (e.g.
|
|
92
|
+
* freewallet's client-key record and unlock-methods registry).
|
|
93
|
+
*
|
|
94
|
+
* @param options {object}
|
|
95
|
+
* @param options.keyAgreementKey {IKeyAgreementKey} the wrapping KAK (for
|
|
96
|
+
* the keyring record, the unlock KAK)
|
|
97
|
+
* @returns {Promise<CollectionEncryption>}
|
|
98
|
+
*/
|
|
99
|
+
export declare function mintRecordEncryption({ keyAgreementKey }: {
|
|
100
|
+
keyAgreementKey: IKeyAgreementKey;
|
|
101
|
+
}): Promise<CollectionEncryption>;
|
|
102
|
+
/**
|
|
103
|
+
* Builds the record's reading cipher: an EDV cipher over the record's own
|
|
104
|
+
* descriptor, from the reader's key-agreement key. The unwrap paths' cipher
|
|
105
|
+
* (and the recovery record's, which reuses the keyring cipher context
|
|
106
|
+
* verbatim); the wrap paths seal through {@link recordSealCipher} instead. An
|
|
107
|
+
* app's own record kind passes its own `collectionId` so its failures name
|
|
108
|
+
* the record kind. The context labels errors only -- the codec is agnostic to
|
|
109
|
+
* it, so a record kind's real swap protection is its contents validation on
|
|
110
|
+
* unwrap.
|
|
111
|
+
*
|
|
112
|
+
* @param options {object}
|
|
113
|
+
* @param options.keyAgreementKey {IKeyAgreementKey} the wrapping KAK (for
|
|
114
|
+
* the keyring record, the unlock KAK)
|
|
115
|
+
* @param options.keyResolver {IKeyResolver}
|
|
116
|
+
* @param options.encryption {CollectionEncryption} the record's descriptor
|
|
117
|
+
* @param [options.collectionId] {string} the cipher context failures are
|
|
118
|
+
* labeled with; defaults to the keyring context
|
|
119
|
+
* @returns {Promise<DocCipher>}
|
|
120
|
+
*/
|
|
121
|
+
export declare function recordCipher({ keyAgreementKey, keyResolver, encryption, collectionId }: {
|
|
122
|
+
keyAgreementKey: IKeyAgreementKey;
|
|
123
|
+
keyResolver: IKeyResolver;
|
|
124
|
+
encryption: CollectionEncryption;
|
|
125
|
+
collectionId?: string;
|
|
126
|
+
}): Promise<DocCipher>;
|
|
127
|
+
/**
|
|
128
|
+
* Builds the record's sealing cipher: an encrypt-only EDV cipher over the
|
|
129
|
+
* record's own descriptor, needing no key-agreement secret -- a write seals to
|
|
130
|
+
* the descriptor's epoch public key, reconstructed from the epoch id. This is
|
|
131
|
+
* what lets the recovery re-mint, which holds only the code's unlock KAK
|
|
132
|
+
* public half, re-seal a record it can never open; the issuance wraps go
|
|
133
|
+
* through the same construction and produce the same envelope shape. Decrypt
|
|
134
|
+
* on it refuses with was-client's typed `EncryptOnlyCipherError`.
|
|
135
|
+
*
|
|
136
|
+
* @param options {object}
|
|
137
|
+
* @param options.encryption {CollectionEncryption} the record's descriptor
|
|
138
|
+
* @param [options.collectionId] {string} the cipher context failures are
|
|
139
|
+
* labeled with; defaults to the keyring context
|
|
140
|
+
* @returns {Promise<DocCipher>}
|
|
141
|
+
*/
|
|
142
|
+
export declare function recordSealCipher({ encryption, collectionId }: {
|
|
143
|
+
encryption: CollectionEncryption;
|
|
144
|
+
collectionId?: string;
|
|
145
|
+
}): Promise<DocCipher>;
|
|
146
|
+
/**
|
|
147
|
+
* Reads the addressed id a stored record envelope must be decrypted under.
|
|
148
|
+
*
|
|
149
|
+
* A record's members seal through {@link recordSealCipher}, which builds on
|
|
150
|
+
* was-client's default content-derived id mode: the id does not exist until
|
|
151
|
+
* after encryption, so the codec computes it from the JWE ciphertext and
|
|
152
|
+
* stamps it onto the cleartext envelope afterwards. That stamped member is
|
|
153
|
+
* the only value {@link recordCipher}'s decrypt accepts -- the record's own
|
|
154
|
+
* well-known resource id does not verify, and the sealed members of an unlock
|
|
155
|
+
* record have no resource id of their own at all.
|
|
156
|
+
*
|
|
157
|
+
* The check this id feeds is therefore inert here, and deliberately so. In
|
|
158
|
+
* content-derived mode the id is a hash of the ciphertext, so a substituted
|
|
159
|
+
* envelope carries a matching stamp and the comparison always passes. It
|
|
160
|
+
* detects corruption rather than substitution. A record's protection against a
|
|
161
|
+
* substituting storage host is the frame's `eddsa-jcs-2022` proof over
|
|
162
|
+
* `wrapped` and every sealed member, verified by `record.ts`'s
|
|
163
|
+
* `verifyRecordProof` before any unwrap path decrypts. Do not read this id
|
|
164
|
+
* as a security boundary.
|
|
165
|
+
*
|
|
166
|
+
* @param options {object}
|
|
167
|
+
* @param options.wrapped {unknown} the stored envelope
|
|
168
|
+
* @param options.label {string} `'keyring'`, `'recovery'`, or an app record
|
|
169
|
+
* kind's own label, naming the refusal
|
|
170
|
+
* @returns {string} the envelope's addressed id
|
|
171
|
+
*/
|
|
172
|
+
export declare function recordEnvelopeId({ wrapped, label }: {
|
|
173
|
+
wrapped: unknown;
|
|
174
|
+
label: string;
|
|
175
|
+
}): string;
|
|
176
|
+
/**
|
|
177
|
+
* Validates the common `{ version, encryption, wrapped }` frame of a stored
|
|
178
|
+
* record (keyring or recovery -- `label` names the refusals) and returns its
|
|
179
|
+
* members, the `proof` among them for the signed frame. Exported so an app's
|
|
180
|
+
* own record kinds open their records through the same frame validation the
|
|
181
|
+
* codec here seals with, rather than re-deriving the version and shape checks.
|
|
182
|
+
*
|
|
183
|
+
* A frame at the keyring record version is the signed frame, so it must carry
|
|
184
|
+
* a fixed-shape proof; a record kind stamping its own version is unaffected
|
|
185
|
+
* (its authenticity story is its own). Validating the shape here does not
|
|
186
|
+
* verify it -- `record.ts`'s `verifyRecordProof` does, and every unwrap path
|
|
187
|
+
* there runs it before decrypting.
|
|
188
|
+
*
|
|
189
|
+
* @param options {object}
|
|
190
|
+
* @param options.record {unknown}
|
|
191
|
+
* @param options.label {string} `'keyring'`, `'recovery'`, or an app record
|
|
192
|
+
* kind's own label
|
|
193
|
+
* @param [options.version] {number} the version the frame must carry;
|
|
194
|
+
* defaults to the keyring record version
|
|
195
|
+
* @returns {{ encryption: CollectionEncryption, wrapped: unknown,
|
|
196
|
+
* proof?: RecordProof }}
|
|
197
|
+
*/
|
|
198
|
+
export declare function parseRecordFrame({ record, label, version }: {
|
|
199
|
+
record: unknown;
|
|
200
|
+
label: string;
|
|
201
|
+
version?: number;
|
|
202
|
+
}): {
|
|
203
|
+
encryption: CollectionEncryption;
|
|
204
|
+
wrapped: unknown;
|
|
205
|
+
proof?: RecordProof;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* The account pointer a keyring record carries in place of the retired data
|
|
209
|
+
* seed: where the account lives (`spaceId` + `host`, the WAS server's base
|
|
210
|
+
* URL, which carries a base path when the server is deployed under a
|
|
211
|
+
* sub-path) and, once provisioning has published it, the account's stable
|
|
212
|
+
* did:webvh id. Discovery only -- holding the pointer authorizes nothing.
|
|
213
|
+
*/
|
|
214
|
+
export interface AccountPointer {
|
|
215
|
+
did?: string;
|
|
216
|
+
spaceId: string;
|
|
217
|
+
host: string;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* The unwrapped contents of a keyring record: the account controller (the
|
|
221
|
+
* first enrolled client's did:key today), the account email captured at bind
|
|
222
|
+
* time (when one was given -- carried so any unlock method recovers it; a
|
|
223
|
+
* passkey login has no login form to ask on), and the account pointer (absent
|
|
224
|
+
* only on no-WAS deployments, where there is no Space to point at).
|
|
225
|
+
*/
|
|
226
|
+
export interface KeyringRecordContents {
|
|
227
|
+
controller: string;
|
|
228
|
+
email?: string;
|
|
229
|
+
pointer?: AccountPointer;
|
|
230
|
+
createdAt: string;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The bind timestamp a wrap path stamps into a record's plaintext: the
|
|
234
|
+
* caller's, validated as a parseable ISO timestamp, or now. A caller supplies
|
|
235
|
+
* one when it pins record freshness, so it knows the stamp of the record it is
|
|
236
|
+
* writing without reading it back.
|
|
237
|
+
*
|
|
238
|
+
* @param options {object}
|
|
239
|
+
* @param [options.createdAt] {string} the caller's timestamp
|
|
240
|
+
* @returns {string}
|
|
241
|
+
*/
|
|
242
|
+
export declare function recordCreatedAtStamp({ createdAt }: {
|
|
243
|
+
createdAt?: string;
|
|
244
|
+
}): string;
|
|
245
|
+
/**
|
|
246
|
+
* Parses and validates the required `createdAt` member of a record plaintext:
|
|
247
|
+
* the moment the record was bound, as an ISO timestamp that must parse. Apps
|
|
248
|
+
* pin freshness on it, so a record that cannot state its own bind time is
|
|
249
|
+
* refused rather than defaulted.
|
|
250
|
+
*
|
|
251
|
+
* @param options {object}
|
|
252
|
+
* @param options.value {unknown} the plaintext's `createdAt` member
|
|
253
|
+
* @param options.label {string} names the record kind in the refusal
|
|
254
|
+
* @returns {string}
|
|
255
|
+
*/
|
|
256
|
+
export declare function parseRecordCreatedAt({ value, label }: {
|
|
257
|
+
value: unknown;
|
|
258
|
+
label: string;
|
|
259
|
+
}): string;
|
|
260
|
+
/**
|
|
261
|
+
* Parses and validates the optional `pointer` member of a keyring record
|
|
262
|
+
* plaintext. An absent member is a no-WAS record (returns undefined); a
|
|
263
|
+
* present-but-malformed one throws -- a record that claims a pointer but
|
|
264
|
+
* cannot state where the account lives is unusable.
|
|
265
|
+
*
|
|
266
|
+
* @param value {unknown} the record's `pointer` member
|
|
267
|
+
* @returns {AccountPointer | undefined}
|
|
268
|
+
*/
|
|
269
|
+
export declare function parseRecordPointer(value: unknown): AccountPointer | undefined;
|
|
270
|
+
//# sourceMappingURL=recordEnvelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recordEnvelope.d.ts","sourceRoot":"","sources":["../../src/keyring/recordEnvelope.ts"],"names":[],"mappings":"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"}
|