@did-btcr2/method 0.43.0 → 0.44.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.
@@ -24,6 +24,15 @@ export const BTCR2_DID_DOCUMENT_CONTEXT = [
24
24
  'https://www.w3.org/ns/did/v1.1',
25
25
  'https://btcr2.dev/context/v1',
26
26
  ];
27
+
28
+ /** The `type` every did:btcr2 verification method must declare. */
29
+ export const MULTIKEY_VERIFICATION_METHOD_TYPE = 'Multikey';
30
+
31
+ /**
32
+ * The multibase prefix of a did:btcr2 verification method's `publicKeyMultibase`.
33
+ * `zQ3s` is the multibase-base58btc encoding of a Schnorr secp256k1 public key.
34
+ */
35
+ export const MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX = 'zQ3s';
27
36
  export const ID_PLACEHOLDER_VALUE = 'did:btcr2:_';
28
37
  export const BECH32M_CHARS = '';
29
38
  export const DID_REGEX = /did:btcr2:(x1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]*)/g;
@@ -56,6 +65,33 @@ export interface Btcr2VerificationMethod extends W3CDidVerificationMethod {
56
65
  secretKeyMultibase?: string | undefined;
57
66
  }
58
67
 
68
+ /**
69
+ * Determines whether a value is a valid did:btcr2 verification method.
70
+ *
71
+ * Beyond the structural id/type/controller shape, a btcr2 verification method is
72
+ * a {@link MULTIKEY_VERIFICATION_METHOD_TYPE | Multikey} whose public key is a
73
+ * Schnorr secp256k1 key, multibase-encoded with the
74
+ * {@link MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX | zQ3s} prefix. This is the single
75
+ * source of truth for that invariant: it is enforced both when a
76
+ * {@link DidVerificationMethod} is constructed and when a {@link DidDocument}'s
77
+ * `verificationMethod` array is validated, rather than only for the one method
78
+ * being signed with at update time.
79
+ *
80
+ * @param {unknown} vm The value to check.
81
+ * @returns {boolean} True if `vm` is a Multikey verification method with a zQ3s key.
82
+ */
83
+ export function isMultikeyVerificationMethod(vm: unknown): boolean {
84
+ if(!Appendix.isDidVerificationMethod(vm)) {
85
+ return false;
86
+ }
87
+ // `vm` is a structurally-valid verification method; check the btcr2 Multikey
88
+ // invariant on the raw fields (the public key is unconstrained by the guard).
89
+ const { type, publicKeyMultibase } = vm as { type: unknown; publicKeyMultibase: unknown };
90
+ return type === MULTIKEY_VERIFICATION_METHOD_TYPE
91
+ && typeof publicKeyMultibase === 'string'
92
+ && publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX);
93
+ }
94
+
59
95
  /**
60
96
  * DID BTCR2 Verification Method extends the DidVerificationMethod class adding helper methods and properties
61
97
  * @class DidVerificationMethod
@@ -70,6 +106,21 @@ export class DidVerificationMethod implements Btcr2VerificationMethod {
70
106
  secretKeyMultibase?: string | undefined;
71
107
 
72
108
  constructor({ id, type, controller, publicKeyMultibase, secretKeyMultibase }: Btcr2VerificationMethod) {
109
+ // A btcr2 verification method must be a Multikey carrying a Schnorr secp256k1
110
+ // public key (zQ3s multibase prefix). Enforce it here so the invariant holds
111
+ // wherever a verification method is constructed, not only at update time.
112
+ if(type !== MULTIKEY_VERIFICATION_METHOD_TYPE) {
113
+ throw new DidDocumentError(
114
+ `Invalid verification method: type must be "${MULTIKEY_VERIFICATION_METHOD_TYPE}"`,
115
+ INVALID_DID_DOCUMENT, { id, type }
116
+ );
117
+ }
118
+ if(typeof publicKeyMultibase !== 'string' || !publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX)) {
119
+ throw new DidDocumentError(
120
+ `Invalid verification method: publicKeyMultibase must start with "${MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX}"`,
121
+ INVALID_DID_DOCUMENT, { id, publicKeyMultibase }
122
+ );
123
+ }
73
124
  this.id = id;
74
125
  this.type = type;
75
126
  this.controller = controller;
@@ -305,10 +356,12 @@ export class DidDocument implements Btcr2DidDocument {
305
356
  * @returns {boolean} True if the context is valid.
306
357
  */
307
358
  private static isValidContext(context: unknown): boolean {
308
- if(!context) return false;
309
- if(!Array.isArray(context)) return false;
310
- if(!context.every(ctx => typeof ctx === 'string' && BTCR2_DID_DOCUMENT_CONTEXT.includes(ctx))) return false;
311
- return true;
359
+ // "@context" must be a non-empty array of context entries.
360
+ if(!Array.isArray(context) || context.length === 0) return false;
361
+ // The btcr2 base contexts must all be present. Additional proof-suite or
362
+ // extension contexts (string or inline object) are permitted per W3C DID
363
+ // Core 4.1 and are no longer rejected by a strict whitelist.
364
+ return BTCR2_DID_DOCUMENT_CONTEXT.every(required => context.includes(required));
312
365
  }
313
366
 
314
367
  /**
@@ -334,7 +387,7 @@ export class DidDocument implements Btcr2DidDocument {
334
387
  * @returns {boolean} True if the verification methods are valid.
335
388
  */
336
389
  private static isValidVerificationMethods(verificationMethod: unknown): boolean {
337
- return Array.isArray(verificationMethod) && verificationMethod.every(Appendix.isDidVerificationMethod);
390
+ return Array.isArray(verificationMethod) && verificationMethod.every(isMultikeyVerificationMethod);
338
391
  }
339
392
 
340
393
  /**