@bcts/xid 1.0.0-alpha.12 → 1.0.0-alpha.13

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.
@@ -6,14 +6,7 @@
6
6
  * Ported from bc-xid-rust/src/xid_document.rs
7
7
  */
8
8
 
9
- import {
10
- Envelope,
11
- PrivateKeyBase,
12
- type PublicKeyBase,
13
- type EnvelopeEncodable,
14
- type Signer,
15
- type EnvelopeEncodableValue,
16
- } from "@bcts/envelope";
9
+ import { Envelope, type EnvelopeEncodable, type EnvelopeEncodableValue } from "@bcts/envelope";
17
10
  import {
18
11
  KEY,
19
12
  DELEGATE,
@@ -25,7 +18,14 @@ import {
25
18
 
26
19
  // Helper to convert KnownValue to EnvelopeEncodableValue
27
20
  const kv = (v: KnownValue): EnvelopeEncodableValue => v as unknown as EnvelopeEncodableValue;
28
- import { Reference, XID } from "@bcts/components";
21
+ import {
22
+ Reference,
23
+ XID,
24
+ type PublicKeys,
25
+ PrivateKeyBase,
26
+ type PrivateKeys,
27
+ type Signer,
28
+ } from "@bcts/components";
29
29
  import {
30
30
  type ProvenanceMark,
31
31
  ProvenanceMarkGenerator,
@@ -38,7 +38,6 @@ import { Delegate, registerXIDDocumentClass } from "./delegate";
38
38
  import { Service } from "./service";
39
39
  import { Provenance, XIDGeneratorOptions, type XIDGeneratorOptionsValue } from "./provenance";
40
40
  import { XIDError } from "./error";
41
-
42
41
  // Raw values for predicate matching
43
42
  const KEY_RAW = KEY.value();
44
43
  const DELEGATE_RAW = DELEGATE.value();
@@ -51,8 +50,9 @@ const DEREFERENCE_VIA_RAW = DEREFERENCE_VIA.value();
51
50
  */
52
51
  export type XIDInceptionKeyOptions =
53
52
  | { type: "default" }
54
- | { type: "publicKeyBase"; publicKeyBase: PublicKeyBase }
55
- | { type: "privateKeyBase"; privateKeyBase: PrivateKeyBase };
53
+ | { type: "publicKeys"; publicKeys: PublicKeys }
54
+ | { type: "privateKeyBase"; privateKeyBase: PrivateKeyBase }
55
+ | { type: "privateKeys"; privateKeys: PrivateKeys; publicKeys: PublicKeys };
56
56
 
57
57
  /**
58
58
  * Options for creating the genesis mark.
@@ -80,7 +80,8 @@ export type XIDGenesisMarkOptions =
80
80
  export type XIDSigningOptions =
81
81
  | { type: "none" }
82
82
  | { type: "inception" }
83
- | { type: "privateKeyBase"; privateKeyBase: PrivateKeyBase };
83
+ | { type: "privateKeyBase"; privateKeyBase: PrivateKeyBase }
84
+ | { type: "privateKeys"; privateKeys: PrivateKeys };
84
85
 
85
86
  /**
86
87
  * Options for verifying the signature on an envelope when loading.
@@ -134,7 +135,9 @@ export class XIDDocument implements EnvelopeEncodable {
134
135
  const inceptionKey = XIDDocument.inceptionKeyForOptions(keyOptions);
135
136
  const provenance = XIDDocument.genesisMarkWithOptions(markOptions);
136
137
 
137
- const xid = XID.from(hashPublicKey(inceptionKey.publicKeyBase()));
138
+ // Use the reference from PublicKeys (which uses tagged CBOR hash)
139
+ // XID is created from the digest data of the reference
140
+ const xid = XID.from(inceptionKey.publicKeys().reference().getDigest().toData());
138
141
  const doc = new XIDDocument(xid, new Set(), new Map(), new Map(), new Map(), provenance);
139
142
 
140
143
  doc.addKey(inceptionKey);
@@ -144,13 +147,15 @@ export class XIDDocument implements EnvelopeEncodable {
144
147
  private static inceptionKeyForOptions(options: XIDInceptionKeyOptions): Key {
145
148
  switch (options.type) {
146
149
  case "default": {
147
- const privateKeyBase = PrivateKeyBase.generate();
150
+ const privateKeyBase = PrivateKeyBase.new();
148
151
  return Key.newWithPrivateKeyBase(privateKeyBase);
149
152
  }
150
- case "publicKeyBase":
151
- return Key.newAllowAll(options.publicKeyBase);
153
+ case "publicKeys":
154
+ return Key.newAllowAll(options.publicKeys);
152
155
  case "privateKeyBase":
153
156
  return Key.newWithPrivateKeyBase(options.privateKeyBase);
157
+ case "privateKeys":
158
+ return Key.newWithPrivateKeys(options.privateKeys, options.publicKeys);
154
159
  }
155
160
  }
156
161
 
@@ -229,10 +234,10 @@ export class XIDDocument implements EnvelopeEncodable {
229
234
  }
230
235
 
231
236
  /**
232
- * Find a key by its public key base.
237
+ * Find a key by its public keys.
233
238
  */
234
- findKeyByPublicKeyBase(publicKeyBase: PublicKeyBase): Key | undefined {
235
- const hashKey = publicKeyBase.hex();
239
+ findKeyByPublicKeys(publicKeys: PublicKeys): Key | undefined {
240
+ const hashKey = publicKeys.reference().toHex();
236
241
  return this._keys.get(hashKey);
237
242
  }
238
243
 
@@ -251,8 +256,8 @@ export class XIDDocument implements EnvelopeEncodable {
251
256
  /**
252
257
  * Take and remove a key.
253
258
  */
254
- takeKey(publicKeyBase: PublicKeyBase): Key | undefined {
255
- const hashKey = publicKeyBase.hex();
259
+ takeKey(publicKeys: PublicKeys): Key | undefined {
260
+ const hashKey = publicKeys.reference().toHex();
256
261
  const key = this._keys.get(hashKey);
257
262
  if (key !== undefined) {
258
263
  this._keys.delete(hashKey);
@@ -263,22 +268,23 @@ export class XIDDocument implements EnvelopeEncodable {
263
268
  /**
264
269
  * Remove a key.
265
270
  */
266
- removeKey(publicKeyBase: PublicKeyBase): void {
267
- if (this.servicesReferenceKey(publicKeyBase)) {
271
+ removeKey(publicKeys: PublicKeys): void {
272
+ if (this.servicesReferenceKey(publicKeys)) {
268
273
  throw XIDError.stillReferenced("key");
269
274
  }
270
- const hashKey = publicKeyBase.hex();
275
+ const hashKey = publicKeys.reference().toHex();
271
276
  if (!this._keys.delete(hashKey)) {
272
277
  throw XIDError.notFound("key");
273
278
  }
274
279
  }
275
280
 
276
281
  /**
277
- * Check if the given public key is the inception signing key.
282
+ * Check if the given public keys is the inception signing key.
278
283
  */
279
- isInceptionKey(publicKeyBase: PublicKeyBase): boolean {
280
- const xidData = hashPublicKey(publicKeyBase);
281
- return bytesEqual(xidData, this._xid.toData());
284
+ isInceptionKey(publicKeys: PublicKeys): boolean {
285
+ // The XID is derived from the reference of the inception PublicKeys
286
+ const xidReference = publicKeys.reference();
287
+ return bytesEqual(xidReference.getDigest().toData(), this._xid.toData());
282
288
  }
283
289
 
284
290
  /**
@@ -286,7 +292,7 @@ export class XIDDocument implements EnvelopeEncodable {
286
292
  */
287
293
  inceptionKey(): Key | undefined {
288
294
  for (const key of this._keys.values()) {
289
- if (this.isInceptionKey(key.publicKeyBase())) {
295
+ if (this.isInceptionKey(key.publicKeys())) {
290
296
  return key;
291
297
  }
292
298
  }
@@ -294,10 +300,10 @@ export class XIDDocument implements EnvelopeEncodable {
294
300
  }
295
301
 
296
302
  /**
297
- * Get the inception private key base, if available.
303
+ * Get the inception private keys, if available.
298
304
  */
299
- inceptionPrivateKeyBase(): PrivateKeyBase | undefined {
300
- return this.inceptionKey()?.privateKeyBase();
305
+ inceptionPrivateKeys(): PrivateKeys | undefined {
306
+ return this.inceptionKey()?.privateKeys();
301
307
  }
302
308
 
303
309
  /**
@@ -448,16 +454,16 @@ export class XIDDocument implements EnvelopeEncodable {
448
454
  }
449
455
 
450
456
  for (const keyRef of service.keyReferences()) {
451
- const refBytes = hexToBytes(keyRef);
452
- const ref = Reference.hash(refBytes);
457
+ // keyRef is already a hex representation of a Reference, don't hash again
458
+ const ref = Reference.fromHex(keyRef);
453
459
  if (this.findKeyByReference(ref) === undefined) {
454
460
  throw XIDError.unknownKeyReference(keyRef, service.uri());
455
461
  }
456
462
  }
457
463
 
458
464
  for (const delegateRef of service.delegateReferences()) {
459
- const refBytes = hexToBytes(delegateRef);
460
- const ref = Reference.hash(refBytes);
465
+ // delegateRef is already a hex representation of a Reference, don't hash again
466
+ const ref = Reference.fromHex(delegateRef);
461
467
  if (this.findDelegateByReference(ref) === undefined) {
462
468
  throw XIDError.unknownDelegateReference(delegateRef, service.uri());
463
469
  }
@@ -471,8 +477,8 @@ export class XIDDocument implements EnvelopeEncodable {
471
477
  /**
472
478
  * Check if any service references the given key.
473
479
  */
474
- servicesReferenceKey(publicKeyBase: PublicKeyBase): boolean {
475
- const keyRef = Reference.hash(publicKeyBase.data()).toHex();
480
+ servicesReferenceKey(publicKeys: PublicKeys): boolean {
481
+ const keyRef = publicKeys.reference().toHex();
476
482
  for (const service of this._services.values()) {
477
483
  if (service.keyReferences().has(keyRef)) {
478
484
  return true;
@@ -627,27 +633,33 @@ export class XIDDocument implements EnvelopeEncodable {
627
633
  );
628
634
  }
629
635
 
630
- // Apply signing
636
+ // Apply signing (uses sign() which wraps the envelope first)
637
+ // PrivateKeys implements Signer from @bcts/components, which is compatible with envelope's sign()
631
638
  switch (signingOptions.type) {
632
639
  case "inception": {
633
640
  const inceptionKey = this.inceptionKey();
634
641
  if (inceptionKey === undefined) {
635
642
  throw XIDError.missingInceptionKey();
636
643
  }
637
- const privateKeyBase = inceptionKey.privateKeyBase();
638
- if (privateKeyBase === undefined) {
644
+ const privateKeys = inceptionKey.privateKeys();
645
+ if (privateKeys === undefined) {
639
646
  throw XIDError.missingInceptionKey();
640
647
  }
641
- envelope = (envelope as unknown as { addSignature(s: Signer): Envelope }).addSignature(
642
- privateKeyBase as unknown as Signer,
643
- );
648
+ envelope = (envelope as unknown as { sign(s: Signer): Envelope }).sign(privateKeys);
644
649
  break;
645
650
  }
646
- case "privateKeyBase":
647
- envelope = (envelope as unknown as { addSignature(s: Signer): Envelope }).addSignature(
648
- signingOptions.privateKeyBase as unknown as Signer,
651
+ case "privateKeyBase": {
652
+ // Derive PrivateKeys from PrivateKeyBase and use for signing
653
+ const privateKeys = signingOptions.privateKeyBase.ed25519PrivateKeys();
654
+ envelope = (envelope as unknown as { sign(s: Signer): Envelope }).sign(privateKeys);
655
+ break;
656
+ }
657
+ case "privateKeys": {
658
+ envelope = (envelope as unknown as { sign(s: Signer): Envelope }).sign(
659
+ signingOptions.privateKeys,
649
660
  );
650
661
  break;
662
+ }
651
663
  case "none":
652
664
  default:
653
665
  break;
@@ -693,13 +705,13 @@ export class XIDDocument implements EnvelopeEncodable {
693
705
  throw XIDError.missingInceptionKey();
694
706
  }
695
707
 
696
- // Verify signature
697
- if (!envelopeExt.hasSignatureFrom(inceptionKey.publicKeyBase() as unknown as Verifier)) {
708
+ // Verify signature using the PublicKeys (implements Verifier from @bcts/components)
709
+ if (!envelopeExt.hasSignatureFrom(inceptionKey.publicKeys())) {
698
710
  throw XIDError.signatureVerificationFailed();
699
711
  }
700
712
 
701
713
  // Verify XID matches inception key
702
- if (!doc.isInceptionKey(inceptionKey.publicKeyBase())) {
714
+ if (!doc.isInceptionKey(inceptionKey.publicKeys())) {
703
715
  throw XIDError.invalidXid();
704
716
  }
705
717
 
@@ -791,7 +803,7 @@ export class XIDDocument implements EnvelopeEncodable {
791
803
  const envelope = this.toEnvelope(XIDPrivateKeyOptions.Omit, XIDGeneratorOptions.Omit, {
792
804
  type: "none",
793
805
  });
794
- return (envelope as unknown as { addSignature(s: Signer): Envelope }).addSignature(signingKey);
806
+ return (envelope as unknown as { sign(s: Signer): Envelope }).sign(signingKey);
795
807
  }
796
808
 
797
809
  /**
@@ -834,20 +846,7 @@ export class XIDDocument implements EnvelopeEncodable {
834
846
  // Register XIDDocument class with Delegate to resolve circular dependency
835
847
  registerXIDDocumentClass(XIDDocument);
836
848
 
837
- // Helper interface for Verifier
838
- interface Verifier {
839
- verify(data: Uint8Array, signature: { data(): Uint8Array }): boolean;
840
- }
841
-
842
849
  // Helper functions
843
- function hexToBytes(hex: string): Uint8Array {
844
- const bytes = new Uint8Array(hex.length / 2);
845
- for (let i = 0; i < hex.length; i += 2) {
846
- bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
847
- }
848
- return bytes;
849
- }
850
-
851
850
  function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
852
851
  if (a.length !== b.length) return false;
853
852
  for (let i = 0; i < a.length; i++) {
@@ -855,8 +854,3 @@ function bytesEqual(a: Uint8Array, b: Uint8Array): boolean {
855
854
  }
856
855
  return true;
857
856
  }
858
-
859
- function hashPublicKey(publicKeyBase: PublicKeyBase): Uint8Array {
860
- // SHA-256 hash of public key to get XID
861
- return Reference.hash(publicKeyBase.data()).getDigest().toData();
862
- }