@did-btcr2/method 0.60.0 → 0.61.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.
@@ -20,6 +20,7 @@ import type {
20
20
  SignedBTCR2Update,
21
21
  UnsignedBTCR2Update
22
22
  } from './btcr2-update.js';
23
+ import { BTCR2_UPDATE_CONTEXT, isBtcr2UpdateContext } from './btcr2-update.js';
23
24
  import {
24
25
  BIP340Cryptosuite,
25
26
  BIP340DataIntegrityProof,
@@ -608,7 +609,8 @@ export class Resolver {
608
609
  }
609
610
 
610
611
  /**
611
- * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#apply-update | 7.2.f.3 Apply Update}.
612
+ * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#apply-update | 7.2.f.3 Apply Update}
613
+ * and its step {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#check-update-proof | Check update.proof}.
612
614
  * @param {DidDocument} currentDocument The current DID Document to apply the update to.
613
615
  * @param {SignedBTCR2Update} update The BTCR2 Signed Update to apply.
614
616
  * @returns {DidDocument} The updated DID Document after applying the update.
@@ -618,6 +620,24 @@ export class Resolver {
618
620
  currentDocument: DidDocument,
619
621
  update: SignedBTCR2Update
620
622
  ): DidDocument {
623
+ // Spec "Check update.proof": the update @context must be the array that the BTCR2
624
+ // Unsigned Update data structure pins, and the proof @context must equal it, member
625
+ // for member and in order. The array is inside the hashed and signed bytes, so an
626
+ // update with another array is a different update. The check runs before signature
627
+ // verification so that the failure names the array and not the signature.
628
+ if(!isBtcr2UpdateContext(update['@context'])) {
629
+ throw new ResolveError(
630
+ 'Invalid update: @context is not the array the specification pins for a BTCR2 Update',
631
+ INVALID_DID_UPDATE, { context: update['@context'], expected: [ ...BTCR2_UPDATE_CONTEXT ] }
632
+ );
633
+ }
634
+ if(!isBtcr2UpdateContext(update.proof?.['@context'], update['@context'])) {
635
+ throw new ResolveError(
636
+ 'Invalid update: proof @context does not equal the update @context',
637
+ INVALID_DID_UPDATE, { proofContext: update.proof?.['@context'], context: update['@context'] }
638
+ );
639
+ }
640
+
621
641
  // Get the capability id from the to update proof.
622
642
  const capabilityId = update.proof?.capability;
623
643
  // Since this field is optional, check that it exists
@@ -4,6 +4,7 @@ import { canonicalHash, INVALID_DID_UPDATE, JSONPatch, UpdateError } from '@did-
4
4
  import { SchnorrMultikey } from '@did-btcr2/cryptosuite';
5
5
  import type { Signer } from '@did-btcr2/keypair';
6
6
  import type { Btcr2DataIntegrityConfig, SignedBTCR2Update, UnsignedBTCR2Update } from './btcr2-update.js';
7
+ import { BTCR2_UPDATE_CONTEXT } from './btcr2-update.js';
7
8
  import { DidDocument, type Btcr2DidDocument, type DidVerificationMethod } from '../utils/did-document.js';
8
9
  import type { BroadcastResult } from './beacon/beacon.js';
9
10
  import type { CASBroadcastOptions } from './beacon/cas-beacon.js';
@@ -214,12 +215,9 @@ export class Updater {
214
215
  sourceVersionId: number,
215
216
  ): UnsignedBTCR2Update {
216
217
  const unsignedUpdate: UnsignedBTCR2Update = {
217
- '@context' : [
218
- 'https://w3id.org/security/v2',
219
- 'https://w3id.org/zcap/v1',
220
- 'https://w3id.org/json-ld-patch/v1',
221
- 'https://btcr2.dev/context/v1'
222
- ],
218
+ // The array the specification pins, as a fresh copy: the update is a plain JSON
219
+ // object that callers may edit, and the shared constant is frozen.
220
+ '@context' : [ ...BTCR2_UPDATE_CONTEXT ],
223
221
  patch : patches,
224
222
  targetHash : '',
225
223
  targetVersionId : sourceVersionId + 1,
@@ -311,12 +309,10 @@ export class Updater {
311
309
  }
312
310
 
313
311
  const config: Btcr2DataIntegrityConfig = {
314
- '@context' : [
315
- 'https://w3id.org/security/v2',
316
- 'https://w3id.org/zcap/v1',
317
- 'https://w3id.org/json-ld-patch/v1',
318
- 'https://btcr2.dev/context/v1'
319
- ],
312
+ // The proof must carry the same array as the update. The cryptosuite copies the
313
+ // document @context into the proof when the document has one, so the two arrays
314
+ // are equal by construction; this value is the fallback for a document without one.
315
+ '@context' : [ ...BTCR2_UPDATE_CONTEXT ],
320
316
  cryptosuite : 'bip340-jcs-2025',
321
317
  type : 'DataIntegrityProof',
322
318
  // The proof names the signing method by absolute DID URL, even when the document
@@ -161,9 +161,10 @@ export class Appendix {
161
161
  * ```
162
162
  * {
163
163
  * "@context": [
164
+ * "https://w3id.org/json-ld-patch/v1",
164
165
  * "https://w3id.org/zcap/v1",
165
166
  * "https://w3id.org/security/data-integrity/v2",
166
- * "https://w3id.org/json-ld-patch/v1"
167
+ * "https://btcr2.dev/context/v1"
167
168
  * ],
168
169
  * "patch": [
169
170
  * {