@sd-jwt/core 0.2.1 → 2.0.2-next.26
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/LICENSE +201 -0
- package/dist/index.d.mts +106 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.js +606 -0
- package/dist/index.mjs +586 -0
- package/package.json +60 -48
- package/src/decoy.ts +15 -0
- package/src/index.ts +235 -0
- package/src/jwt.ts +107 -0
- package/src/kbjwt.ts +45 -0
- package/src/sdjwt.ts +318 -0
- package/src/test/decoy.spec.ts +30 -0
- package/src/test/index.spec.ts +379 -0
- package/src/test/jwt.spec.ts +141 -0
- package/src/test/kbjwt.spec.ts +275 -0
- package/src/test/pass.spec.ts +6 -0
- package/src/test/sdjwt.spec.ts +382 -0
- package/test/app-e2e.spec.ts +248 -0
- package/test/array_data_types.json +29 -0
- package/test/array_full_sd.json +21 -0
- package/test/array_in_sd.json +13 -0
- package/test/array_nested_in_plain.json +20 -0
- package/test/array_none_disclosed.json +17 -0
- package/test/array_of_nulls.json +15 -0
- package/test/array_of_objects.json +58 -0
- package/test/array_of_scalars.json +15 -0
- package/test/array_recursive_sd.json +35 -0
- package/test/array_recursive_sd_some_disclosed.json +55 -0
- package/test/complex.json +43 -0
- package/test/header_mod.json +44 -0
- package/test/json_serialization.json +44 -0
- package/test/key_binding.json +44 -0
- package/test/no_sd.json +36 -0
- package/test/object_data_types.json +60 -0
- package/test/recursions.json +98 -0
- package/tsconfig.json +7 -0
- package/vitest.config.mts +4 -0
- package/README.md +0 -97
- package/build/base64url.d.ts +0 -28
- package/build/base64url.js +0 -40
- package/build/base64url.js.map +0 -1
- package/build/hasherAlgorithm.d.ts +0 -70
- package/build/hasherAlgorithm.js +0 -75
- package/build/hasherAlgorithm.js.map +0 -1
- package/build/index.d.ts +0 -13
- package/build/index.js +0 -20
- package/build/index.js.map +0 -1
- package/build/jwt/compact.d.ts +0 -6
- package/build/jwt/compact.js +0 -27
- package/build/jwt/compact.js.map +0 -1
- package/build/jwt/error.d.ts +0 -2
- package/build/jwt/error.js +0 -7
- package/build/jwt/error.js.map +0 -1
- package/build/jwt/index.d.ts +0 -2
- package/build/jwt/index.js +0 -19
- package/build/jwt/index.js.map +0 -1
- package/build/jwt/jwt.d.ts +0 -208
- package/build/jwt/jwt.js +0 -325
- package/build/jwt/jwt.js.map +0 -1
- package/build/keyBinding/index.d.ts +0 -1
- package/build/keyBinding/index.js +0 -18
- package/build/keyBinding/index.js.map +0 -1
- package/build/keyBinding/keyBinding.d.ts +0 -64
- package/build/keyBinding/keyBinding.js +0 -119
- package/build/keyBinding/keyBinding.js.map +0 -1
- package/build/sdJwt/compact.d.ts +0 -8
- package/build/sdJwt/compact.js +0 -39
- package/build/sdJwt/compact.js.map +0 -1
- package/build/sdJwt/decoys.d.ts +0 -3
- package/build/sdJwt/decoys.js +0 -35
- package/build/sdJwt/decoys.js.map +0 -1
- package/build/sdJwt/disclosureFrame.d.ts +0 -8
- package/build/sdJwt/disclosureFrame.js +0 -87
- package/build/sdJwt/disclosureFrame.js.map +0 -1
- package/build/sdJwt/disclosureMapping.d.ts +0 -43
- package/build/sdJwt/disclosureMapping.js +0 -278
- package/build/sdJwt/disclosureMapping.js.map +0 -1
- package/build/sdJwt/disclosures.d.ts +0 -33
- package/build/sdJwt/disclosures.js +0 -114
- package/build/sdJwt/disclosures.js.map +0 -1
- package/build/sdJwt/error.d.ts +0 -2
- package/build/sdJwt/error.js +0 -7
- package/build/sdJwt/error.js.map +0 -1
- package/build/sdJwt/index.d.ts +0 -6
- package/build/sdJwt/index.js +0 -23
- package/build/sdJwt/index.js.map +0 -1
- package/build/sdJwt/presentationFrame.d.ts +0 -3
- package/build/sdJwt/presentationFrame.js +0 -64
- package/build/sdJwt/presentationFrame.js.map +0 -1
- package/build/sdJwt/sdJwt.d.ts +0 -206
- package/build/sdJwt/sdJwt.js +0 -442
- package/build/sdJwt/sdJwt.js.map +0 -1
- package/build/sdJwt/swapClaim.d.ts +0 -2
- package/build/sdJwt/swapClaim.js +0 -79
- package/build/sdJwt/swapClaim.js.map +0 -1
- package/build/sdJwt/types.d.ts +0 -5
- package/build/sdJwt/types.js +0 -3
- package/build/sdJwt/types.js.map +0 -1
- package/build/sdJwtVc/error.d.ts +0 -2
- package/build/sdJwtVc/error.js +0 -7
- package/build/sdJwtVc/error.js.map +0 -1
- package/build/sdJwtVc/index.d.ts +0 -2
- package/build/sdJwtVc/index.js +0 -19
- package/build/sdJwtVc/index.js.map +0 -1
- package/build/sdJwtVc/sdJwtVc.d.ts +0 -47
- package/build/sdJwtVc/sdJwtVc.js +0 -149
- package/build/sdJwtVc/sdJwtVc.js.map +0 -1
- package/build/signatureAndEncryptionAlgorithm.d.ts +0 -105
- package/build/signatureAndEncryptionAlgorithm.js +0 -110
- package/build/signatureAndEncryptionAlgorithm.js.map +0 -1
- package/build/types/disclosure.d.ts +0 -5
- package/build/types/disclosure.js +0 -3
- package/build/types/disclosure.js.map +0 -1
- package/build/types/frame.d.ts +0 -5
- package/build/types/frame.js +0 -3
- package/build/types/frame.js.map +0 -1
- package/build/types/hasher.d.ts +0 -14
- package/build/types/hasher.js +0 -3
- package/build/types/hasher.js.map +0 -1
- package/build/types/index.d.ts +0 -5
- package/build/types/index.js +0 -22
- package/build/types/index.js.map +0 -1
- package/build/types/present.d.ts +0 -2
- package/build/types/present.js +0 -3
- package/build/types/present.js.map +0 -1
- package/build/types/saltGenerator.d.ts +0 -17
- package/build/types/saltGenerator.js +0 -3
- package/build/types/saltGenerator.js.map +0 -1
- package/build/types/signer.d.ts +0 -2
- package/build/types/signer.js +0 -3
- package/build/types/signer.js.map +0 -1
- package/build/types/utils.d.ts +0 -2
- package/build/types/utils.js +0 -3
- package/build/types/utils.js.map +0 -1
- package/build/types/verifier.d.ts +0 -14
- package/build/types/verifier.js +0 -3
- package/build/types/verifier.js.map +0 -1
- package/build/utils/index.d.ts +0 -2
- package/build/utils/index.js +0 -19
- package/build/utils/index.js.map +0 -1
- package/build/utils/traverse.d.ts +0 -8
- package/build/utils/traverse.js +0 -29
- package/build/utils/traverse.js.map +0 -1
- package/build/utils/utils.d.ts +0 -8
- package/build/utils/utils.js +0 -118
- package/build/utils/utils.js.map +0 -1
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __reflectGet = Reflect.get;
|
|
9
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
10
|
+
var __spreadValues = (a, b) => {
|
|
11
|
+
for (var prop in b || (b = {}))
|
|
12
|
+
if (__hasOwnProp.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
if (__getOwnPropSymbols)
|
|
15
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
16
|
+
if (__propIsEnum.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
}
|
|
19
|
+
return a;
|
|
20
|
+
};
|
|
21
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
22
|
+
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
23
|
+
var __async = (__this, __arguments, generator) => {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
var fulfilled = (value) => {
|
|
26
|
+
try {
|
|
27
|
+
step(generator.next(value));
|
|
28
|
+
} catch (e) {
|
|
29
|
+
reject(e);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var rejected = (value) => {
|
|
33
|
+
try {
|
|
34
|
+
step(generator.throw(value));
|
|
35
|
+
} catch (e) {
|
|
36
|
+
reject(e);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
40
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// src/index.ts
|
|
45
|
+
import { SDJWTException as SDJWTException4 } from "@sd-jwt/utils";
|
|
46
|
+
|
|
47
|
+
// src/jwt.ts
|
|
48
|
+
import { Base64urlEncode, SDJWTException } from "@sd-jwt/utils";
|
|
49
|
+
import { decodeJwt } from "@sd-jwt/decode";
|
|
50
|
+
var Jwt = class _Jwt {
|
|
51
|
+
constructor(data) {
|
|
52
|
+
this.header = data == null ? void 0 : data.header;
|
|
53
|
+
this.payload = data == null ? void 0 : data.payload;
|
|
54
|
+
this.signature = data == null ? void 0 : data.signature;
|
|
55
|
+
}
|
|
56
|
+
static decodeJWT(jwt) {
|
|
57
|
+
return decodeJwt(jwt);
|
|
58
|
+
}
|
|
59
|
+
static fromEncode(encodedJwt) {
|
|
60
|
+
const { header, payload, signature } = _Jwt.decodeJWT(
|
|
61
|
+
encodedJwt
|
|
62
|
+
);
|
|
63
|
+
const jwt = new _Jwt({
|
|
64
|
+
header,
|
|
65
|
+
payload,
|
|
66
|
+
signature
|
|
67
|
+
});
|
|
68
|
+
return jwt;
|
|
69
|
+
}
|
|
70
|
+
setHeader(header) {
|
|
71
|
+
this.header = header;
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
setPayload(payload) {
|
|
75
|
+
this.payload = payload;
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
sign(signer) {
|
|
79
|
+
return __async(this, null, function* () {
|
|
80
|
+
if (!this.header || !this.payload) {
|
|
81
|
+
throw new SDJWTException("Sign Error: Invalid JWT");
|
|
82
|
+
}
|
|
83
|
+
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
84
|
+
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
85
|
+
const data = `${header}.${payload}`;
|
|
86
|
+
this.signature = yield signer(data);
|
|
87
|
+
return this.encodeJwt();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
encodeJwt() {
|
|
91
|
+
if (!this.header || !this.payload || !this.signature) {
|
|
92
|
+
throw new SDJWTException("Serialize Error: Invalid JWT");
|
|
93
|
+
}
|
|
94
|
+
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
95
|
+
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
96
|
+
const signature = this.signature;
|
|
97
|
+
const compact = `${header}.${payload}.${signature}`;
|
|
98
|
+
return compact;
|
|
99
|
+
}
|
|
100
|
+
verify(verifier) {
|
|
101
|
+
return __async(this, null, function* () {
|
|
102
|
+
if (!this.header || !this.payload || !this.signature) {
|
|
103
|
+
throw new SDJWTException("Verify Error: Invalid JWT");
|
|
104
|
+
}
|
|
105
|
+
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
106
|
+
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
107
|
+
const data = `${header}.${payload}`;
|
|
108
|
+
const verified = verifier(data, this.signature);
|
|
109
|
+
if (!verified) {
|
|
110
|
+
throw new SDJWTException("Verify Error: Invalid JWT Signature");
|
|
111
|
+
}
|
|
112
|
+
return { payload: this.payload, header: this.header };
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/kbjwt.ts
|
|
118
|
+
import { SDJWTException as SDJWTException2 } from "@sd-jwt/utils";
|
|
119
|
+
var KBJwt = class _KBJwt extends Jwt {
|
|
120
|
+
// Checking the validity of the key binding jwt
|
|
121
|
+
verify(verifier) {
|
|
122
|
+
return __async(this, null, function* () {
|
|
123
|
+
var _a, _b, _c, _d, _e, _f;
|
|
124
|
+
if (!((_a = this.header) == null ? void 0 : _a.alg) || !this.header.typ || !((_b = this.payload) == null ? void 0 : _b.iat) || !((_c = this.payload) == null ? void 0 : _c.aud) || !((_d = this.payload) == null ? void 0 : _d.nonce) || // this is for backward compatibility with version 06
|
|
125
|
+
!(((_e = this.payload) == null ? void 0 : _e.sd_hash) || ((_f = this.payload) == null ? void 0 : _f._sd_hash))) {
|
|
126
|
+
throw new SDJWTException2("Invalid Key Binding Jwt");
|
|
127
|
+
}
|
|
128
|
+
return yield __superGet(_KBJwt.prototype, this, "verify").call(this, verifier);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
// This function is for creating KBJwt object for verify properly
|
|
132
|
+
static fromKBEncode(encodedJwt) {
|
|
133
|
+
const { header, payload, signature } = Jwt.decodeJWT(
|
|
134
|
+
encodedJwt
|
|
135
|
+
);
|
|
136
|
+
const jwt = new _KBJwt({
|
|
137
|
+
header,
|
|
138
|
+
payload,
|
|
139
|
+
signature
|
|
140
|
+
});
|
|
141
|
+
return jwt;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/decoy.ts
|
|
146
|
+
import { Uint8ArrayToBase64Url } from "@sd-jwt/utils";
|
|
147
|
+
var createDecoy = (hash, saltGenerator) => __async(void 0, null, function* () {
|
|
148
|
+
const { hasher, alg } = hash;
|
|
149
|
+
const salt = yield saltGenerator(16);
|
|
150
|
+
const decoy = yield hasher(salt, alg);
|
|
151
|
+
return Uint8ArrayToBase64Url(decoy);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// src/sdjwt.ts
|
|
155
|
+
import { SDJWTException as SDJWTException3, Disclosure } from "@sd-jwt/utils";
|
|
156
|
+
import {
|
|
157
|
+
SD_DECOY,
|
|
158
|
+
SD_DIGEST,
|
|
159
|
+
SD_LIST_KEY,
|
|
160
|
+
SD_SEPARATOR
|
|
161
|
+
} from "@sd-jwt/types";
|
|
162
|
+
import { createHashMapping, getSDAlgAndPayload, unpack } from "@sd-jwt/decode";
|
|
163
|
+
var SDJwt = class _SDJwt {
|
|
164
|
+
constructor(data) {
|
|
165
|
+
this.jwt = data == null ? void 0 : data.jwt;
|
|
166
|
+
this.disclosures = data == null ? void 0 : data.disclosures;
|
|
167
|
+
this.kbJwt = data == null ? void 0 : data.kbJwt;
|
|
168
|
+
}
|
|
169
|
+
static decodeSDJwt(sdjwt, hasher) {
|
|
170
|
+
return __async(this, null, function* () {
|
|
171
|
+
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
|
|
172
|
+
const jwt = Jwt.fromEncode(encodedJwt);
|
|
173
|
+
if (!jwt.payload) {
|
|
174
|
+
throw new Error("Payload is undefined on the JWT. Invalid state reached");
|
|
175
|
+
}
|
|
176
|
+
if (encodedDisclosures.length === 0) {
|
|
177
|
+
return {
|
|
178
|
+
jwt,
|
|
179
|
+
disclosures: []
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const encodedKeyBindingJwt = encodedDisclosures.pop();
|
|
183
|
+
const kbJwt = encodedKeyBindingJwt ? KBJwt.fromKBEncode(encodedKeyBindingJwt) : void 0;
|
|
184
|
+
const { _sd_alg } = getSDAlgAndPayload(jwt.payload);
|
|
185
|
+
const disclosures = yield Promise.all(
|
|
186
|
+
encodedDisclosures.map(
|
|
187
|
+
(ed) => Disclosure.fromEncode(ed, { alg: _sd_alg, hasher })
|
|
188
|
+
)
|
|
189
|
+
);
|
|
190
|
+
return {
|
|
191
|
+
jwt,
|
|
192
|
+
disclosures,
|
|
193
|
+
kbJwt
|
|
194
|
+
};
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
static fromEncode(encodedSdJwt, hasher) {
|
|
198
|
+
return __async(this, null, function* () {
|
|
199
|
+
const { jwt, disclosures, kbJwt } = yield _SDJwt.decodeSDJwt(encodedSdJwt, hasher);
|
|
200
|
+
return new _SDJwt({
|
|
201
|
+
jwt,
|
|
202
|
+
disclosures,
|
|
203
|
+
kbJwt
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
present(keys, hasher) {
|
|
208
|
+
return __async(this, null, function* () {
|
|
209
|
+
var _a;
|
|
210
|
+
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
211
|
+
throw new SDJWTException3("Invalid sd-jwt: jwt or disclosures is missing");
|
|
212
|
+
}
|
|
213
|
+
const { _sd_alg: alg } = getSDAlgAndPayload(this.jwt.payload);
|
|
214
|
+
const hash = { alg, hasher };
|
|
215
|
+
const hashmap = yield createHashMapping(this.disclosures, hash);
|
|
216
|
+
const { disclosureKeymap } = yield unpack(
|
|
217
|
+
this.jwt.payload,
|
|
218
|
+
this.disclosures,
|
|
219
|
+
hasher
|
|
220
|
+
);
|
|
221
|
+
const presentableKeys = Object.keys(disclosureKeymap);
|
|
222
|
+
const missingKeys = keys.filter((k) => !presentableKeys.includes(k));
|
|
223
|
+
if (missingKeys.length > 0) {
|
|
224
|
+
throw new SDJWTException3(
|
|
225
|
+
`Invalid sd-jwt: invalid present keys: ${missingKeys.join(", ")}`
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]);
|
|
229
|
+
const presentSDJwt = new _SDJwt({
|
|
230
|
+
jwt: this.jwt,
|
|
231
|
+
disclosures,
|
|
232
|
+
kbJwt: this.kbJwt
|
|
233
|
+
});
|
|
234
|
+
return presentSDJwt.encodeSDJwt();
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
encodeSDJwt() {
|
|
238
|
+
const data = [];
|
|
239
|
+
if (!this.jwt) {
|
|
240
|
+
throw new SDJWTException3("Invalid sd-jwt: jwt is missing");
|
|
241
|
+
}
|
|
242
|
+
const encodedJwt = this.jwt.encodeJwt();
|
|
243
|
+
data.push(encodedJwt);
|
|
244
|
+
if (this.disclosures && this.disclosures.length > 0) {
|
|
245
|
+
const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(SD_SEPARATOR);
|
|
246
|
+
data.push(encodeddisclosures);
|
|
247
|
+
}
|
|
248
|
+
data.push(this.kbJwt ? this.kbJwt.encodeJwt() : "");
|
|
249
|
+
return data.join(SD_SEPARATOR);
|
|
250
|
+
}
|
|
251
|
+
keys(hasher) {
|
|
252
|
+
return __async(this, null, function* () {
|
|
253
|
+
return listKeys(yield this.getClaims(hasher)).sort();
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
presentableKeys(hasher) {
|
|
257
|
+
return __async(this, null, function* () {
|
|
258
|
+
var _a, _b;
|
|
259
|
+
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
260
|
+
throw new SDJWTException3("Invalid sd-jwt: jwt or disclosures is missing");
|
|
261
|
+
}
|
|
262
|
+
const { disclosureKeymap } = yield unpack(
|
|
263
|
+
(_b = this.jwt) == null ? void 0 : _b.payload,
|
|
264
|
+
this.disclosures,
|
|
265
|
+
hasher
|
|
266
|
+
);
|
|
267
|
+
return Object.keys(disclosureKeymap).sort();
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
getClaims(hasher) {
|
|
271
|
+
return __async(this, null, function* () {
|
|
272
|
+
var _a;
|
|
273
|
+
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
274
|
+
throw new SDJWTException3("Invalid sd-jwt: jwt or disclosures is missing");
|
|
275
|
+
}
|
|
276
|
+
const { unpackedObj } = yield unpack(
|
|
277
|
+
this.jwt.payload,
|
|
278
|
+
this.disclosures,
|
|
279
|
+
hasher
|
|
280
|
+
);
|
|
281
|
+
return unpackedObj;
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
var listKeys = (obj, prefix = "") => {
|
|
286
|
+
const keys = [];
|
|
287
|
+
for (const key in obj) {
|
|
288
|
+
if (obj[key] === void 0)
|
|
289
|
+
continue;
|
|
290
|
+
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
291
|
+
keys.push(newKey);
|
|
292
|
+
if (obj[key] && typeof obj[key] === "object" && obj[key] !== null) {
|
|
293
|
+
keys.push(...listKeys(obj[key], newKey));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return keys;
|
|
297
|
+
};
|
|
298
|
+
var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, null, function* () {
|
|
299
|
+
var _a, _b;
|
|
300
|
+
if (!disclosureFrame) {
|
|
301
|
+
return {
|
|
302
|
+
packedClaims: claims,
|
|
303
|
+
disclosures: []
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
const sd = (_a = disclosureFrame[SD_DIGEST]) != null ? _a : [];
|
|
307
|
+
const decoyCount = (_b = disclosureFrame[SD_DECOY]) != null ? _b : 0;
|
|
308
|
+
if (Array.isArray(claims)) {
|
|
309
|
+
const packedClaims2 = [];
|
|
310
|
+
const disclosures2 = [];
|
|
311
|
+
const recursivePackedClaims2 = {};
|
|
312
|
+
for (const key in disclosureFrame) {
|
|
313
|
+
if (key !== SD_DIGEST) {
|
|
314
|
+
const idx = parseInt(key);
|
|
315
|
+
const packed = yield pack(
|
|
316
|
+
claims[idx],
|
|
317
|
+
disclosureFrame[idx],
|
|
318
|
+
hash,
|
|
319
|
+
saltGenerator
|
|
320
|
+
);
|
|
321
|
+
recursivePackedClaims2[idx] = packed.packedClaims;
|
|
322
|
+
disclosures2.push(...packed.disclosures);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
for (let i = 0; i < claims.length; i++) {
|
|
326
|
+
const claim = recursivePackedClaims2[i] ? recursivePackedClaims2[i] : claims[i];
|
|
327
|
+
if (sd.includes(i)) {
|
|
328
|
+
const salt = yield saltGenerator(16);
|
|
329
|
+
const disclosure = new Disclosure([salt, claim]);
|
|
330
|
+
const digest = yield disclosure.digest(hash);
|
|
331
|
+
packedClaims2.push({ [SD_LIST_KEY]: digest });
|
|
332
|
+
disclosures2.push(disclosure);
|
|
333
|
+
} else {
|
|
334
|
+
packedClaims2.push(claim);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
for (let j = 0; j < decoyCount; j++) {
|
|
338
|
+
const decoyDigest = yield createDecoy(hash, saltGenerator);
|
|
339
|
+
packedClaims2.push({ [SD_LIST_KEY]: decoyDigest });
|
|
340
|
+
}
|
|
341
|
+
return { packedClaims: packedClaims2, disclosures: disclosures2 };
|
|
342
|
+
}
|
|
343
|
+
const packedClaims = {};
|
|
344
|
+
const disclosures = [];
|
|
345
|
+
const recursivePackedClaims = {};
|
|
346
|
+
for (const key in disclosureFrame) {
|
|
347
|
+
if (key !== SD_DIGEST) {
|
|
348
|
+
const packed = yield pack(
|
|
349
|
+
// @ts-ignore
|
|
350
|
+
claims[key],
|
|
351
|
+
disclosureFrame[key],
|
|
352
|
+
hash,
|
|
353
|
+
saltGenerator
|
|
354
|
+
);
|
|
355
|
+
recursivePackedClaims[key] = packed.packedClaims;
|
|
356
|
+
disclosures.push(...packed.disclosures);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const _sd = [];
|
|
360
|
+
for (const key in claims) {
|
|
361
|
+
const claim = recursivePackedClaims[key] ? recursivePackedClaims[key] : claims[key];
|
|
362
|
+
if (sd.includes(key)) {
|
|
363
|
+
const salt = yield saltGenerator(16);
|
|
364
|
+
const disclosure = new Disclosure([salt, key, claim]);
|
|
365
|
+
const digest = yield disclosure.digest(hash);
|
|
366
|
+
_sd.push(digest);
|
|
367
|
+
disclosures.push(disclosure);
|
|
368
|
+
} else {
|
|
369
|
+
packedClaims[key] = claim;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
for (let j = 0; j < decoyCount; j++) {
|
|
373
|
+
const decoyDigest = yield createDecoy(hash, saltGenerator);
|
|
374
|
+
_sd.push(decoyDigest);
|
|
375
|
+
}
|
|
376
|
+
if (_sd.length > 0) {
|
|
377
|
+
packedClaims[SD_DIGEST] = _sd.sort();
|
|
378
|
+
}
|
|
379
|
+
return { packedClaims, disclosures };
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// src/index.ts
|
|
383
|
+
import {
|
|
384
|
+
KB_JWT_TYP,
|
|
385
|
+
SD_JWT_TYP
|
|
386
|
+
} from "@sd-jwt/types";
|
|
387
|
+
var _SDJwtInstance = class _SDJwtInstance {
|
|
388
|
+
constructor(userConfig) {
|
|
389
|
+
this.userConfig = {};
|
|
390
|
+
if (userConfig) {
|
|
391
|
+
this.userConfig = userConfig;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
createKBJwt(options) {
|
|
395
|
+
return __async(this, null, function* () {
|
|
396
|
+
if (!this.userConfig.kbSigner) {
|
|
397
|
+
throw new SDJWTException4("Key Binding Signer not found");
|
|
398
|
+
}
|
|
399
|
+
if (!this.userConfig.kbSignAlg) {
|
|
400
|
+
throw new SDJWTException4("Key Binding sign algorithm not specified");
|
|
401
|
+
}
|
|
402
|
+
const { payload } = options;
|
|
403
|
+
const kbJwt = new KBJwt({
|
|
404
|
+
header: {
|
|
405
|
+
typ: KB_JWT_TYP,
|
|
406
|
+
alg: this.userConfig.kbSignAlg
|
|
407
|
+
},
|
|
408
|
+
payload
|
|
409
|
+
});
|
|
410
|
+
yield kbJwt.sign(this.userConfig.kbSigner);
|
|
411
|
+
return kbJwt;
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
SignJwt(jwt) {
|
|
415
|
+
return __async(this, null, function* () {
|
|
416
|
+
if (!this.userConfig.signer) {
|
|
417
|
+
throw new SDJWTException4("Signer not found");
|
|
418
|
+
}
|
|
419
|
+
yield jwt.sign(this.userConfig.signer);
|
|
420
|
+
return jwt;
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
VerifyJwt(jwt) {
|
|
424
|
+
return __async(this, null, function* () {
|
|
425
|
+
if (!this.userConfig.verifier) {
|
|
426
|
+
throw new SDJWTException4("Verifier not found");
|
|
427
|
+
}
|
|
428
|
+
return jwt.verify(this.userConfig.verifier);
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
issue(payload, disclosureFrame, options) {
|
|
432
|
+
return __async(this, null, function* () {
|
|
433
|
+
var _a, _b;
|
|
434
|
+
if (!this.userConfig.hasher) {
|
|
435
|
+
throw new SDJWTException4("Hasher not found");
|
|
436
|
+
}
|
|
437
|
+
if (!this.userConfig.saltGenerator) {
|
|
438
|
+
throw new SDJWTException4("SaltGenerator not found");
|
|
439
|
+
}
|
|
440
|
+
if (!this.userConfig.signAlg) {
|
|
441
|
+
throw new SDJWTException4("sign alogrithm not specified");
|
|
442
|
+
}
|
|
443
|
+
const hasher = this.userConfig.hasher;
|
|
444
|
+
const hashAlg = (_a = this.userConfig.hashAlg) != null ? _a : _SDJwtInstance.DEFAULT_hashAlg;
|
|
445
|
+
const { packedClaims, disclosures } = yield pack(
|
|
446
|
+
payload,
|
|
447
|
+
disclosureFrame,
|
|
448
|
+
{ hasher, alg: hashAlg },
|
|
449
|
+
this.userConfig.saltGenerator
|
|
450
|
+
);
|
|
451
|
+
const alg = this.userConfig.signAlg;
|
|
452
|
+
const OptionHeader = (_b = options == null ? void 0 : options.header) != null ? _b : {};
|
|
453
|
+
const CustomHeader = this.userConfig.omitTyp ? OptionHeader : __spreadValues({ typ: SD_JWT_TYP }, OptionHeader);
|
|
454
|
+
const header = __spreadProps(__spreadValues({}, CustomHeader), { alg });
|
|
455
|
+
const jwt = new Jwt({
|
|
456
|
+
header,
|
|
457
|
+
payload: __spreadProps(__spreadValues({}, packedClaims), {
|
|
458
|
+
_sd_alg: hashAlg
|
|
459
|
+
})
|
|
460
|
+
});
|
|
461
|
+
yield this.SignJwt(jwt);
|
|
462
|
+
const sdJwt = new SDJwt({
|
|
463
|
+
jwt,
|
|
464
|
+
disclosures
|
|
465
|
+
});
|
|
466
|
+
return sdJwt.encodeSDJwt();
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
present(encodedSDJwt, presentationKeys, options) {
|
|
470
|
+
return __async(this, null, function* () {
|
|
471
|
+
if (!presentationKeys)
|
|
472
|
+
return encodedSDJwt;
|
|
473
|
+
if (!this.userConfig.hasher) {
|
|
474
|
+
throw new SDJWTException4("Hasher not found");
|
|
475
|
+
}
|
|
476
|
+
const hasher = this.userConfig.hasher;
|
|
477
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
478
|
+
const kbJwt = (options == null ? void 0 : options.kb) ? yield this.createKBJwt(options.kb) : void 0;
|
|
479
|
+
sdjwt.kbJwt = kbJwt;
|
|
480
|
+
return sdjwt.present(presentationKeys.sort(), hasher);
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
// This function is for verifying the SD JWT
|
|
484
|
+
// If requiredClaimKeys is provided, it will check if the required claim keys are presentation in the SD JWT
|
|
485
|
+
// If requireKeyBindings is true, it will check if the key binding JWT is presentation and verify it
|
|
486
|
+
verify(encodedSDJwt, requiredClaimKeys, requireKeyBindings) {
|
|
487
|
+
return __async(this, null, function* () {
|
|
488
|
+
if (!this.userConfig.hasher) {
|
|
489
|
+
throw new SDJWTException4("Hasher not found");
|
|
490
|
+
}
|
|
491
|
+
const hasher = this.userConfig.hasher;
|
|
492
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
493
|
+
if (!sdjwt.jwt) {
|
|
494
|
+
throw new SDJWTException4("Invalid SD JWT");
|
|
495
|
+
}
|
|
496
|
+
const { payload, header } = yield this.validate(encodedSDJwt);
|
|
497
|
+
if (requiredClaimKeys) {
|
|
498
|
+
const keys = yield sdjwt.keys(hasher);
|
|
499
|
+
const missingKeys = requiredClaimKeys.filter((k) => !keys.includes(k));
|
|
500
|
+
if (missingKeys.length > 0) {
|
|
501
|
+
throw new SDJWTException4(
|
|
502
|
+
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if (!requireKeyBindings) {
|
|
507
|
+
return { payload, header };
|
|
508
|
+
}
|
|
509
|
+
if (!sdjwt.kbJwt) {
|
|
510
|
+
throw new SDJWTException4("Key Binding JWT not exist");
|
|
511
|
+
}
|
|
512
|
+
if (!this.userConfig.kbVerifier) {
|
|
513
|
+
throw new SDJWTException4("Key Binding Verifier not found");
|
|
514
|
+
}
|
|
515
|
+
const kb = yield sdjwt.kbJwt.verify(this.userConfig.kbVerifier);
|
|
516
|
+
return { payload, header, kb };
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
// This function is for validating the SD JWT
|
|
520
|
+
// Just checking signature and return its the claims
|
|
521
|
+
validate(encodedSDJwt) {
|
|
522
|
+
return __async(this, null, function* () {
|
|
523
|
+
if (!this.userConfig.hasher) {
|
|
524
|
+
throw new SDJWTException4("Hasher not found");
|
|
525
|
+
}
|
|
526
|
+
const hasher = this.userConfig.hasher;
|
|
527
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
528
|
+
if (!sdjwt.jwt) {
|
|
529
|
+
throw new SDJWTException4("Invalid SD JWT");
|
|
530
|
+
}
|
|
531
|
+
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt);
|
|
532
|
+
const claims = yield sdjwt.getClaims(hasher);
|
|
533
|
+
return { payload: claims, header: verifiedPayloads.header };
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
config(newConfig) {
|
|
537
|
+
this.userConfig = __spreadValues(__spreadValues({}, this.userConfig), newConfig);
|
|
538
|
+
}
|
|
539
|
+
encode(sdJwt) {
|
|
540
|
+
return sdJwt.encodeSDJwt();
|
|
541
|
+
}
|
|
542
|
+
decode(endcodedSDJwt) {
|
|
543
|
+
if (!this.userConfig.hasher) {
|
|
544
|
+
throw new SDJWTException4("Hasher not found");
|
|
545
|
+
}
|
|
546
|
+
return SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
547
|
+
}
|
|
548
|
+
keys(endcodedSDJwt) {
|
|
549
|
+
return __async(this, null, function* () {
|
|
550
|
+
if (!this.userConfig.hasher) {
|
|
551
|
+
throw new SDJWTException4("Hasher not found");
|
|
552
|
+
}
|
|
553
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
554
|
+
return sdjwt.keys(this.userConfig.hasher);
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
presentableKeys(endcodedSDJwt) {
|
|
558
|
+
return __async(this, null, function* () {
|
|
559
|
+
if (!this.userConfig.hasher) {
|
|
560
|
+
throw new SDJWTException4("Hasher not found");
|
|
561
|
+
}
|
|
562
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
563
|
+
return sdjwt.presentableKeys(this.userConfig.hasher);
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
getClaims(endcodedSDJwt) {
|
|
567
|
+
return __async(this, null, function* () {
|
|
568
|
+
if (!this.userConfig.hasher) {
|
|
569
|
+
throw new SDJWTException4("Hasher not found");
|
|
570
|
+
}
|
|
571
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
572
|
+
return sdjwt.getClaims(this.userConfig.hasher);
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
_SDJwtInstance.DEFAULT_hashAlg = "sha-256";
|
|
577
|
+
var SDJwtInstance = _SDJwtInstance;
|
|
578
|
+
export {
|
|
579
|
+
Jwt,
|
|
580
|
+
KBJwt,
|
|
581
|
+
SDJwt,
|
|
582
|
+
SDJwtInstance,
|
|
583
|
+
createDecoy,
|
|
584
|
+
listKeys,
|
|
585
|
+
pack
|
|
586
|
+
};
|
package/package.json
CHANGED
|
@@ -1,51 +1,63 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
"name": "@sd-jwt/core",
|
|
3
|
+
"version": "2.0.2-next.26+278b4fa",
|
|
4
|
+
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "rm -rf **/dist && tsup",
|
|
16
|
+
"lint": "biome lint ./src",
|
|
17
|
+
"test": "pnpm run test:node && pnpm run test:browser && pnpm run test:e2e && pnpm run test:cov",
|
|
18
|
+
"test:node": "vitest run ./src/test/*.spec.ts && vitest run ./src/test/*.spec.ts --environment jsdom",
|
|
19
|
+
"test:browser": "vitest run ./src/test/*.spec.ts --environment jsdom",
|
|
20
|
+
"test:e2e": "vitest run ./test/*e2e.spec.ts --environment node",
|
|
21
|
+
"test:cov": "vitest run --coverage"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"sd-jwt",
|
|
25
|
+
"sdjwt",
|
|
26
|
+
"sd-jwt-vc"
|
|
27
|
+
],
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/openwallet-foundation-labs/sd-jwt-js"
|
|
31
|
+
},
|
|
32
|
+
"author": "Lukas.J.Han <lukas.j.han@gmail.com>",
|
|
33
|
+
"homepage": "https://github.com/openwallet-foundation-labs/sd-jwt-js/wiki",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/openwallet-foundation-labs/sd-jwt-js/issues"
|
|
36
|
+
},
|
|
37
|
+
"license": "Apache-2.0",
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@sd-jwt/crypto-nodejs": "2.0.2-next.26+278b4fa"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@sd-jwt/decode": "2.0.2-next.26+278b4fa",
|
|
43
|
+
"@sd-jwt/types": "2.0.2-next.26+278b4fa",
|
|
44
|
+
"@sd-jwt/utils": "2.0.2-next.26+278b4fa"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"tsup": {
|
|
50
|
+
"entry": [
|
|
51
|
+
"./src/index.ts"
|
|
18
52
|
],
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"access": "public"
|
|
30
|
-
},
|
|
31
|
-
"main": "build/index.js",
|
|
32
|
-
"files": [
|
|
33
|
-
"build"
|
|
34
|
-
],
|
|
35
|
-
"scripts": {
|
|
36
|
-
"build": "tsc",
|
|
37
|
-
"test": "node --require ts-node/register --test ./tests/*.test.ts"
|
|
38
|
-
},
|
|
39
|
-
"dependencies": {
|
|
40
|
-
"@sd-jwt/decode": "0.2.1",
|
|
41
|
-
"@sd-jwt/present": "0.2.1",
|
|
42
|
-
"@sd-jwt/types": "0.2.1",
|
|
43
|
-
"@sd-jwt/utils": "0.2.1"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@types/node": "*",
|
|
47
|
-
"ts-node": "*",
|
|
48
|
-
"typescript": "*"
|
|
49
|
-
},
|
|
50
|
-
"gitHead": "a1fb5fad0b938081e033233bae5569ae3b9fe8cb"
|
|
53
|
+
"sourceMap": true,
|
|
54
|
+
"splitting": false,
|
|
55
|
+
"clean": true,
|
|
56
|
+
"dts": true,
|
|
57
|
+
"format": [
|
|
58
|
+
"cjs",
|
|
59
|
+
"esm"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
"gitHead": "278b4faf53b544d274ecb4e14a9f90c2312af846"
|
|
51
63
|
}
|