@sd-jwt/present 0.4.0 → 0.4.1-next.2

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,21 @@ 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
+ /**
24
+ * This function selects the serialized disclosures from the payload
25
+ * and array of serialized disclosure based on the presentation frame.
26
+ * If you want to know what is serialized disclosures, check type SerializedDisclosure.
27
+ * @param payload: Record<string, unknown>
28
+ * @param disclosures: SerializedDisclosure[]
29
+ * @param presentationFrame: PresentationFrame<T>
30
+ */
31
+ declare const selectDisclosures: <T extends Record<string, unknown>>(payload: Record<string, unknown>, disclosures: SerializedDisclosure[], presentationFrame: PresentationFrame<T>) => SerializedDisclosure[];
16
32
 
17
- export { present, presentSync, presentableKeys, presentableKeysSync, transformPresentationFrame };
33
+ export { type SerializedDisclosure, present, presentSync, presentableKeys, presentableKeysSync, selectDisclosures, transformPresentationFrame };
package/dist/index.d.ts CHANGED
@@ -13,5 +13,21 @@ 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
+ /**
24
+ * This function selects the serialized disclosures from the payload
25
+ * and array of serialized disclosure based on the presentation frame.
26
+ * If you want to know what is serialized disclosures, check type SerializedDisclosure.
27
+ * @param payload: Record<string, unknown>
28
+ * @param disclosures: SerializedDisclosure[]
29
+ * @param presentationFrame: PresentationFrame<T>
30
+ */
31
+ declare const selectDisclosures: <T extends Record<string, unknown>>(payload: Record<string, unknown>, disclosures: SerializedDisclosure[], presentationFrame: PresentationFrame<T>) => SerializedDisclosure[];
16
32
 
17
- export { present, presentSync, presentableKeys, presentableKeysSync, transformPresentationFrame };
33
+ export { type SerializedDisclosure, present, presentSync, presentableKeys, presentableKeysSync, selectDisclosures, transformPresentationFrame };
package/dist/index.js CHANGED
@@ -44,12 +44,14 @@ __export(src_exports, {
44
44
  presentSync: () => presentSync,
45
45
  presentableKeys: () => presentableKeys,
46
46
  presentableKeysSync: () => presentableKeysSync,
47
+ selectDisclosures: () => selectDisclosures,
47
48
  transformPresentationFrame: () => transformPresentationFrame
48
49
  });
49
50
  module.exports = __toCommonJS(src_exports);
50
51
 
51
52
  // src/present.ts
52
53
  var import_types = require("@sd-jwt/types");
54
+ var import_utils = require("@sd-jwt/utils");
53
55
  var import_decode = require("@sd-jwt/decode");
54
56
  var presentableKeys = (rawPayload, disclosures, hasher) => __async(void 0, null, function* () {
55
57
  const { disclosureKeymap } = yield (0, import_decode.unpack)(rawPayload, disclosures, hasher);
@@ -111,11 +113,51 @@ var transformPresentationFrame = (obj, prefix = "") => {
111
113
  return acc;
112
114
  }, []);
113
115
  };
116
+ var createHashMappingForSerializedDisclosure = (disclosures) => {
117
+ const map = {};
118
+ for (let i = 0; i < disclosures.length; i++) {
119
+ const disclosure = disclosures[i];
120
+ const { digest, encoded, key, salt, value } = disclosure;
121
+ map[digest] = import_utils.Disclosure.fromArray(
122
+ key ? [salt, key, value] : [salt, value],
123
+ { digest, encoded }
124
+ );
125
+ }
126
+ return map;
127
+ };
128
+ var selectDisclosures = (payload, disclosures, presentationFrame) => {
129
+ if (disclosures.length === 0) {
130
+ return [];
131
+ }
132
+ const hashmap = createHashMappingForSerializedDisclosure(disclosures);
133
+ const { disclosureKeymap } = (0, import_decode.unpackObj)(payload, hashmap);
134
+ const keys = transformPresentationFrame(presentationFrame);
135
+ const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
136
+ const selectedDisclosures = presentedDisclosures.map(
137
+ (d) => {
138
+ const { salt, key, value, _digest } = d;
139
+ if (!_digest) {
140
+ throw new import_utils.SDJWTException(
141
+ "Implementation error: _digest is not defined"
142
+ );
143
+ }
144
+ return {
145
+ digest: _digest,
146
+ encoded: d.encode(),
147
+ salt,
148
+ key,
149
+ value
150
+ };
151
+ }
152
+ );
153
+ return selectedDisclosures;
154
+ };
114
155
  // Annotate the CommonJS export names for ESM import in node:
115
156
  0 && (module.exports = {
116
157
  present,
117
158
  presentSync,
118
159
  presentableKeys,
119
160
  presentableKeysSync,
161
+ selectDisclosures,
120
162
  transformPresentationFrame
121
163
  });
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,50 @@ 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 {
95
138
  present,
96
139
  presentSync,
97
140
  presentableKeys,
98
141
  presentableKeysSync,
142
+ selectDisclosures,
99
143
  transformPresentationFrame
100
144
  };
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.2+b11bedf",
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.2+b11bedf"
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.2+b11bedf",
45
+ "@sd-jwt/types": "0.4.1-next.2+b11bedf",
46
+ "@sd-jwt/utils": "0.4.1-next.2+b11bedf"
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": "b11bedfe62dd1827653a76226ebdca3e0da1bbe0"
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
+ 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
  });