@sd-jwt/core 0.20.1 → 0.21.0-alpha-20260916100413

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 (68) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +82 -80
  3. package/dist/index.cjs +1526 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +696 -0
  6. package/dist/index.d.mts +537 -527
  7. package/dist/index.mjs +1422 -1998
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +29 -49
  10. package/CHANGELOG.md +0 -39
  11. package/dist/index.d.ts +0 -686
  12. package/dist/index.js +0 -2100
  13. package/src/decode/decode.ts +0 -407
  14. package/src/decode/index.ts +0 -1
  15. package/src/decoy.ts +0 -15
  16. package/src/flattenJSON.ts +0 -99
  17. package/src/generalJSON.ts +0 -157
  18. package/src/index.ts +0 -1000
  19. package/src/jwt.ts +0 -286
  20. package/src/kbjwt.ts +0 -101
  21. package/src/present/index.ts +0 -1
  22. package/src/present/present.ts +0 -216
  23. package/src/sdjwt.ts +0 -384
  24. package/src/test/decode/decode.spec.ts +0 -197
  25. package/src/test/decoy.spec.ts +0 -30
  26. package/src/test/flattenJSON.spec.ts +0 -122
  27. package/src/test/generalJSON.spec.ts +0 -198
  28. package/src/test/index.spec.ts +0 -986
  29. package/src/test/jwt.spec.ts +0 -301
  30. package/src/test/kbjwt.spec.ts +0 -555
  31. package/src/test/pass.spec.ts +0 -7
  32. package/src/test/present/present.spec.ts +0 -305
  33. package/src/test/sdjwt.spec.ts +0 -384
  34. package/src/test/types/type.spec.ts +0 -88
  35. package/src/test/utils/base64url.spec.ts +0 -33
  36. package/src/test/utils/disclosure.spec.ts +0 -170
  37. package/src/test/utils/error.spec.ts +0 -15
  38. package/src/types/index.ts +0 -2
  39. package/src/types/type.ts +0 -270
  40. package/src/types/verification-error.ts +0 -55
  41. package/src/utils/base64url.ts +0 -6
  42. package/src/utils/disclosure.ts +0 -121
  43. package/src/utils/error.ts +0 -25
  44. package/src/utils/index.ts +0 -3
  45. package/src/utils/strict-json.ts +0 -17
  46. package/test/app-e2e.spec.ts +0 -292
  47. package/test/array_data_types.json +0 -31
  48. package/test/array_full_sd.json +0 -21
  49. package/test/array_in_sd.json +0 -13
  50. package/test/array_nested_in_plain.json +0 -29
  51. package/test/array_none_disclosed.json +0 -17
  52. package/test/array_of_nulls.json +0 -15
  53. package/test/array_of_objects.json +0 -65
  54. package/test/array_of_scalars.json +0 -19
  55. package/test/array_recursive_sd.json +0 -35
  56. package/test/array_recursive_sd_some_disclosed.json +0 -63
  57. package/test/complex.json +0 -43
  58. package/test/header_mod.json +0 -48
  59. package/test/json_serialization.json +0 -48
  60. package/test/key_binding.json +0 -48
  61. package/test/no_sd.json +0 -36
  62. package/test/object_data_types.json +0 -62
  63. package/test/recursions.json +0 -117
  64. package/test/rfc9901-audit-fixes.spec.ts +0 -252
  65. package/test/rfc9901-validation.spec.ts +0 -150
  66. package/test/tsconfig.json +0 -4
  67. package/tsconfig.json +0 -7
  68. package/vitest.config.mts +0 -4
