@interop/ed25519-signature 6.0.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/LICENSE +29 -0
  3. package/README.md +256 -0
  4. package/dist/core/createSigner.d.ts +17 -0
  5. package/dist/core/createSigner.d.ts.map +1 -0
  6. package/dist/core/createSigner.js +15 -0
  7. package/dist/core/createSigner.js.map +1 -0
  8. package/dist/core/createVerifier.d.ts +10 -0
  9. package/dist/core/createVerifier.d.ts.map +1 -0
  10. package/dist/core/createVerifier.js +14 -0
  11. package/dist/core/createVerifier.js.map +1 -0
  12. package/dist/core/requiredAlgorithm.d.ts +2 -0
  13. package/dist/core/requiredAlgorithm.d.ts.map +1 -0
  14. package/dist/core/requiredAlgorithm.js +2 -0
  15. package/dist/core/requiredAlgorithm.js.map +1 -0
  16. package/dist/core/sha256-browser.d.ts +4 -0
  17. package/dist/core/sha256-browser.d.ts.map +1 -0
  18. package/dist/core/sha256-browser.js +5 -0
  19. package/dist/core/sha256-browser.js.map +1 -0
  20. package/dist/core/sha256.d.ts +4 -0
  21. package/dist/core/sha256.d.ts.map +1 -0
  22. package/dist/core/sha256.js +5 -0
  23. package/dist/core/sha256.js.map +1 -0
  24. package/dist/ed25519-signature-2020/cryptosuite.d.ts +3 -0
  25. package/dist/ed25519-signature-2020/cryptosuite.d.ts.map +1 -0
  26. package/dist/ed25519-signature-2020/cryptosuite.js +12 -0
  27. package/dist/ed25519-signature-2020/cryptosuite.js.map +1 -0
  28. package/dist/ed25519-signature-2020/index.d.ts +19 -0
  29. package/dist/ed25519-signature-2020/index.d.ts.map +1 -0
  30. package/dist/ed25519-signature-2020/index.js +30 -0
  31. package/dist/ed25519-signature-2020/index.js.map +1 -0
  32. package/dist/eddsa-jcs-2022/canonize.d.ts +2 -0
  33. package/dist/eddsa-jcs-2022/canonize.d.ts.map +1 -0
  34. package/dist/eddsa-jcs-2022/canonize.js +9 -0
  35. package/dist/eddsa-jcs-2022/canonize.js.map +1 -0
  36. package/dist/eddsa-jcs-2022/createVerifyData.d.ts +3 -0
  37. package/dist/eddsa-jcs-2022/createVerifyData.d.ts.map +1 -0
  38. package/dist/eddsa-jcs-2022/createVerifyData.js +67 -0
  39. package/dist/eddsa-jcs-2022/createVerifyData.js.map +1 -0
  40. package/dist/eddsa-jcs-2022/index.d.ts +21 -0
  41. package/dist/eddsa-jcs-2022/index.d.ts.map +1 -0
  42. package/dist/eddsa-jcs-2022/index.js +28 -0
  43. package/dist/eddsa-jcs-2022/index.js.map +1 -0
  44. package/dist/eddsa-rdfc-2022/canonize.d.ts +2 -0
  45. package/dist/eddsa-rdfc-2022/canonize.d.ts.map +1 -0
  46. package/dist/eddsa-rdfc-2022/canonize.js +17 -0
  47. package/dist/eddsa-rdfc-2022/canonize.js.map +1 -0
  48. package/dist/eddsa-rdfc-2022/index.d.ts +9 -0
  49. package/dist/eddsa-rdfc-2022/index.d.ts.map +1 -0
  50. package/dist/eddsa-rdfc-2022/index.js +10 -0
  51. package/dist/eddsa-rdfc-2022/index.js.map +1 -0
  52. package/dist/index.d.ts +6 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +6 -0
  55. package/dist/index.js.map +1 -0
  56. package/package.json +97 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,133 @@
