@sd-jwt/present 0.4.0 → 0.4.1-next.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.
package/dist/index.d.mts CHANGED
@@ -13,5 +13,22 @@ declare const presentSync: <T extends Record<string, unknown>>(sdJwt: string, pr
13
13
  * @returns
14
14
  */
15
15
  declare const transformPresentationFrame: <T extends object>(obj: PresentationFrame<T>, prefix?: string) => string[];
16
+ type SerializedDisclosure = {
17
+ digest: string;
18
+ encoded: string;
19
+ salt: string;
20
+ key: string | undefined;
21
+ value: unknown;
22
+ };
23
+ declare const createHashMappingForSerializedDisclosure: (disclosures: SerializedDisclosure[]) => Record<string, Disclosure<unknown>>;
24
+ /**
25
+ * This function selects the serialized disclosures from the payload
26
+ * and array of serialized disclosure based on the presentation frame.
27
+ * If you want to know what is serialized disclosures, check type SerializedDisclosure.
28
+ * @param payload: Record<string, unknown>
29
+ * @param disclosures: SerializedDisclosure[]
30
+ * @param presentationFrame: PresentationFrame<T>
31
+ */
32
+ declare const selectDisclosures: <T extends Record<string, unknown>>(payload: Record<string, unknown>, disclosures: SerializedDisclosure[], presentationFrame: PresentationFrame<T>) => SerializedDisclosure[];
16
33
 
17
- export { present, presentSync, presentableKeys, presentableKeysSync, transformPresentationFrame };
34
+ export { type SerializedDisclosure, createHashMappingForSerializedDisclosure, present, presentSync, presentableKeys, presentableKeysSync, selectDisclosures, transformPresentationFrame };
package/dist/index.d.ts CHANGED
@@ -13,5 +13,22 @@ declare const presentSync: <T extends Record<string, unknown>>(sdJwt: string, pr
13
13
  * @returns
14
14
  */
15
15
  declare const transformPresentationFrame: <T extends object>(obj: PresentationFrame<T>, prefix?: string) => string[];
16
+ type SerializedDisclosure = {
17
+ digest: string;
18
+ encoded: string;
19
+ salt: string;
20
+ key: string | undefined;
21
+ value: unknown;
22
+ };
23
+ declare const createHashMappingForSerializedDisclosure: (disclosures: SerializedDisclosure[]) => Record<string, Disclosure<unknown>>;
24
+ /**
25
+ * This function selects the serialized disclosures from the payload
26
+ * and array of serialized disclosure based on the presentation frame.
27
+ * If you want to know what is serialized disclosures, check type SerializedDisclosure.
28
+ * @param payload: Record<string, unknown>
29
+ * @param disclosures: SerializedDisclosure[]
30
+ * @param presentationFrame: PresentationFrame<T>
31
+ */
32
+ declare const selectDisclosures: <T extends Record<string, unknown>>(payload: Record<string, unknown>, disclosures: SerializedDisclosure[], presentationFrame: PresentationFrame<T>) => SerializedDisclosure[];
16
33
 
17
- export { present, presentSync, presentableKeys, presentableKeysSync, transformPresentationFrame };
34
+ export { type SerializedDisclosure, createHashMappingForSerializedDisclosure, present, presentSync, presentableKeys, presentableKeysSync, selectDisclosures, transformPresentationFrame };
package/dist/index.js CHANGED
@@ -40,16 +40,19 @@ var __async = (__this, __arguments, generator) => {
40
40
  // src/index.ts
41
41
  var src_exports = {};
42
42
  __export(src_exports, {
43
+ createHashMappingForSerializedDisclosure: () => createHashMappingForSerializedDisclosure,
43
44
  present: () => present,
44
45
  presentSync: () => presentSync,
45
46
  presentableKeys: () => presentableKeys,
46
47
  presentableKeysSync: () => presentableKeysSync,
48
+ selectDisclosures: () => selectDisclosures,
47
49
  transformPresentationFrame: () => transformPresentationFrame
48
50
  });
49
51
  module.exports = __toCommonJS(src_exports);
50
52
 
51
53
  // src/present.ts
52
54
  var import_types = require("@sd-jwt/types");
55
+ var import_utils = require("@sd-jwt/utils");
53
56
  var import_decode = require("@sd-jwt/decode");
54
57
  var presentableKeys = (rawPayload, disclosures, hasher) => __async(void 0, null, function* () {
55
58
  const { disclosureKeymap } = yield (0, import_decode.unpack)(rawPayload, disclosures, hasher);
@@ -111,11 +114,52 @@ var transformPresentationFrame = (obj, prefix = "") => {
111
114
  return acc;
112
115
  }, []);
113
116
  };
117
+ var createHashMappingForSerializedDisclosure = (disclosures) => {
118
+ const map = {};
119
+ for (let i = 0; i < disclosures.length; i++) {
120
+ const disclosure = disclosures[i];
121
+ const { digest, encoded, key, salt, value } = disclosure;
122
+ map[digest] = import_utils.Disclosure.fromArray(
123
+ key ? [salt, key, value] : [salt, value],
124
+ { digest, encoded }
125
+ );
126
+ }
127
+ return map;
128
+ };
129
+ var selectDisclosures = (payload, disclosures, presentationFrame) => {
130
+ if (disclosures.length === 0) {
131
+ return [];
132
+ }
133
+ const hashmap = createHashMappingForSerializedDisclosure(disclosures);
134
+ const { disclosureKeymap } = (0, import_decode.unpackObj)(payload, hashmap);
135
+ const keys = transformPresentationFrame(presentationFrame);
136
+ const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
137
+ const selectedDisclosures = presentedDisclosures.map(
138
+ (d) => {
139
+ const { salt, key, value, _digest } = d;
140
+ if (!_digest) {
141
+ throw new import_utils.SDJWTException(
142
+ "Implementation error: _digest is not defined"
143
+ );
144
+ }
145
+ return {
146
+ digest: _digest,
147
+ encoded: d.encode(),
148
+ salt,
149
+ key,
150
+ value
151
+ };
152
+ }
153
+ );
154
+ return selectedDisclosures;
155
+ };
114
156
  // Annotate the CommonJS export names for ESM import in node:
115
157
  0 && (module.exports = {
158
+ createHashMappingForSerializedDisclosure,
116
159
  present,
117
160
  presentSync,
118
161
  presentableKeys,
119
162
  presentableKeysSync,
163
+ selectDisclosures,
120
164
  transformPresentationFrame
121
165
  });
package/dist/index.mjs CHANGED
@@ -20,7 +20,10 @@ var __async = (__this, __arguments, generator) => {
20
20
  };
21
21
 
22
22
  // src/present.ts
23
- import { SD_SEPARATOR } from "@sd-jwt/types";
23
+ import {
24
+ SD_SEPARATOR
25
+ } from "@sd-jwt/types";
26
+ import { Disclosure, SDJWTException } from "@sd-jwt/utils";
24
27
  import {
25
28
  createHashMapping,
26
29
  decodeSdJwt,
@@ -29,7 +32,8 @@ import {
29
32
  unpack,
30
33
  createHashMappingSync,
31
34
  decodeSdJwtSync,
32
- unpackSync
35
+ unpackSync,
36
+ unpackObj
33
37
  } from "@sd-jwt/decode";
34
38
  var presentableKeys = (rawPayload, disclosures, hasher) => __async(void 0, null, function* () {
35
39
  const { disclosureKeymap } = yield unpack(rawPayload, disclosures, hasher);
@@ -91,10 +95,51 @@ var transformPresentationFrame = (obj, prefix = "") => {
91
95
  return acc;
92
96
  }, []);
93
97
  };
98
+ var createHashMappingForSerializedDisclosure = (disclosures) => {
99
+ const map = {};
100
+ for (let i = 0; i < disclosures.length; i++) {
101
+ const disclosure = disclosures[i];
102
+ const { digest, encoded, key, salt, value } = disclosure;
103
+ map[digest] = Disclosure.fromArray(
104
+ key ? [salt, key, value] : [salt, value],
105
+ { digest, encoded }
106
+ );
107
+ }
108
+ return map;
109
+ };
110
+ var selectDisclosures = (payload, disclosures, presentationFrame) => {
111
+ if (disclosures.length === 0) {
112
+ return [];
113
+ }
114
+ const hashmap = createHashMappingForSerializedDisclosure(disclosures);
115
+ const { disclosureKeymap } = unpackObj(payload, hashmap);
116
+ const keys = transformPresentationFrame(presentationFrame);
117
+ const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
118
+ const selectedDisclosures = presentedDisclosures.map(
119
+ (d) => {
120
+ const { salt, key, value, _digest } = d;
121
+ if (!_digest) {
122
+ throw new SDJWTException(
123
+ "Implementation error: _digest is not defined"
124
+ );
125
+ }
126
+ return {
127
+ digest: _digest,
128
+ encoded: d.encode(),
129
+ salt,
130
+ key,
131
+ value
132
+ };
133
+ }
134
+ );
135
+ return selectedDisclosures;
136
+ };
94
137
  export {
138
+ createHashMappingForSerializedDisclosure,
95
139
  present,
96
140
  presentSync,
97
141
  presentableKeys,
98
142
  presentableKeysSync,
143
+ selectDisclosures,
99
144
  transformPresentationFrame
100
145
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sd-jwt/present",
3
- "version": "0.4.0",
3
+ "version": "0.4.1-next.13+f92b3e2",
4
4
  "description": "sd-jwt draft 7 implementation in typescript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -38,12 +38,12 @@
38
38
  },
39
39
  "license": "Apache-2.0",
40
40
  "devDependencies": {
41
- "@sd-jwt/crypto-nodejs": "0.4.0"
41
+ "@sd-jwt/crypto-nodejs": "0.4.1-next.13+f92b3e2"
42
42
  },
43
43
  "dependencies": {
44
- "@sd-jwt/decode": "0.4.0",
45
- "@sd-jwt/types": "0.4.0",
46
- "@sd-jwt/utils": "0.4.0"
44
+ "@sd-jwt/decode": "0.4.1-next.13+f92b3e2",
45
+ "@sd-jwt/types": "0.4.1-next.13+f92b3e2",
46
+ "@sd-jwt/utils": "0.4.1-next.13+f92b3e2"
47
47
  },
48
48
  "publishConfig": {
49
49
  "access": "public"
@@ -61,5 +61,5 @@
61
61
  "esm"
62
62
  ]
63
63
  },
64
- "gitHead": "391a36550a66833b3d393ff0deb699b1b72cca59"
64
+ "gitHead": "f92b3e246371a83c51c5450b9bccb04753c58bf4"
65
65
  }
package/src/present.ts CHANGED
@@ -1,5 +1,9 @@
1
- import { Hasher, PresentationFrame, SD_SEPARATOR } from '@sd-jwt/types';
2
- import { Disclosure } from '@sd-jwt/utils';
1
+ import {
2
+ type Hasher,
3
+ type PresentationFrame,
4
+ SD_SEPARATOR,
5
+ } from '@sd-jwt/types';
6
+ import { Disclosure, SDJWTException } from '@sd-jwt/utils';
3
7
  import {
4
8
  createHashMapping,
5
9
  decodeSdJwt,
@@ -9,8 +13,9 @@ import {
9
13
  createHashMappingSync,
10
14
  decodeSdJwtSync,
11
15
  unpackSync,
16
+ unpackObj,
12
17
  } from '@sd-jwt/decode';
13
- import { HasherSync } from '@sd-jwt/types/src/type';
18
+ import type { HasherSync } from '@sd-jwt/types/src/type';
14
19
 
15
20
  // Presentable keys
16
21
  // The presentable keys are the path of JSON object that are presentable in the SD JWT
@@ -134,3 +139,73 @@ export const transformPresentationFrame = <T extends object>(
134
139
  return acc;
135
140
  }, []);
136
141
  };
142
+
143
+ export type SerializedDisclosure = {
144
+ digest: string;
145
+ encoded: string;
146
+ salt: string;
147
+ key: string | undefined;
148
+ value: unknown;
149
+ };
150
+
151
+ export const createHashMappingForSerializedDisclosure = (
152
+ disclosures: SerializedDisclosure[],
153
+ ) => {
154
+ const map: Record<string, Disclosure> = {};
155
+ for (let i = 0; i < disclosures.length; i++) {
156
+ const disclosure = disclosures[i];
157
+ const { digest, encoded, key, salt, value } = disclosure;
158
+ // we made Disclosure to fit the interface of unpack
159
+ map[digest] = Disclosure.fromArray(
160
+ key ? [salt, key, value] : [salt, value],
161
+ { digest, encoded },
162
+ );
163
+ }
164
+ return map;
165
+ };
166
+
167
+ /**
168
+ * This function selects the serialized disclosures from the payload
169
+ * and array of serialized disclosure based on the presentation frame.
170
+ * If you want to know what is serialized disclosures, check type SerializedDisclosure.
171
+ * @param payload: Record<string, unknown>
172
+ * @param disclosures: SerializedDisclosure[]
173
+ * @param presentationFrame: PresentationFrame<T>
174
+ */
175
+ export const selectDisclosures = <T extends Record<string, unknown>>(
176
+ payload: Record<string, unknown>,
177
+ disclosures: SerializedDisclosure[],
178
+ presentationFrame: PresentationFrame<T>,
179
+ ) => {
180
+ if (disclosures.length === 0) {
181
+ return [];
182
+ }
183
+
184
+ const hashmap = createHashMappingForSerializedDisclosure(disclosures);
185
+ const { disclosureKeymap } = unpackObj(payload, hashmap);
186
+ const keys = transformPresentationFrame(presentationFrame);
187
+
188
+ const presentedDisclosures = keys
189
+ .map((k) => hashmap[disclosureKeymap[k]])
190
+ .filter((d) => d !== undefined);
191
+
192
+ const selectedDisclosures: SerializedDisclosure[] = presentedDisclosures.map(
193
+ (d) => {
194
+ const { salt, key, value, _digest } = d;
195
+ if (!_digest) {
196
+ throw new SDJWTException(
197
+ 'Implementation error: _digest is not defined',
198
+ );
199
+ }
200
+ return {
201
+ digest: _digest,
202
+ encoded: d.encode(),
203
+ salt,
204
+ key,
205
+ value,
206
+ };
207
+ },
208
+ );
209
+
210
+ return selectedDisclosures;
211
+ };
@@ -1,14 +1,16 @@
1
1
  import { describe, expect, test } from 'vitest';
2
2
  import { digest } from '@sd-jwt/crypto-nodejs';
3
3
  import {
4
+ type SerializedDisclosure,
4
5
  present,
5
6
  presentSync,
6
7
  presentableKeys,
7
8
  presentableKeysSync,
9
+ selectDisclosures,
8
10
  transformPresentationFrame,
9
11
  } from '../index';
10
12
  import { decodeSdJwt, decodeSdJwtSync } from '@sd-jwt/decode';
11
- import { PresentationFrame } from '@sd-jwt/types';
13
+ import type { PresentationFrame } from '@sd-jwt/types';
12
14
 
13
15
  describe('Present tests', () => {
14
16
  test('presentableKeys', async () => {
@@ -149,4 +151,155 @@ describe('Present tests', () => {
149
151
  const list = transformPresentationFrame<typeof claims>(obj);
150
152
  expect(list).toStrictEqual(['address', 'address.city', 'address.street']);
151
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-ignore
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('Implementation error: _digest is not defined');
304
+ });
152
305
  });