@@ -1,305 +0,0 @@
1
- import { hasher as digest } from '@owf/crypto';
2
- import { describe, expect, test } from 'vitest';
3
- import { decodeSdJwt, decodeSdJwtSync } from '../../decode';
4
- import {
5
- present,
6
- presentableKeys,
7
- presentableKeysSync,
8
- presentSync,
9
- type SerializedDisclosure,
10
- selectDisclosures,
11
- transformPresentationFrame,
12
- } from '../../present';
13
- import type { PresentationFrame } from '../../types';
14
-
15
- describe('Present tests', () => {
16
- test('presentableKeys', async () => {
17
- const sdjwt =
18
- 'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
19
- const decodedSdJwt = await decodeSdJwt(sdjwt, digest);
20
- const keys = await presentableKeys(
21
- decodedSdJwt.jwt.payload,
22
- decodedSdJwt.disclosures,
23
- digest,
24
- );
25
- expect(keys).toStrictEqual(['arr', 'arr.0', 'arr.2.a', 'foo', 'test.zzz']);
26
- });
27
-
28
- test('presentableKeys sync', () => {
29
- const sdjwt =
30
- 'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
31
- const decodedSdJwt = decodeSdJwtSync(sdjwt, digest);
32
- const keys = presentableKeysSync(
33
- decodedSdJwt.jwt.payload,
34
- decodedSdJwt.disclosures,
35
- digest,
36
- );
37
- expect(keys).toStrictEqual(['arr', 'arr.0', 'arr.2.a', 'foo', 'test.zzz']);
38
- });
39
-
40
- test('present', async () => {
41
- const sdjwt =
42
- 'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
43
- const presentedSdJwt = await present(
44
- sdjwt,
45
- {
46
- foo: true,
47
- arr: {
48
- 0: true,
49
- },
50
- test: {
51
- zzz: true,
52
- },
53
- },
54
- digest,
55
- );
56
- expect(presentedSdJwt).toStrictEqual(
57
- 'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~',
58
- );
59
- });
60
-
61
- test('present sync', () => {
62
- const sdjwt =
63
- 'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIwNGU0MjAzOWU4ZWFiOWRjIiwiYSIsIjEiXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~';
64
- const presentedSdJwt = presentSync(
65
- sdjwt,
66
- {
67
- foo: true,
68
- arr: {
69
- 0: true,
70
- },
71
- test: {
72
- zzz: true,
73
- },
74
- },
75
- digest,
76
- );
77
- expect(presentedSdJwt).toStrictEqual(
78
- 'eyJ0eXAiOiJzZC1qd3QiLCJhbGciOiJFZERTQSJ9.eyJ0ZXN0Ijp7Il9zZCI6WyJqVEszMHNleDZhYV9kUk1KSWZDR056Q0FwbVB5MzRRNjNBa3QzS3hhSktzIl19LCJfc2QiOlsiME9nMi1ReG95eW1UOGNnVzZZUjVSSFpQLUJuR2tHUi1NM2otLV92RWlzSSIsIkcwZ3lHNnExVFMyUlQxMkZ3X2RRRDVVcjlZc1AwZlVWOXVtQWdGMC1jQ1EiXSwiX3NkX2FsZyI6InNoYS0yNTYifQ.ggEyE4SeDO2Hu3tol3VLmi7NQj56yKzKQDaafocgkLrUBdivghohtzrfcbrMN7CRufJ_Cnh0EL54kymXLGTdDQ~WyIxYzdmOTE4ZTE0MjA2NzZiIiwiZm9vIiwiYmFyIl0~WyJmZjYxYzQ5ZGU2NjFiYzMxIiwiYXJyIixbeyIuLi4iOiJTSG96VW5KNUpkd0ZtTjVCbXB5dXZCWGZfZWRjckVvcExPYThTVlBFUmg0In0sIjIiLHsiX3NkIjpbIkpuODNhZkp0OGx4NG1FMzZpRkZyS2U2R2VnN0dlVUQ4Z3UwdVo3NnRZcW8iXX1dXQ~WyIwOGE1Yjc5MjMyYjAzYzBhIiwiMSJd~WyJiNWE2YjUzZGQwYTFmMGIwIiwienp6IiwieHh4Il0~',
79
- );
80
- });
81
-
82
- test('transform an object for a presentation to a list', () => {
83
- const claims = {
84
- firstname: 'John',
85
- lastname: 'Doe',
86
- ssn: '123-45-6789',
87
- id: '1234',
88
- data: {
89
- firstname: 'John',
90
- lastname: 'Doe',
91
- ssn: '123-45-6789',
92
- list: [{ r: 'd' }, 'b', 'c'],
93
- list2: ['1', '2', '3'],
94
- list3: ['1', null, 2],
95
- },
96
- data2: {
97
- hi: 'bye',
98
- },
99
- };
100
-
101
- const presentFrame: PresentationFrame<typeof claims> = {
102
- firstname: true,
103
- data: {
104
- firstname: true,
105
- list: {
106
- 1: true,
107
- 0: {
108
- r: true,
109
- },
110
- },
111
- list2: {
112
- 1: true,
113
- },
114
- list3: true,
115
- },
116
- data2: true,
117
- };
118
-
119
- const list = transformPresentationFrame(presentFrame);
120
- expect(list).toStrictEqual([
121
- 'firstname',
122
- 'data',
123
- 'data.firstname',
124
- 'data.list',
125
- 'data.list.0',
126
- 'data.list.0.r',
127
- 'data.list.1',
128
- 'data.list2',
129
- 'data.list2.1',
130
- 'data.list3',
131
- 'data2',
132
- ]);
133
- });
134
-
135
- test('transform an object for a presentation to a list, but with faulty inputs', () => {
136
- const claims = {
137
- name: 'John',
138
- address: {
139
- city: 'New York',
140
- street: '5th Avenue',
141
- },
142
- };
143
-
144
- const obj: PresentationFrame<typeof claims> = {
145
- name: false,
146
- address: {
147
- city: true,
148
- street: true,
149
- },
150
- };
151
- const list = transformPresentationFrame(obj);
152
- expect(list).toStrictEqual(['address', 'address.city', 'address.street']);
153
- });
154
-
155
- test('select disclosures', () => {
156
- const payload = {
157
- lastname: 'Doe',
158
- _sd: [
159
- 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU',
160
- 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4',
161
- 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14',
162
- ],
163
- _sd_alg: 'sha-256',
164
- };
165
-
166
- const presentationFrame = {
167
- firstname: true,
168
- //ssn: true,
169
- id: true,
170
- };
171
-
172
- const disclosures: SerializedDisclosure[] = [
173
- {
174
- digest: 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU',
175
- encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd',
176
- salt: 'b04760b9810823fa',
177
- key: 'firstname',
178
- value: 'John',
179
- },
180
- {
181
- digest: 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4',
182
- encoded: 'WyJjNTQwZWE4YjJhOTNmZDE1Iiwic3NuIiwiMTIzLTQ1LTY3ODkiXQ',
183
- salt: 'c540ea8b2a93fd15',
184
- key: 'ssn',
185
- value: '123-45-6789',
186
- },
187
- {
188
- digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14',
189
- encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0',
190
- salt: '97f055de944af729',
191
- key: 'id',
192
- value: '1234',
193
- },
194
- ];
195
-
196
- const selected = selectDisclosures(payload, disclosures, presentationFrame);
197
- expect(selected).toStrictEqual([
198
- {
199
- digest: 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU',
200
- encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd',
201
- salt: 'b04760b9810823fa',
202
- key: 'firstname',
203
- value: 'John',
204
- },
205
- {
206
- digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14',
207
- encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0',
208
- salt: '97f055de944af729',
209
- key: 'id',
210
- value: '1234',
211
- },
212
- ]);
213
- });
214
-
215
- test('select disclosures no input', () => {
216
- const selected = selectDisclosures({}, [], {});
217
- expect(selected).toStrictEqual([]);
218
- });
219
-
220
- test('select disclosures noting return', () => {
221
- const payload = {
222
- lastname: 'Doe',
223
- _sd: [
224
- 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU',
225
- 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4',
226
- 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14',
227
- ],
228
- _sd_alg: 'sha-256',
229
- };
230
-
231
- const presentationFrame = {};
232
-
233
- const disclosures: SerializedDisclosure[] = [
234
- {
235
- digest: 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU',
236
- encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd',
237
- salt: 'b04760b9810823fa',
238
- key: 'firstname',
239
- value: 'John',
240
- },
241
- {
242
- digest: 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4',
243
- encoded: 'WyJjNTQwZWE4YjJhOTNmZDE1Iiwic3NuIiwiMTIzLTQ1LTY3ODkiXQ',
244
- salt: 'c540ea8b2a93fd15',
245
- key: 'ssn',
246
- value: '123-45-6789',
247
- },
248
- {
249
- digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14',
250
- encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0',
251
- salt: '97f055de944af729',
252
- key: 'id',
253
- value: '1234',
254
- },
255
- ];
256
- const selected = selectDisclosures(payload, disclosures, presentationFrame);
257
- expect(selected).toStrictEqual([]);
258
- });
259
-
260
- test('expect missing digest', () => {
261
- const payload = {
262
- lastname: 'Doe',
263
- _sd: [
264
- 'COnqXH7wGBFGR1ao12sDwTfu84Zs7cq92CZIg8ulIuU',
265
- 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4',
266
- 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14',
267
- ],
268
- _sd_alg: 'sha-256',
269
- };
270
-
271
- const presentationFrame = {
272
- firstname: true,
273
- //ssn: true,
274
- id: true,
275
- };
276
-
277
- const disclosures: SerializedDisclosure[] = [
278
- //@ts-expect-error
279
- {
280
- encoded: 'WyJiMDQ3NjBiOTgxMDgyM2ZhIiwiZmlyc3RuYW1lIiwiSm9obiJd',
281
- salt: 'b04760b9810823fa',
282
- key: 'firstname',
283
- value: 'John',
284
- },
285
- {
286
- digest: 'RrOc4ZfBVyD6iNlMbtmdokZOti322mOXfvIOBKvpuc4',
287
- encoded: 'WyJjNTQwZWE4YjJhOTNmZDE1Iiwic3NuIiwiMTIzLTQ1LTY3ODkiXQ',
288
- salt: 'c540ea8b2a93fd15',
289
- key: 'ssn',
290
- value: '123-45-6789',
291
- },
292
- {
293
- digest: 'aXqInKwHoE1l8OM1VNUQDqTPeNUG1cMJVwVbxZJpP14',
294
- encoded: 'WyI5N2YwNTVkZTk0NGFmNzI5IiwiaWQiLCIxMjM0Il0',
295
- salt: '97f055de944af729',
296
- key: 'id',
297
- value: '1234',
298
- },
299
- ];
300
-
301
- expect(() =>
302
- selectDisclosures(payload, disclosures, presentationFrame),
303
- ).toThrowError('Unreferenced disclosure(s) detected in SD-JWT');
304
- });
305
- });
@@ -1,384 +0,0 @@
1
- import Crypto from 'node:crypto';
2
- import { generateSalt, hasher } from '@owf/crypto';
3
- import { describe, expect, test } from 'vitest';
4
- import { createHashMapping, unpack } from '../decode';
5
- import { Jwt } from '../jwt';
6
- import { listKeys, pack, SDJwt } from '../sdjwt';
7
- import type { DisclosureFrame, Signer } from '../types';
8
- import { Disclosure } from '../utils';
9
-
10
- const hash = { alg: 'SHA256', hasher };
11
-
12
- describe('SD JWT', () => {
13
- test('create and encode', async () => {
14
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
15
- const testSigner: Signer = async (data: string) => {
16
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
17
- return Buffer.from(sig).toString('base64url');
18
- };
19
-
20
- const jwt = new Jwt({
21
- header: { alg: 'EdDSA' },
22
- payload: { foo: 'bar' },
23
- });
24
-
25
- await jwt.sign(testSigner);
26
- const sdJwt = new SDJwt({
27
- jwt,
28
- disclosures: [],
29
- });
30
- expect(sdJwt).toBeDefined();
31
-
32
- const encoded = sdJwt.encodeSDJwt();
33
- expect(encoded).toBeDefined();
34
- });
35
-
36
- test('decode', async () => {
37
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
38
- const testSigner: Signer = async (data: string) => {
39
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
40
- return Buffer.from(sig).toString('base64url');
41
- };
42
-
43
- const jwt = new Jwt({
44
- header: { alg: 'EdDSA' },
45
- payload: { foo: 'bar', _sd_alg: 'sha-256' },
46
- });
47
-
48
- await jwt.sign(testSigner);
49
- const sdJwt = new SDJwt({
50
- jwt,
51
- disclosures: [],
52
- });
53
-
54
- const encoded = sdJwt.encodeSDJwt();
55
-
56
- const newSdJwt = await SDJwt.fromEncode(encoded, hasher);
57
- expect(newSdJwt).toBeDefined();
58
- const newJwt = newSdJwt.jwt;
59
- expect(newJwt?.header).toEqual(jwt.header);
60
- expect(newJwt?.payload).toEqual(jwt.payload);
61
- expect(newJwt?.signature).toEqual(jwt.signature);
62
- });
63
-
64
- test('decode compatibilty', async () => {
65
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
66
- const testSigner: Signer = async (data: string) => {
67
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
68
- return Buffer.from(sig).toString('base64url');
69
- };
70
-
71
- const jwt = new Jwt({
72
- header: { alg: 'EdDSA' },
73
- payload: { foo: 'bar' },
74
- });
75
-
76
- await jwt.sign(testSigner);
77
- const sdJwt = new SDJwt({
78
- jwt,
79
- disclosures: [],
80
- });
81
-
82
- const encoded = sdJwt.encodeSDJwt();
83
-
84
- const newSdJwt = await SDJwt.fromEncode(encoded, hasher);
85
- expect(newSdJwt).toBeDefined();
86
- const newJwt = newSdJwt.jwt;
87
- expect(newJwt?.header).toEqual(jwt.header);
88
- expect(newJwt?.payload).toEqual(jwt.payload);
89
- expect(newJwt?.signature).toEqual(jwt.signature);
90
- });
91
-
92
- test('keys', async () => {
93
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
94
- const testSigner: Signer = async (data: string) => {
95
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
96
- return Buffer.from(sig).toString('base64url');
97
- };
98
- const jwt = new Jwt({
99
- header: { alg: 'EdDSA' },
100
- payload: { foo: 'bar' },
101
- });
102
-
103
- await jwt.sign(testSigner);
104
- const sdJwt = new SDJwt({
105
- jwt,
106
- disclosures: [],
107
- });
108
-
109
- const keys = await sdJwt.keys(hasher);
110
- expect(keys).toBeDefined();
111
- expect(keys).toEqual(['foo']);
112
- });
113
-
114
- test('presentable keys', async () => {
115
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
116
- const testSigner: Signer = async (data: string) => {
117
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
118
- return Buffer.from(sig).toString('base64url');
119
- };
120
-
121
- const jwt = new Jwt({
122
- header: { alg: 'EdDSA' },
123
- payload: { foo: 'bar' },
124
- });
125
-
126
- await jwt.sign(testSigner);
127
- const sdJwt = new SDJwt({
128
- jwt,
129
- disclosures: [],
130
- });
131
-
132
- const keys = await sdJwt.presentableKeys(hasher);
133
- expect(keys).toBeDefined();
134
- expect(keys).toEqual([]);
135
- });
136
-
137
- test('claims', async () => {
138
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
139
- const testSigner: Signer = async (data: string) => {
140
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
141
- return Buffer.from(sig).toString('base64url');
142
- };
143
-
144
- const jwt = new Jwt({
145
- header: { alg: 'EdDSA' },
146
- payload: { foo: 'bar' },
147
- });
148
-
149
- await jwt.sign(testSigner);
150
- const sdJwt = new SDJwt({
151
- jwt,
152
- disclosures: [],
153
- });
154
-
155
- const claims = await sdJwt.getClaims(hasher);
156
- expect(claims).toBeDefined();
157
- expect(claims).toEqual({
158
- foo: 'bar',
159
- });
160
- });
161
-
162
- test('pack', async () => {
163
- const claim = {
164
- firstname: 'John',
165
- lastname: 'Doe',
166
- };
167
-
168
- const { packedClaims, disclosures } = await pack(
169
- claim,
170
- {
171
- _sd: ['firstname'],
172
- },
173
- hash,
174
- generateSalt,
175
- );
176
-
177
- expect(disclosures).toBeDefined();
178
- expect(packedClaims).toBeDefined();
179
-
180
- expect(disclosures.length).toEqual(1);
181
- expect(disclosures[0].key).toEqual('firstname');
182
- expect(disclosures[0].value).toEqual('John');
183
-
184
- expect(packedClaims._sd).toBeDefined();
185
- expect(packedClaims._sd.length).toEqual(1);
186
- expect(packedClaims.lastname).toEqual('Doe');
187
- });
188
-
189
- test('list keys', () => {
190
- const data = {
191
- a: {
192
- b: {
193
- c: 1,
194
- },
195
- d: [
196
- {
197
- e: 'fasfdsa',
198
- f: 1234,
199
- },
200
- 3,
201
- 4,
202
- ],
203
- },
204
- g: [['h'], 'i'],
205
- };
206
-
207
- const keys = listKeys(data);
208
- expect(keys).toEqual([
209
- 'a',
210
- 'a.b',
211
- 'a.b.c',
212
- 'a.d',
213
- 'a.d.0',
214
- 'a.d.0.e',
215
- 'a.d.0.f',
216
- 'a.d.1',
217
- 'a.d.2',
218
- 'g',
219
- 'g.0',
220
- 'g.0.0',
221
- 'g.1',
222
- ]);
223
- });
224
-
225
- test('presentable keys', async () => {
226
- const claim = {
227
- firstname: 'John',
228
- lastname: 'Doe',
229
- };
230
-
231
- const { packedClaims, disclosures } = await pack(
232
- claim,
233
- {
234
- _sd: ['firstname'],
235
- },
236
- hash,
237
- generateSalt,
238
- );
239
-
240
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
241
- const testSigner: Signer = async (data: string) => {
242
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
243
- return Buffer.from(sig).toString('base64url');
244
- };
245
- const jwt = new Jwt({
246
- header: { alg: 'EdDSA' },
247
- payload: packedClaims,
248
- });
249
-
250
- await jwt.sign(testSigner);
251
- const sdJwt = new SDJwt({
252
- jwt,
253
- disclosures,
254
- });
255
-
256
- const keys = await sdJwt.presentableKeys(hasher);
257
-
258
- expect(keys).toBeDefined();
259
- expect(keys).toEqual(['firstname']);
260
- });
261
-
262
- test('hash map', async () => {
263
- const claim = {
264
- firstname: 'John',
265
- lastname: 'Doe',
266
- };
267
-
268
- const { disclosures } = await pack(
269
- claim,
270
- {
271
- _sd: ['firstname'],
272
- },
273
- hash,
274
- generateSalt,
275
- );
276
-
277
- const mapping = await createHashMapping(disclosures, hash);
278
- expect(mapping).toBeDefined();
279
- expect(Object.keys(mapping).length).toEqual(1);
280
- expect(mapping[Object.keys(mapping)[0]]).toBeInstanceOf(Disclosure);
281
- });
282
-
283
- test('unpack', async () => {
284
- const claim = {
285
- firstname: 'John',
286
- lastname: 'Doe',
287
- };
288
-
289
- const { packedClaims, disclosures } = await pack(
290
- claim,
291
- {
292
- _sd: ['firstname'],
293
- },
294
- hash,
295
- generateSalt,
296
- );
297
-
298
- const { disclosureKeymap, unpackedObj } = await unpack(
299
- packedClaims,
300
- disclosures,
301
- hasher,
302
- );
303
- expect(disclosureKeymap).toBeDefined();
304
- expect(unpackedObj).toBeDefined();
305
- expect(unpackedObj).toEqual({
306
- firstname: 'John',
307
- lastname: 'Doe',
308
- });
309
- expect(disclosureKeymap.firstname).toBeDefined();
310
- expect(typeof disclosureKeymap.firstname).toEqual('string');
311
- });
312
-
313
- test('pack and unpack', async () => {
314
- const claims = {
315
- firstname: 'John',
316
- lastname: 'Doe',
317
- ssn: '123-45-6789',
318
- id: '1234',
319
- data: {
320
- firstname: 'John',
321
- lastname: 'Doe',
322
- ssn: '123-45-6789',
323
- list: [{ r: '1' }, 'b', 'c'],
324
- },
325
- data2: {
326
- hi: 'bye',
327
- },
328
- };
329
-
330
- const disclosureFrame: DisclosureFrame<typeof claims> = {
331
- _sd: ['firstname', 'id', 'data2'],
332
- data: {
333
- _sd: ['list'],
334
- _sd_decoy: 2,
335
- list: {
336
- _sd: [0, 2],
337
- _sd_decoy: 1,
338
- 0: {
339
- _sd: ['r'],
340
- },
341
- },
342
- },
343
- data2: {
344
- _sd: ['hi'],
345
- },
346
- };
347
-
348
- const { packedClaims, disclosures } = await pack(
349
- claims,
350
- disclosureFrame,
351
- hash,
352
- generateSalt,
353
- );
354
- const { unpackedObj } = await unpack(packedClaims, disclosures, hasher);
355
-
356
- expect(unpackedObj).toEqual(claims);
357
- });
358
-
359
- test('no disclosures', async () => {
360
- const { privateKey } = Crypto.generateKeyPairSync('ed25519');
361
- const testSigner: Signer = async (data: string) => {
362
- const sig = Crypto.sign(null, Buffer.from(data), privateKey);
363
- return Buffer.from(sig).toString('base64url');
364
- };
365
-
366
- const jwt = new Jwt({
367
- header: { alg: 'EdDSA' },
368
- payload: { foo: 'bar' },
369
- });
370
-
371
- await jwt.sign(testSigner);
372
- const sdJwt = new SDJwt({
373
- jwt,
374
- disclosures: [],
375
- });
376
-
377
- const credential = sdJwt.encodeSDJwt();
378
- const decoded = await SDJwt.decodeSDJwt(credential, hasher);
379
- expect(jwt.header).toEqual(decoded.jwt.header);
380
- expect(jwt.payload).toEqual(decoded.jwt.payload);
381
- expect(jwt.signature).toEqual(decoded.jwt.signature);
382
- expect(decoded.disclosures).toEqual([]);
383
- });
384
- });