1
+ # @interop/ed25519-signature Changelog
2
+
3
+ ## 6.0.0 - 2026-05-27
4
+ ### Changed
5
+ - **BREAKING: Renamed** from `@digitalbazaar/ed25519-signature-2020` to
6
+ `@interop/ed25519-signature` (rename-in-place; preserves git history and the
7
+ committed spec test vectors).
8
+ - **BREAKING: New architecture.** The package now provides all three Ed25519
9
+ proof flavors -- `Ed25519Signature2020`, `eddsa-rdfc-2022`, and
10
+ `eddsa-jcs-2022` -- unified on the `DataIntegrityProof` container model. The
11
+ legacy `Ed25519Signature2020` suite is now a thin subclass of
12
+ `DataIntegrityProof` (not a `LinkedDataSignature` subclass); its signed bytes
13
+ remain byte-identical to the legacy suite (pinned acceptance test).
14
+ - **BREAKING: New API surface.** Per-suite subpath exports
15
+ (`./ed25519-signature-2020`, `./eddsa-rdfc-2022`, `./eddsa-jcs-2022`) plus a
16
+ root barrel; `sideEffects: false` for tree-shaking. The three suites expose
17
+ deliberately different shapes (class vs static cryptosuite vs sign/verify
18
+ factories), matching their specs.
19
+ - **BREAKING: Ported to TypeScript** (`src/` to `dist/` via `tsc`); ESM-only,
20
+ Node.js 20+. New pnpm + Vitest + Playwright + ESLint + Prettier toolchain
21
+ (the karma/mocha/webpack stack was dropped).
22
+ - Single key library: `@interop/ed25519-verification-key` (reads Multikey +
23
+ 2020 + 2018 + JWK), replacing `@digitalbazaar/ed25519-multikey` and
24
+ `@digitalbazaar/ed25519-verification-key-2020`.
25
+ - Uses `@interop/jsonld-signatures` as the `jsigs.sign` / `jsigs.verify` entry
26
+ point and `@interop/jsonld` for RDFC-1.0 canonicalization.
27
+
28
+ ### Added
29
+ - `eddsa-rdfc-2022` cryptosuite (DataIntegrityProof, RDFC-1.0).
30
+ - `eddsa-jcs-2022` sign/verify cryptosuite factories (DataIntegrityProof, JCS /
31
+ RFC 8785), including the spec context-prefix ordering check.
32
+ - `createSigner` / `createVerifier` core helpers (inject the `algorithm`
33
+ property `DataIntegrityProof` requires; idempotent).
34
+ - Mixed-proof-array verification test (one VC carrying all three proof types,
35
+ disambiguated by `matchProof`).
36
+
37
+ ### Fixed
38
+ - `eddsa-jcs-2022` verify: the context-prefix check now compares `@context`
39
+ entries by value, not reference, so a VC carrying an inline `@context` object
40
+ verifies after a JSON round-trip (the realistic transport path). The previous
41
+ reference (`!==`) comparison, mirrored from the upstream spec reference impl,
42
+ wrongly rejected such VCs.
43
+
44
+ ## 5.4.0 - 2024-08-01
45
+
46
+ ### Changed
47
+ - Use `jsonld-signature@11.3` to get `RDFC-1.0` implementation.
48
+
49
+ ## 5.3.0 - 2024-06-15
50
+
51
+ ### Added
52
+ - Add support for `Multikey` verification methods.
53
+
54
+ ### Changed
55
+ - Loosen restrictions on verification methods that do not have
56
+ contexts, allowing processing of well-known types in those cases.
57
+ - Allow `publiKeyJwk` to be used to express key material.
58
+
59
+ ## 5.2.0 - 2023-02-13
60
+
61
+ ### Removed
62
+ - Remove unused `expansionMap` from `matchProof()` as it was removed
63
+ from `jsonld-signatures@11` which is required since version `5.0`.
64
+
65
+ ## 5.1.0 - 2023-02-07
66
+
67
+ ### Added
68
+ - Allow custom `canonizeOptions` to be passed in the construction of
69
+ a suite as a stop-gap until hard requirements for canonize options
70
+ are either set or advised to be certain values by a W3C working group.
71
+
72
+ ## 5.0.0 - 2022-08-23
73
+
74
+ ### Changed
75
+ - **BREAKING**: Use `jsonld-signatures@11` to get better safe mode
76
+ protections when canonizing.
77
+
78
+ ## 4.0.1 - 2022-06-06
79
+
80
+ ### Changed
81
+ - Update to jsonld-signatures@10.
82
+
83
+ ## 4.0.0 - 2022-06-06
84
+
85
+ ### Changed
86
+ - **BREAKING**: Convert to module (ESM).
87
+ - **BREAKING**: Require Node.js >=14.
88
+ - Update dependencies.
89
+ - Lint module.
90
+
91
+ ## 3.0.0 - 2021-06-19
92
+
93
+ ### Fixed
94
+
95
+ - **BREAKING**: Update to use new Ed25519VerificationKey2020 multicodec
96
+ encoded key formats.
97
+
98
+ ## 2.2.0 - 2021-05-26
99
+
100
+ ### Added
101
+ - It is now possible to verify `Ed25519Signature2020` proofs using using
102
+ 2018 keys.
103
+
104
+ ### Changed
105
+ - Replace `@transmute/jsonld-document-loader` with
106
+ `@digitalbazaar/security-document-loader` in test.
107
+
108
+ ## 2.1.0 - 2021-04-09
109
+
110
+ ### Added
111
+ - Export the suite's context (and related objects such as context url,
112
+ documentLoader, etc), and also set them as a property of the suite class.
113
+ - Set the `contextUrl` property on suite instance, to support context
114
+ enforcement during the `sign()` operation that was added to `jsonld-signatures`
115
+ `v9.0.1`.
116
+
117
+ ## 2.0.1 - 2021-04-09
118
+
119
+ ### Changed
120
+ - Use `ed25519-verification-key-2020@2.1.1`. Signer now has an "id" property.
121
+
122
+ ## 2.0.0 - 2021-04-06
123
+
124
+ ### Changed
125
+ - **BREAKING**: Update to use `jsonld-signatures` v9.0 (removes
126
+ `verificationMethod` suite constructor param, makes key and signer validation
127
+ stricter).
128
+ - Fix initializing signer and verifier object by passing it to superclass.
129
+
130
+ ## 1.0.0 - 2021-03-19
131
+
132
+ ### Added
133
+ - Initial files.
package/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2021, Digital Bazaar, Inc.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md ADDED
@@ -0,0 +1,256 @@
1
+ # @interop/ed25519-signature
2
+
3
+ [![Node.js CI](https://github.com/interop-alliance/ed25519-signature/workflows/CI/badge.svg)](https://github.com/interop-alliance/ed25519-signature/actions?query=workflow%3A%22CI%22)
4
+ [![NPM Version](https://img.shields.io/npm/v/@interop/ed25519-signature.svg)](https://npm.im/@interop/ed25519-signature)
5
+
6
+ > Ed25519 Linked Data / Data Integrity signature suites for use with
7
+ > [`jsonld-signatures`](https://github.com/digitalbazaar/jsonld-signatures),
8
+ > in TypeScript.
9
+
10
+ One package providing all three Ed25519 Verifiable Credential proof flavors,
11
+ unified on the `DataIntegrityProof` container model:
12
+
13
+ | Suite | `proof.type` | `proof.cryptosuite` | Canonicalization |
14
+ |------------------------|------------------------|---------------------|------------------|
15
+ | `Ed25519Signature2020` | `Ed25519Signature2020` | (absent) | RDFC-1.0 |
16
+ | `eddsa-rdfc-2022` | `DataIntegrityProof` | `eddsa-rdfc-2022` | RDFC-1.0 |
17
+ | `eddsa-jcs-2022` | `DataIntegrityProof` | `eddsa-jcs-2022` | JCS (RFC 8785) |
18
+
19
+ This is a TypeScript rewrite and rename-in-place of
20
+ `@digitalbazaar/ed25519-signature-2020` (v6). The full design and migration
21
+ history live in [`refactor-plan.md`](./refactor-plan.md); contributor-facing
22
+ architecture notes are in [`CLAUDE.md`](./CLAUDE.md).
23
+
24
+ ## Table of Contents
25
+
26
+ - [Background](#background)
27
+ - [Install](#install)
28
+ - [Subpath imports](#subpath-imports)
29
+ - [Usage](#usage)
30
+ - [`Ed25519Signature2020`](#ed25519signature2020)
31
+ - [`eddsa-rdfc-2022`](#eddsa-rdfc-2022)
32
+ - [`eddsa-jcs-2022`](#eddsa-jcs-2022)
33
+ - [Verifying a mixed proof set](#verifying-a-mixed-proof-set)
34
+ - [API asymmetry across suites](#api-asymmetry-across-suites)
35
+ - [The `createSigner` requirement](#the-createsigner-requirement)
36
+ - [Contribute](#contribute)
37
+ - [License](#license)
38
+
39
+ ## Background
40
+
41
+ Lets a downstream consumer issue and verify all three Ed25519 proof types -- as
42
+ they appear mixed in VC `proof` arrays and DID documents -- through one package,
43
+ one container concept (`DataIntegrityProof`), one key library
44
+ ([`@interop/ed25519-verification-key`](https://github.com/interop-alliance/ed25519-verification-key),
45
+ which reads Multikey + 2020 + 2018 + JWK), and one toolchain.
46
+
47
+ The legacy `Ed25519Signature2020` suite is implemented as a thin subclass of
48
+ `DataIntegrityProof` rather than a `LinkedDataSignature` subclass, so the
49
+ container, key library, and signing payload are shared with the
50
+ data-integrity suites. Its signed bytes are byte-identical to the legacy
51
+ `@digitalbazaar/ed25519-signature-2020` suite (a pinned acceptance test).
52
+
53
+ Related spec: [Verifiable Credential Data Integrity / EdDSA Cryptosuites](https://w3c.github.io/vc-di-eddsa/).
54
+
55
+ ## Install
56
+
57
+ Node.js 20+ and modern browsers are supported. This package is ESM-only.
58
+
59
+ ```
60
+ npm install @interop/ed25519-signature
61
+ ```
62
+
63
+ `@interop/jsonld-signatures` is an optional peer dependency -- install it
64
+ alongside if you use the `jsigs.sign` / `jsigs.verify` entry points shown below.
65
+
66
+ ## Subpath imports
67
+
68
+ Each suite has its own subpath export, so a JCS-only consumer is not forced to
69
+ pull in the heavy `jsonld` / `rdf-canonize` machinery that only the RDFC suites
70
+ need (the package is `sideEffects: false` for tree-shaking). Prefer the
71
+ leaf-scoped import for the suite you actually use:
72
+
73
+ ```js
74
+ import { Ed25519Signature2020 } from '@interop/ed25519-signature/ed25519-signature-2020'
75
+ import { eddsaRdfc2022 } from '@interop/ed25519-signature/eddsa-rdfc-2022'
76
+ import {
77
+ createSignCryptosuite,
78
+ createVerifyCryptosuite
79
+ } from '@interop/ed25519-signature/eddsa-jcs-2022'
80
+ ```
81
+
82
+ A convenience root barrel re-exports everything (plus `createSigner` /
83
+ `createVerifier`) for when bundle size is not a concern:
84
+
85
+ ```js
86
+ import { Ed25519Signature2020, eddsaRdfc2022, createSigner } from '@interop/ed25519-signature'
87
+ ```
88
+
89
+ ## Usage
90
+
91
+ The examples share this setup:
92
+
93
+ ```js
94
+ import jsigs from '@interop/jsonld-signatures'
95
+ import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'
96
+
97
+ const { purposes: { AssertionProofPurpose } } = jsigs
98
+
99
+ const controller = 'https://example.edu/issuers/565049'
100
+ const keyPair = await Ed25519VerificationKey.from({
101
+ type: 'Ed25519VerificationKey2020',
102
+ controller,
103
+ id: controller + '#z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T',
104
+ publicKeyMultibase: 'z6MknCCLeeHBUaHu4aHSVLDCYQW9gjVJ7a63FpMvtuVMy53T',
105
+ privateKeyMultibase:
106
+ 'zrv2EET2WWZ8T1Jbg4fEH5cQxhbUS22XxdweypUbjWVzv1YD6VqYuW6LH7heQCNYQCuoKaDwvv2qCWz3uBzG2xesqmf'
107
+ })
108
+
109
+ // Provide a documentLoader that resolves the VC contexts, the key, and its
110
+ // controller. See test/node/documentLoader.ts for a securityLoader()-based one.
111
+ ```
112
+
113
+ ### `Ed25519Signature2020`
114
+
115
+ A class extending `DataIntegrityProof`. Pass `keyPair.signer()` directly -- the
116
+ constructor injects the required `algorithm` for you.
117
+
118
+ ```js
119
+ import { Ed25519Signature2020 } from '@interop/ed25519-signature/ed25519-signature-2020'
120
+
121
+ const credential = {
122
+ '@context': [
123
+ 'https://www.w3.org/2018/credentials/v1',
124
+ { AlumniCredential: 'https://schema.org#AlumniCredential', alumniOf: 'https://schema.org#alumniOf' },
125
+ 'https://w3id.org/security/suites/ed25519-2020/v1'
126
+ ],
127
+ id: 'http://example.edu/credentials/1872',
128
+ type: ['VerifiableCredential', 'AlumniCredential'],
129
+ issuer: controller,
130
+ issuanceDate: '2010-01-01T19:23:24Z',
131
+ credentialSubject: { id: 'https://example.edu/students/alice', alumniOf: 'Example University' }
132
+ }
133
+
134
+ const signed = await jsigs.sign({ ...credential }, {
135
+ suite: new Ed25519Signature2020({ signer: keyPair.signer() }),
136
+ purpose: new AssertionProofPurpose(),
137
+ documentLoader
138
+ })
139
+ // signed.proof.type === 'Ed25519Signature2020' (no `cryptosuite` field)
140
+
141
+ const result = await jsigs.verify(signed, {
142
+ suite: new Ed25519Signature2020(),
143
+ purpose: new AssertionProofPurpose(),
144
+ documentLoader
145
+ })
146
+ // result.verified === true
147
+ ```
148
+
149
+ ### `eddsa-rdfc-2022`
150
+
151
+ A static cryptosuite object used with a bare `DataIntegrityProof`. On the sign
152
+ side, wrap the key with `createSigner` (see
153
+ [below](#the-createsigner-requirement)).
154
+
155
+ ```js
156
+ import { DataIntegrityProof } from '@digitalbazaar/data-integrity'
157
+ import { eddsaRdfc2022 } from '@interop/ed25519-signature/eddsa-rdfc-2022'
158
+ import { createSigner } from '@interop/ed25519-signature'
159
+
160
+ // The VC @context must include 'https://w3id.org/security/data-integrity/v2'.
161
+ const signed = await jsigs.sign({ ...diCredential }, {
162
+ suite: new DataIntegrityProof({ cryptosuite: eddsaRdfc2022, signer: createSigner(keyPair) }),
163
+ purpose: new AssertionProofPurpose(),
164
+ documentLoader
165
+ })
166
+ // signed.proof.type === 'DataIntegrityProof', signed.proof.cryptosuite === 'eddsa-rdfc-2022'
167
+
168
+ const result = await jsigs.verify(signed, {
169
+ suite: new DataIntegrityProof({ cryptosuite: eddsaRdfc2022 }),
170
+ purpose: new AssertionProofPurpose(),
171
+ documentLoader
172
+ })
173
+ ```
174
+
175
+ ### `eddsa-jcs-2022`
176
+
177
+ Split sign / verify factories (not a single object). The sign cryptosuite's
178
+ `createVerifier` throws, as a sign-only guard.
179
+
180
+ ```js
181
+ import { DataIntegrityProof } from '@digitalbazaar/data-integrity'
182
+ import { createSignCryptosuite, createVerifyCryptosuite } from '@interop/ed25519-signature/eddsa-jcs-2022'
183
+ import { createSigner } from '@interop/ed25519-signature'
184
+
185
+ const signed = await jsigs.sign({ ...diCredential }, {
186
+ suite: new DataIntegrityProof({ cryptosuite: createSignCryptosuite(), signer: createSigner(keyPair) }),
187
+ purpose: new AssertionProofPurpose(),
188
+ documentLoader
189
+ })
190
+ // signed.proof.cryptosuite === 'eddsa-jcs-2022'
191
+
192
+ const result = await jsigs.verify(signed, {
193
+ suite: new DataIntegrityProof({ cryptosuite: createVerifyCryptosuite() }),
194
+ purpose: new AssertionProofPurpose(),
195
+ documentLoader
196
+ })
197
+ ```
198
+
199
+ JCS verification enforces the spec's context-prefix ordering check: the
200
+ document's `@context` must start with the proof's `@context`, in order.
201
+
202
+ ### Verifying a mixed proof set
203
+
204
+ A single VC can carry one of each proof type in its `proof` array; pass all the
205
+ matching suites to one `jsigs.verify` call and they are disambiguated by
206
+ `matchProof`:
207
+
208
+ ```js
209
+ const result = await jsigs.verify(signed, {
210
+ suite: [
211
+ new Ed25519Signature2020(),
212
+ new DataIntegrityProof({ cryptosuite: eddsaRdfc2022 }),
213
+ new DataIntegrityProof({ cryptosuite: createVerifyCryptosuite() })
214
+ ],
215
+ purpose: new AssertionProofPurpose(),
216
+ documentLoader
217
+ })
218
+ ```
219
+
220
+ Note the proof-set semantics of `jsonld-signatures`: `result.verified` is `true`
221
+ if **any** matched proof verifies. Inspect `result.results` for the per-proof
222
+ outcome.
223
+
224
+ ## API asymmetry across suites
225
+
226
+ The three suites expose deliberately different shapes, because the specs do --
227
+ a class (`Ed25519Signature2020`), a static cryptosuite object
228
+ (`eddsa-rdfc-2022`), and sign/verify factories (`eddsa-jcs-2022`). This is
229
+ intentional; don't try to abstract over it.
230
+
231
+ ## The `createSigner` requirement
232
+
233
+ `DataIntegrityProof` asserts `signer.algorithm === 'Ed25519'` at construction.
234
+ In the Digital Bazaar ecosystem the key library supplies that property;
235
+ `@interop/ed25519-verification-key` does not (yet), so when using a **bare**
236
+ `DataIntegrityProof` (the rdfc / jcs suites) wrap the key with `createSigner`:
237
+
238
+ ```js
239
+ import { createSigner } from '@interop/ed25519-signature'
240
+ new DataIntegrityProof({ cryptosuite: eddsaRdfc2022, signer: createSigner(keyPair) })
241
+ ```
242
+
243
+ The `Ed25519Signature2020` class does this for you, so there you can pass
244
+ `keyPair.signer()` directly. `createSigner` is idempotent
245
+ (`algorithm ?? 'Ed25519'`), so it becomes a no-op once the key library sets
246
+ `algorithm` itself.
247
+
248
+ ## Contribute
249
+
250
+ PRs accepted. See [`CLAUDE.md`](./CLAUDE.md) for toolchain, project layout, and
251
+ the testing rules (notably: never hand-roll JSON-LD `@context` documents in
252
+ tests).
253
+
254
+ ## License
255
+
256
+ [New BSD License (3-clause)](LICENSE)
@@ -0,0 +1,17 @@
1
+ import type { SignerLike } from '@digitalbazaar/data-integrity';
2
+ type SignerSource = Omit<SignerLike, 'algorithm'> & {
3
+ algorithm?: string;
4
+ };
5
+ /**
6
+ * Produces a signer that carries `algorithm`, which `DataIntegrityProof`
7
+ * requires (it asserts `signer.algorithm === requiredAlgorithm` at
8
+ * construction). `@interop/ed25519-verification-key`'s `signer()` does not set
9
+ * `algorithm`; this injects it. Idempotent: an `algorithm` already present
10
+ * (e.g. once the key library sets it) is preserved.
11
+ */
12
+ export declare function createSigner(keyPair: {
13
+ signer(): SignerSource;
14
+ }): SignerLike;
15
+ export declare function ensureSignerAlgorithm(signer: SignerSource): SignerLike;
16
+ export {};
17
+ //# sourceMappingURL=createSigner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSigner.d.ts","sourceRoot":"","sources":["../../src/core/createSigner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAG/D,KAAK,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1E;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE;IAAE,MAAM,IAAI,YAAY,CAAA;CAAE,GAAG,UAAU,CAE5E;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,UAAU,CAEtE"}
@@ -0,0 +1,15 @@
1
+ import { requiredAlgorithm } from './requiredAlgorithm.js';
2
+ /**
3
+ * Produces a signer that carries `algorithm`, which `DataIntegrityProof`
4
+ * requires (it asserts `signer.algorithm === requiredAlgorithm` at
5
+ * construction). `@interop/ed25519-verification-key`'s `signer()` does not set
6
+ * `algorithm`; this injects it. Idempotent: an `algorithm` already present
7
+ * (e.g. once the key library sets it) is preserved.
8
+ */
9
+ export function createSigner(keyPair) {
10
+ return ensureSignerAlgorithm(keyPair.signer());
11
+ }
12
+ export function ensureSignerAlgorithm(signer) {
13
+ return { ...signer, algorithm: signer.algorithm ?? requiredAlgorithm };
14
+ }
15
+ //# sourceMappingURL=createSigner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createSigner.js","sourceRoot":"","sources":["../../src/core/createSigner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAI1D;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAAmC;IAC9D,OAAO,qBAAqB,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAoB;IACxD,OAAO,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,iBAAiB,EAAE,CAAA;AACxE,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare function createVerifier({ verificationMethod }: {
2
+ verificationMethod: unknown;
3
+ }): Promise<{
4
+ verify(opts: {
5
+ data: Uint8Array;
6
+ signature: Uint8Array;
7
+ }): Promise<boolean>;
8
+ algorithm: string;
9
+ }>;
10
+ //# sourceMappingURL=createVerifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createVerifier.d.ts","sourceRoot":"","sources":["../../src/core/createVerifier.ts"],"names":[],"mappings":"AAGA,wBAAsB,cAAc,CAAC,EACnC,kBAAkB,EACnB,EAAE;IACD,kBAAkB,EAAE,OAAO,CAAA;CAC5B,GAAG,OAAO,CAAC;IAAE,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAU9G"}
@@ -0,0 +1,14 @@
1
+ import { Ed25519VerificationKey } from '@interop/ed25519-verification-key';
2
+ import { requiredAlgorithm } from './requiredAlgorithm.js';
3
+ export async function createVerifier({ verificationMethod }) {
4
+ // verificationMethod is one of: Multikey, Ed25519VerificationKey2020,
5
+ // Ed25519VerificationKey2018, or JsonWebKey2020
6
+ const key = await Ed25519VerificationKey.from(verificationMethod);
7
+ const verifier = key.verifier();
8
+ // DataIntegrityProof checks verifier.algorithm against requiredAlgorithm;
9
+ // the verification-key library does not set algorithm on the returned object.
10
+ // Idempotent: preserve an algorithm already set (e.g. once the key library
11
+ // sets it).
12
+ return { ...verifier, algorithm: verifier.algorithm ?? requiredAlgorithm };
13
+ }
14
+ //# sourceMappingURL=createVerifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createVerifier.js","sourceRoot":"","sources":["../../src/core/createVerifier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAA;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAE1D,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EACnC,kBAAkB,EAGnB;IACC,sEAAsE;IACtE,gDAAgD;IAChD,MAAM,GAAG,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,kBAAyB,CAAC,CAAA;IACxE,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAA;IAC/B,0EAA0E;IAC1E,8EAA8E;IAC9E,2EAA2E;IAC3E,YAAY;IACZ,OAAO,EAAE,GAAG,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,iBAAiB,EAAE,CAAA;AAC5E,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const requiredAlgorithm = "Ed25519";
2
+ //# sourceMappingURL=requiredAlgorithm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requiredAlgorithm.d.ts","sourceRoot":"","sources":["../../src/core/requiredAlgorithm.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export const requiredAlgorithm = 'Ed25519';
2
+ //# sourceMappingURL=requiredAlgorithm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requiredAlgorithm.js","sourceRoot":"","sources":["../../src/core/requiredAlgorithm.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAA"}
@@ -0,0 +1,4 @@
1
+ export declare function sha256({ string }: {
2
+ string: string;
3
+ }): Promise<Uint8Array>;
4
+ //# sourceMappingURL=sha256-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha256-browser.d.ts","sourceRoot":"","sources":["../../src/core/sha256-browser.ts"],"names":[],"mappings":"AAAA,wBAAsB,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAKhF"}
@@ -0,0 +1,5 @@
1
+ export async function sha256({ string }) {
2
+ const bytes = new TextEncoder().encode(string);
3
+ return new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));
4
+ }
5
+ //# sourceMappingURL=sha256-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha256-browser.js","sourceRoot":"","sources":["../../src/core/sha256-browser.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAAE,MAAM,EAAsB;IACzD,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC9C,OAAO,IAAI,UAAU,CACnB,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAC7C,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function sha256({ string }: {
2
+ string: string;
3
+ }): Promise<Uint8Array>;
4
+ //# sourceMappingURL=sha256.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha256.d.ts","sourceRoot":"","sources":["../../src/core/sha256.ts"],"names":[],"mappings":"AAEA,wBAAsB,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAEhF"}
@@ -0,0 +1,5 @@
1
+ import crypto from 'node:crypto';
2
+ export async function sha256({ string }) {
3
+ return new Uint8Array(crypto.createHash('sha256').update(string).digest());
4
+ }
5
+ //# sourceMappingURL=sha256.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../src/core/sha256.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAEhC,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAAE,MAAM,EAAsB;IACzD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;AAC5E,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { CryptosuiteLike } from '@digitalbazaar/data-integrity';
2
+ export declare const ed25519Sig2020Cryptosuite: CryptosuiteLike;
3
+ //# sourceMappingURL=cryptosuite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cryptosuite.d.ts","sourceRoot":"","sources":["../../src/ed25519-signature-2020/cryptosuite.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAKpE,eAAO,MAAM,yBAAyB,EAAE,eAIvC,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { canonize } from '../eddsa-rdfc-2022/canonize.js';
2
+ import { createVerifier } from '../core/createVerifier.js';
3
+ import { requiredAlgorithm } from '../core/requiredAlgorithm.js';
4
+ // Internal cryptosuite for Ed25519Signature2020 -- deliberately no `name`
5
+ // so this.cryptosuite stays undefined on the proof (2020 proofs carry no
6
+ // cryptosuite field).
7
+ export const ed25519Sig2020Cryptosuite = {
8
+ canonize: canonize,
9
+ createVerifier: createVerifier,
10
+ requiredAlgorithm
11
+ };
12
+ //# sourceMappingURL=cryptosuite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cryptosuite.js","sourceRoot":"","sources":["../../src/ed25519-signature-2020/cryptosuite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAGhE,0EAA0E;AAC1E,yEAAyE;AACzE,sBAAsB;AACtB,MAAM,CAAC,MAAM,yBAAyB,GAAoB;IACxD,QAAQ,EAAE,QAAuC;IACjD,cAAc,EAAE,cAAmD;IACnE,iBAAiB;CAClB,CAAA"}
@@ -0,0 +1,19 @@
1
+ import { DataIntegrityProof } from '@digitalbazaar/data-integrity';
2
+ import type { ProofLike, SignerLike } from '@digitalbazaar/data-integrity';
3
+ import suiteContext2020 from 'ed25519-signature-2020-context';
4
+ export declare class Ed25519Signature2020 extends DataIntegrityProof {
5
+ static CONTEXT_URL: string;
6
+ static CONTEXT: unknown;
7
+ constructor({ signer, date }?: {
8
+ signer?: Omit<SignerLike, 'algorithm'> & {
9
+ algorithm?: string;
10
+ };
11
+ date?: string | Date | number | null;
12
+ });
13
+ updateProof({ proof }: {
14
+ proof: ProofLike;
15
+ [key: string]: unknown;
16
+ }): Promise<ProofLike>;
17
+ }
18
+ export { suiteContext2020 as suiteContext };
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ed25519-signature-2020/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAG1E,OAAO,gBAAgB,MAAM,gCAAgC,CAAA;AAI7D,qBAAa,oBAAqB,SAAQ,kBAAkB;IAC1D,MAAM,CAAC,WAAW,SAAoB;IACtC,MAAM,CAAC,OAAO,UAAmD;gBAErD,EACV,MAAM,EACN,IAAI,EACL,GAAE;QACD,MAAM,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG;YAAE,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;QAC/D,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAAA;KAChC;IAgBS,WAAW,CAAC,EACzB,KAAK,EACN,EAAE;QACD,KAAK,EAAE,SAAS,CAAA;QAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KACvB,GAAG,OAAO,CAAC,SAAS,CAAC;CAIvB;AAED,OAAO,EAAE,gBAAgB,IAAI,YAAY,EAAE,CAAA"}
@@ -0,0 +1,30 @@
1
+ import { DataIntegrityProof } from '@digitalbazaar/data-integrity';
2
+ import { ed25519Sig2020Cryptosuite } from './cryptosuite.js';
3
+ import { ensureSignerAlgorithm } from '../core/createSigner.js';
4
+ import suiteContext2020 from 'ed25519-signature-2020-context';
5
+ const SUITE_CONTEXT_URL = suiteContext2020.constants.CONTEXT_URL;
6
+ export class Ed25519Signature2020 extends DataIntegrityProof {
7
+ static CONTEXT_URL = SUITE_CONTEXT_URL;
8
+ static CONTEXT = suiteContext2020.contexts.get(SUITE_CONTEXT_URL);
9
+ constructor({ signer, date } = {}) {
10
+ // Cryptosuite has no `name`, so this.cryptosuite stays undefined --
11
+ // matching the absent cryptosuite field on legacy 2020 proofs.
12
+ // DataIntegrityProof validates signer.algorithm; ensure it is set
13
+ // (the @interop/ed25519-verification-key signer doesn't set algorithm).
14
+ const wrappedSigner = signer
15
+ ? ensureSignerAlgorithm(signer)
16
+ : undefined;
17
+ super({ signer: wrappedSigner, date, cryptosuite: ed25519Sig2020Cryptosuite });
18
+ this.type = 'Ed25519Signature2020';
19
+ this.contextUrl = SUITE_CONTEXT_URL;
20
+ }
21
+ // Called by DataIntegrityProof.createProof() before hashing proof options.
22
+ // Removes the cryptosuite field that the base class writes (2020 proofs
23
+ // carry no cryptosuite field).
24
+ async updateProof({ proof }) {
25
+ delete proof.cryptosuite;
26
+ return proof;
27
+ }
28
+ }
29
+ export { suiteContext2020 as suiteContext };
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ed25519-signature-2020/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAElE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,gBAAgB,MAAM,gCAAgC,CAAA;AAE7D,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAA;AAEhE,MAAM,OAAO,oBAAqB,SAAQ,kBAAkB;IAC1D,MAAM,CAAC,WAAW,GAAG,iBAAiB,CAAA;IACtC,MAAM,CAAC,OAAO,GAAG,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;IAEjE,YAAY,EACV,MAAM,EACN,IAAI,KAIF,EAAE;QACJ,oEAAoE;QACpE,+DAA+D;QAC/D,kEAAkE;QAClE,wEAAwE;QACxE,MAAM,aAAa,GAA2B,MAAM;YAClD,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC;YAC/B,CAAC,CAAC,SAAS,CAAA;QACb,KAAK,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC,CAAA;QAC9E,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;QAClC,IAAI,CAAC,UAAU,GAAG,iBAAiB,CAAA;IACrC,CAAC;IAED,2EAA2E;IAC3E,wEAAwE;IACxE,+BAA+B;IACtB,KAAK,CAAC,WAAW,CAAC,EACzB,KAAK,EAIN;QACC,OAAO,KAAK,CAAC,WAAW,CAAA;QACxB,OAAO,KAAK,CAAA;IACd,CAAC;;AAGH,OAAO,EAAE,gBAAgB,IAAI,YAAY,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare function canonize(input: unknown): Promise<string>;
2
+ //# sourceMappingURL=canonize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonize.d.ts","sourceRoot":"","sources":["../../src/eddsa-jcs-2022/canonize.ts"],"names":[],"mappings":"AAEA,wBAAsB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9D"}
@@ -0,0 +1,9 @@
1
+ import canonicalize from 'canonicalize';
2
+ export async function canonize(input) {
3
+ const result = canonicalize(input);
4
+ if (result === undefined) {
5
+ throw new TypeError('JCS canonicalize returned undefined for input');
6
+ }
7
+ return result;
8
+ }
9
+ //# sourceMappingURL=canonize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonize.js","sourceRoot":"","sources":["../../src/eddsa-jcs-2022/canonize.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,cAAc,CAAA;AAEvC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAc;IAC3C,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAA;IAClC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAA;IACtE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type CreateVerifyDataFn = (opts: unknown) => Promise<Uint8Array>;
2
+ export declare function createVerifyDataFn(mode: 'sign' | 'verify'): CreateVerifyDataFn;
3
+ //# sourceMappingURL=createVerifyData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createVerifyData.d.ts","sourceRoot":"","sources":["../../src/eddsa-jcs-2022/createVerifyData.ts"],"names":[],"mappings":"AAwEA,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;AAEvE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,kBAAkB,CA0B9E"}
@@ -0,0 +1,67 @@
1
+ import { sha256 } from '../core/sha256.js';
2
+ const NAME = 'eddsa-jcs-2022';
3
+ function concat(b1, b2) {
4
+ const out = new Uint8Array(b1.length + b2.length);
5
+ out.set(b1, 0);
6
+ out.set(b2, b1.length);
7
+ return out;
8
+ }
9
+ async function canonizeProof(proofOptions, canonize) {
10
+ const proof = { ...proofOptions };
11
+ delete proof.proofValue;
12
+ return canonize(proof);
13
+ }
14
+ // On sign: copy document.@context onto proof so verifiers can reconstruct it.
15
+ function modifyForSign({ proof, document }) {
16
+ if (document['@context']) {
17
+ proof['@context'] = document['@context'];
18
+ }
19
+ }
20
+ // On verify: assert document.@context starts with proof.@context in order.
21
+ // This ordering check is security-sensitive per the JCS spec.
22
+ //
23
+ // Entries are compared by VALUE, not reference: an inline @context object (e.g.
24
+ // {AlumniCredential: ...}) becomes a distinct instance once the VC is
25
+ // serialized and re-parsed, so a reference (`!==`) compare wrongly rejects every
26
+ // transmitted VC that carries one. JSON.stringify gives the value compare the
27
+ // spec asks for; it is key-order sensitive, but both @context trees originate
28
+ // from the same issuer-side object so order is preserved (and any mismatch just
29
+ // throws -- fail-closed).
30
+ function modifyForVerify({ proof, document }) {
31
+ if (!proof['@context']) {
32
+ return;
33
+ }
34
+ const proofContext = Array.isArray(proof['@context'])
35
+ ? proof['@context']
36
+ : [proof['@context']];
37
+ const docContext = Array.isArray(document['@context'])
38
+ ? document['@context']
39
+ : [document['@context']];
40
+ for (let i = 0; i < proofContext.length; i++) {
41
+ if (JSON.stringify(proofContext[i]) !== JSON.stringify(docContext[i])) {
42
+ throw new Error('document.@context does not start with proof.@context');
43
+ }
44
+ }
45
+ // Adopt proof @context for canonicalization
46
+ document['@context'] = proof['@context'];
47
+ }
48
+ export function createVerifyDataFn(mode) {
49
+ return async function (opts) {
50
+ const { cryptosuite, document, proof } = opts;
51
+ if (cryptosuite?.name !== NAME) {
52
+ throw new TypeError(`"cryptosuite.name" must be "${NAME}".`);
53
+ }
54
+ if (mode === 'sign') {
55
+ modifyForSign({ proof, document });
56
+ }
57
+ else {
58
+ modifyForVerify({ proof, document });
59
+ }
60
+ const [proofHash, docHash] = await Promise.all([
61
+ canonizeProof(proof, cryptosuite.canonize.bind(cryptosuite)).then(jcs => sha256({ string: jcs })),
62
+ cryptosuite.canonize(document).then(jcs => sha256({ string: jcs }))
63
+ ]);
64
+ return concat(proofHash, docHash);
65
+ };
66
+ }
67
+ //# sourceMappingURL=createVerifyData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createVerifyData.js","sourceRoot":"","sources":["../../src/eddsa-jcs-2022/createVerifyData.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { canonize } from './canonize.js';
2
+ import { createVerifier } from '../core/createVerifier.js';
3
+ import { type CreateVerifyDataFn } from './createVerifyData.js';
4
+ import type { CryptosuiteLike } from '@digitalbazaar/data-integrity';
5
+ export interface JcsSignCryptosuite extends CryptosuiteLike {
6
+ name: string;
7
+ canonize: typeof canonize;
8
+ requiredAlgorithm: string;
9
+ createVerifier: () => never;
10
+ createVerifyData: CreateVerifyDataFn;
11
+ }
12
+ export interface JcsVerifyCryptosuite extends CryptosuiteLike {
13
+ name: string;
14
+ canonize: typeof canonize;
15
+ requiredAlgorithm: string;
16
+ createVerifier: typeof createVerifier;
17
+ createVerifyData: CreateVerifyDataFn;
18
+ }
19
+ export declare function createSignCryptosuite(): JcsSignCryptosuite;
20
+ export declare function createVerifyCryptosuite(): JcsVerifyCryptosuite;
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/eddsa-jcs-2022/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAE1D,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACnF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAWpE,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,QAAQ,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,KAAK,CAAA;IAC3B,gBAAgB,EAAE,kBAAkB,CAAA;CACrC;AAED,MAAM,WAAW,oBAAqB,SAAQ,eAAe;IAC3D,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,OAAO,QAAQ,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,OAAO,cAAc,CAAA;IACrC,gBAAgB,EAAE,kBAAkB,CAAA;CACrC;AAED,wBAAgB,qBAAqB,IAAI,kBAAkB,CAQ1D;AAED,wBAAgB,uBAAuB,IAAI,oBAAoB,CAQ9D"}
@@ -0,0 +1,28 @@
1
+ import { canonize } from './canonize.js';
2
+ import { createVerifier } from '../core/createVerifier.js';
3
+ import { requiredAlgorithm } from '../core/requiredAlgorithm.js';
4
+ import { createVerifyDataFn } from './createVerifyData.js';
5
+ const NAME = 'eddsa-jcs-2022';
6
+ function throwSignUsageError() {
7
+ throw new Error('This cryptosuite must only be used with "sign". ' +
8
+ 'Use createVerifyCryptosuite() for verification.');
9
+ }
10
+ export function createSignCryptosuite() {
11
+ return {
12
+ name: NAME,
13
+ canonize,
14
+ requiredAlgorithm,
15
+ createVerifier: throwSignUsageError,
16
+ createVerifyData: createVerifyDataFn('sign')
17
+ };
18
+ }
19
+ export function createVerifyCryptosuite() {
20
+ return {
21
+ name: NAME,
22
+ canonize,
23
+ requiredAlgorithm,
24
+ createVerifier,
25
+ createVerifyData: createVerifyDataFn('verify')
26
+ };
27
+ }
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/eddsa-jcs-2022/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,EAAE,kBAAkB,EAA2B,MAAM,uBAAuB,CAAA;AAGnF,MAAM,IAAI,GAAG,gBAAgB,CAAA;AAE7B,SAAS,mBAAmB;IAC1B,MAAM,IAAI,KAAK,CACb,kDAAkD;QAChD,iDAAiD,CACpD,CAAA;AACH,CAAC;AAkBD,MAAM,UAAU,qBAAqB;IACnC,OAAO;QACL,IAAI,EAAE,IAAI;QACV,QAAQ;QACR,iBAAiB;QACjB,cAAc,EAAE,mBAAmB;QACnC,gBAAgB,EAAE,kBAAkB,CAAC,MAAM,CAAC;KAC7C,CAAA;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,IAAI,EAAE,IAAI;QACV,QAAQ;QACR,iBAAiB;QACjB,cAAc;QACd,gBAAgB,EAAE,kBAAkB,CAAC,QAAQ,CAAC;KAC/C,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function canonize(input: unknown, options?: unknown): Promise<string>;
2
+ //# sourceMappingURL=canonize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonize.d.ts","sourceRoot":"","sources":["../../src/eddsa-rdfc-2022/canonize.ts"],"names":[],"mappings":"AAGA,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,MAAM,CAAC,CAajB"}
@@ -0,0 +1,17 @@
1
+ import * as rdfCanonize from 'rdf-canonize';
2
+ import jsonld from '@interop/jsonld';
3
+ export async function canonize(input, options) {
4
+ const opts = {
5
+ algorithm: 'RDFC-1.0',
6
+ format: 'application/n-quads',
7
+ base: null,
8
+ safe: true,
9
+ ...options,
10
+ rdfDirection: 'i18n-datatype',
11
+ produceGeneralizedRdf: false
12
+ };
13
+ const { format, ...rdfOpts } = opts;
14
+ const dataset = await jsonld.toRDF(input, rdfOpts);
15
+ return rdfCanonize.canonize(dataset, { algorithm: 'RDFC-1.0', format });
16
+ }
17
+ //# sourceMappingURL=canonize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonize.js","sourceRoot":"","sources":["../../src/eddsa-rdfc-2022/canonize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,cAAc,CAAA;AAC3C,OAAO,MAAM,MAAM,iBAAiB,CAAA;AAEpC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAc,EACd,OAAiB;IAEjB,MAAM,IAAI,GAA4B;QACpC,SAAS,EAAE,UAAU;QACrB,MAAM,EAAE,qBAAqB;QAC7B,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,IAAI;QACV,GAAI,OAA+C;QACnD,YAAY,EAAE,eAAe;QAC7B,qBAAqB,EAAE,KAAK;KAC7B,CAAA;IACD,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,IAAI,CAAA;IACnC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAClD,OAAO,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;AACzE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { canonize } from './canonize.js';
2
+ import { createVerifier } from '../core/createVerifier.js';
3
+ export declare const eddsaRdfc2022: {
4
+ canonize: typeof canonize;
5
+ createVerifier: typeof createVerifier;
6
+ name: string;
7
+ requiredAlgorithm: string;
8
+ };
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/eddsa-rdfc-2022/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAG1D,eAAO,MAAM,aAAa;;;;;CAKzB,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { canonize } from './canonize.js';
2
+ import { createVerifier } from '../core/createVerifier.js';
3
+ import { requiredAlgorithm } from '../core/requiredAlgorithm.js';
4
+ export const eddsaRdfc2022 = {
5
+ canonize,
6
+ createVerifier,
7
+ name: 'eddsa-rdfc-2022',
8
+ requiredAlgorithm
9
+ };
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/eddsa-rdfc-2022/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAEhE,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,QAAQ;IACR,cAAc;IACd,IAAI,EAAE,iBAAiB;IACvB,iBAAiB;CAClB,CAAA"}
@@ -0,0 +1,6 @@
1
+ export { Ed25519Signature2020, suiteContext } from './ed25519-signature-2020/index.js';
2
+ export { eddsaRdfc2022 } from './eddsa-rdfc-2022/index.js';
3
+ export { createSignCryptosuite, createVerifyCryptosuite } from './eddsa-jcs-2022/index.js';
4
+ export { createSigner, ensureSignerAlgorithm } from './core/createSigner.js';
5
+ export { createVerifier } from './core/createVerifier.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAC1F,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { Ed25519Signature2020, suiteContext } from './ed25519-signature-2020/index.js';
2
+ export { eddsaRdfc2022 } from './eddsa-rdfc-2022/index.js';
3
+ export { createSignCryptosuite, createVerifyCryptosuite } from './eddsa-jcs-2022/index.js';
4
+ export { createSigner, ensureSignerAlgorithm } from './core/createSigner.js';
5
+ export { createVerifier } from './core/createVerifier.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAC1F,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA"}
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "@interop/ed25519-signature",
3
+ "version": "6.0.0",
4
+ "description": "Ed25519 Linked Data / Data Integrity signature suites (Ed25519Signature2020, eddsa-rdfc-2022, eddsa-jcs-2022) in TypeScript.",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./ed25519-signature-2020": {
13
+ "types": "./dist/ed25519-signature-2020/index.d.ts",
14
+ "default": "./dist/ed25519-signature-2020/index.js"
15
+ },
16
+ "./eddsa-rdfc-2022": {
17
+ "types": "./dist/eddsa-rdfc-2022/index.d.ts",
18
+ "default": "./dist/eddsa-rdfc-2022/index.js"
19
+ },
20
+ "./eddsa-jcs-2022": {
21
+ "types": "./dist/eddsa-jcs-2022/index.d.ts",
22
+ "default": "./dist/eddsa-jcs-2022/index.js"
23
+ }
24
+ },
25
+ "browser": {
26
+ "./dist/core/sha256.js": "./dist/core/sha256-browser.js"
27
+ },
28
+ "module": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "files": [
31
+ "dist",
32
+ "CHANGELOG.md",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "build": "pnpm run clear && tsc",
38
+ "clear": "rimraf dist/*",
39
+ "dev": "vite",
40
+ "fix": "eslint --fix src test && pnpm run format",
41
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
42
+ "lint": "eslint src test",
43
+ "typecheck": "tsc -p tsconfig.dev.json --noEmit",
44
+ "prepare": "pnpm run build",
45
+ "rebuild": "pnpm run clear && pnpm run build",
46
+ "test": "pnpm run lint && pnpm run typecheck && pnpm run test-node",
47
+ "test-browser": "playwright test",
48
+ "test-node": "vitest run",
49
+ "test-coverage": "vitest run --coverage"
50
+ },
51
+ "homepage": "https://github.com/interop-alliance/ed25519-signature",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/interop-alliance/ed25519-signature.git"
55
+ },
56
+ "license": "BSD-3-Clause",
57
+ "dependencies": {
58
+ "@digitalbazaar/data-integrity": "^2.5.0",
59
+ "@interop/ed25519-verification-key": "^6.2.0",
60
+ "@interop/jsonld": "^9.0.2",
61
+ "canonicalize": "^2.0.0",
62
+ "ed25519-signature-2020-context": "^1.1.0",
63
+ "rdf-canonize": "^5.0.0"
64
+ },
65
+ "peerDependencies": {
66
+ "@interop/jsonld-signatures": "^11.6.2"
67
+ },
68
+ "peerDependenciesMeta": {
69
+ "@interop/jsonld-signatures": {
70
+ "optional": true
71
+ }
72
+ },
73
+ "devDependencies": {
74
+ "@interop/security-document-loader": "^9.0.0",
75
+ "@eslint/js": "^10.0.1",
76
+ "@interop/jsonld-signatures": "^11.6.2",
77
+ "@playwright/test": "^1.60.0",
78
+ "@types/node": "^25.9.1",
79
+ "@vitest/coverage-v8": "^4.1.7",
80
+ "eslint": "^10.4.0",
81
+ "eslint-config-prettier": "^10.1.8",
82
+ "globals": "^17.6.0",
83
+ "prettier": "^3.8.3",
84
+ "rimraf": "^6.1.3",
85
+ "typescript": "^5.5.0",
86
+ "typescript-eslint": "^8.59.4",
87
+ "vite": "^8.0.14",
88
+ "vitest": "^4.1.7"
89
+ },
90
+ "publishConfig": {
91
+ "access": "public"
92
+ },
93
+ "packageManager": "pnpm@11.3.0",
94
+ "engines": {
95
+ "node": ">=24.0"
96
+ }
97
+ }