@sd-jwt/core 0.1.0 → 0.1.1-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/LICENSE +201 -0
- package/README.md +106 -0
- package/dist/index.d.mts +659 -0
- package/dist/index.d.ts +659 -0
- package/dist/index.js +1906 -0
- package/dist/index.mjs +1846 -0
- package/package.json +59 -47
- package/src/decode/decode.ts +376 -0
- package/src/decode/index.ts +1 -0
- package/src/decoy.ts +15 -0
- package/src/flattenJSON.ts +99 -0
- package/src/generalJSON.ts +148 -0
- package/src/index.ts +945 -0
- package/src/jwt.ts +190 -0
- package/src/kbjwt.ts +81 -0
- package/src/present/index.ts +1 -0
- package/src/present/present.ts +210 -0
- package/src/sdjwt.ts +354 -0
- package/src/test/decode/decode.spec.ts +202 -0
- package/src/test/decoy.spec.ts +30 -0
- package/src/test/flattenJSON.spec.ts +122 -0
- package/src/test/generalJSON.spec.ts +198 -0
- package/src/test/index.spec.ts +974 -0
- package/src/test/jwt.spec.ts +301 -0
- package/src/test/kbjwt.spec.ts +565 -0
- package/src/test/pass.spec.ts +7 -0
- package/src/test/present/present.spec.ts +305 -0
- package/src/test/sdjwt.spec.ts +384 -0
- package/src/test/types/type.spec.ts +88 -0
- package/src/test/utils/base64url.spec.ts +33 -0
- package/src/test/utils/disclosure.spec.ts +170 -0
- package/src/test/utils/error.spec.ts +15 -0
- package/src/types/index.ts +2 -0
- package/src/types/type.ts +249 -0
- package/src/types/verification-error.ts +55 -0
- package/src/utils/base64url.ts +6 -0
- package/src/utils/disclosure.ts +101 -0
- package/src/utils/error.ts +25 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/strict-json.ts +17 -0
- package/test/app-e2e.spec.ts +292 -0
- package/test/array_data_types.json +31 -0
- package/test/array_full_sd.json +21 -0
- package/test/array_in_sd.json +13 -0
- package/test/array_nested_in_plain.json +29 -0
- package/test/array_none_disclosed.json +17 -0
- package/test/array_of_nulls.json +15 -0
- package/test/array_of_objects.json +65 -0
- package/test/array_of_scalars.json +19 -0
- package/test/array_recursive_sd.json +35 -0
- package/test/array_recursive_sd_some_disclosed.json +63 -0
- package/test/complex.json +43 -0
- package/test/header_mod.json +48 -0
- package/test/json_serialization.json +48 -0
- package/test/key_binding.json +48 -0
- package/test/no_sd.json +36 -0
- package/test/object_data_types.json +62 -0
- package/test/recursions.json +117 -0
- package/test/rfc9901-validation.spec.ts +150 -0
- package/tsconfig.json +7 -0
- package/vitest.config.mts +4 -0
- 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 -11
- 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 -3
- package/build/jwt/index.js +0 -20
- package/build/jwt/index.js.map +0 -1
- package/build/jwt/jwt.d.ts +0 -204
- package/build/jwt/jwt.js +0 -324
- 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 -56
- package/build/keyBinding/keyBinding.js +0 -99
- 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 -2
- package/build/sdJwt/decoys.js +0 -35
- package/build/sdJwt/decoys.js.map +0 -1
- package/build/sdJwt/disclosureFrame.d.ts +0 -7
- package/build/sdJwt/disclosureFrame.js +0 -89
- package/build/sdJwt/disclosureFrame.js.map +0 -1
- package/build/sdJwt/disclosureMapping.d.ts +0 -44
- package/build/sdJwt/disclosureMapping.js +0 -289
- package/build/sdJwt/disclosureMapping.js.map +0 -1
- package/build/sdJwt/disclosures.d.ts +0 -14
- package/build/sdJwt/disclosures.js +0 -59
- 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 -7
- package/build/sdJwt/index.js +0 -24
- package/build/sdJwt/index.js.map +0 -1
- package/build/sdJwt/presentationFrame.d.ts +0 -4
- package/build/sdJwt/presentationFrame.js +0 -73
- package/build/sdJwt/presentationFrame.js.map +0 -1
- package/build/sdJwt/sdJwt.d.ts +0 -204
- package/build/sdJwt/sdJwt.js +0 -383
- package/build/sdJwt/sdJwt.js.map +0 -1
- package/build/sdJwt/swapClaim.d.ts +0 -3
- package/build/sdJwt/swapClaim.js +0 -90
- 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 -125
- 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 -6
- package/build/types/index.js +0 -23
- 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 -5
- 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 -7
- package/build/utils/utils.js +0 -109
- package/build/utils/utils.js.map +0 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"array_with_recursive_sd": [
|
|
4
|
+
"boring",
|
|
5
|
+
{
|
|
6
|
+
"foo": "bar",
|
|
7
|
+
"baz": {
|
|
8
|
+
"qux": "quxx"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
["foo", "bar"]
|
|
12
|
+
],
|
|
13
|
+
"test2": ["foo", "bar"]
|
|
14
|
+
},
|
|
15
|
+
"disclosureFrame": {
|
|
16
|
+
"array_with_recursive_sd": {
|
|
17
|
+
"1": {
|
|
18
|
+
"_sd": ["baz"]
|
|
19
|
+
},
|
|
20
|
+
"2": {
|
|
21
|
+
"_sd": [0, 1]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"test2": {
|
|
25
|
+
"_sd": [0, 1]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"presentationFrames": {
|
|
29
|
+
"array_with_recursive_sd": {
|
|
30
|
+
"1": {
|
|
31
|
+
"baz": true
|
|
32
|
+
},
|
|
33
|
+
"2": {
|
|
34
|
+
"1": true
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"test2": {
|
|
38
|
+
"0": true,
|
|
39
|
+
"1": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"presentedClaims": {
|
|
43
|
+
"array_with_recursive_sd": [
|
|
44
|
+
"boring",
|
|
45
|
+
{
|
|
46
|
+
"foo": "bar",
|
|
47
|
+
"baz": {
|
|
48
|
+
"qux": "quxx"
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
["bar"]
|
|
52
|
+
],
|
|
53
|
+
"test2": ["foo", "bar"]
|
|
54
|
+
},
|
|
55
|
+
"requiredClaimKeys": [
|
|
56
|
+
"array_with_recursive_sd.1",
|
|
57
|
+
"array_with_recursive_sd.2",
|
|
58
|
+
"array_with_recursive_sd.1.baz",
|
|
59
|
+
"array_with_recursive_sd.2.1",
|
|
60
|
+
"test2.0",
|
|
61
|
+
"test2.1"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"firstname": "John",
|
|
4
|
+
"lastname": "Doe",
|
|
5
|
+
"ssn": "123-45-6789",
|
|
6
|
+
"id": "1234",
|
|
7
|
+
"data": {
|
|
8
|
+
"firstname": "John",
|
|
9
|
+
"lastname": "Doe",
|
|
10
|
+
"ssn": "123-45-6789",
|
|
11
|
+
"list": [{ "r": "1" }, "b", "c"]
|
|
12
|
+
},
|
|
13
|
+
"data2": {
|
|
14
|
+
"hi": "bye"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"disclosureFrame": {
|
|
18
|
+
"_sd": ["firstname", "id", "data2"],
|
|
19
|
+
"data": {
|
|
20
|
+
"_sd": ["list"],
|
|
21
|
+
"_sd_decoy": 2,
|
|
22
|
+
"list": {
|
|
23
|
+
"_sd": [0, 2],
|
|
24
|
+
"_sd_decoy": 1,
|
|
25
|
+
"0": {
|
|
26
|
+
"_sd": ["r"]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"data2": {
|
|
31
|
+
"_sd": ["hi"]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"presentationFrames": { "firstname": true, "id": true },
|
|
35
|
+
"presentedClaims": {
|
|
36
|
+
"lastname": "Doe",
|
|
37
|
+
"ssn": "123-45-6789",
|
|
38
|
+
"data": { "firstname": "John", "lastname": "Doe", "ssn": "123-45-6789" },
|
|
39
|
+
"id": "1234",
|
|
40
|
+
"firstname": "John"
|
|
41
|
+
},
|
|
42
|
+
"requiredClaimKeys": ["firstname", "id", "data.ssn"]
|
|
43
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"sub": "john_deo_42",
|
|
4
|
+
"given_name": "John",
|
|
5
|
+
"family_name": "Deo",
|
|
6
|
+
"email": "johndeo@example.com",
|
|
7
|
+
"phone": "+1-202-555-0101",
|
|
8
|
+
"address": {
|
|
9
|
+
"street_address": "123 Main St",
|
|
10
|
+
"locality": "Anytown",
|
|
11
|
+
"region": "Anystate",
|
|
12
|
+
"country": "US"
|
|
13
|
+
},
|
|
14
|
+
"birthdate": "1940-01-01"
|
|
15
|
+
},
|
|
16
|
+
"disclosureFrame": {
|
|
17
|
+
"_sd": [
|
|
18
|
+
"sub",
|
|
19
|
+
"given_name",
|
|
20
|
+
"family_name",
|
|
21
|
+
"email",
|
|
22
|
+
"phone",
|
|
23
|
+
"address",
|
|
24
|
+
"birthdate"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"presentationFrames": {
|
|
28
|
+
"given_name": true,
|
|
29
|
+
"family_name": true,
|
|
30
|
+
"address": true
|
|
31
|
+
},
|
|
32
|
+
"presentedClaims": {
|
|
33
|
+
"given_name": "John",
|
|
34
|
+
"family_name": "Deo",
|
|
35
|
+
"address": {
|
|
36
|
+
"street_address": "123 Main St",
|
|
37
|
+
"locality": "Anytown",
|
|
38
|
+
"region": "Anystate",
|
|
39
|
+
"country": "US"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"requiredClaimKeys": [
|
|
43
|
+
"given_name",
|
|
44
|
+
"family_name",
|
|
45
|
+
"address.street_address",
|
|
46
|
+
"address.country"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"sub": "john_deo_42",
|
|
4
|
+
"given_name": "John",
|
|
5
|
+
"family_name": "Deo",
|
|
6
|
+
"email": "johndeo@example.com",
|
|
7
|
+
"phone": "+1-202-555-0101",
|
|
8
|
+
"address": {
|
|
9
|
+
"street_address": "123 Main St",
|
|
10
|
+
"locality": "Anytown",
|
|
11
|
+
"region": "Anystate",
|
|
12
|
+
"country": "US"
|
|
13
|
+
},
|
|
14
|
+
"birthdate": "1940-01-01"
|
|
15
|
+
},
|
|
16
|
+
"disclosureFrame": {
|
|
17
|
+
"_sd": [
|
|
18
|
+
"sub",
|
|
19
|
+
"given_name",
|
|
20
|
+
"family_name",
|
|
21
|
+
"email",
|
|
22
|
+
"phone",
|
|
23
|
+
"address",
|
|
24
|
+
"birthdate"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"presentationFrames": {
|
|
28
|
+
"given_name": true,
|
|
29
|
+
"family_name": true,
|
|
30
|
+
"address": true
|
|
31
|
+
},
|
|
32
|
+
"presentedClaims": {
|
|
33
|
+
"given_name": "John",
|
|
34
|
+
"family_name": "Deo",
|
|
35
|
+
"address": {
|
|
36
|
+
"street_address": "123 Main St",
|
|
37
|
+
"locality": "Anytown",
|
|
38
|
+
"region": "Anystate",
|
|
39
|
+
"country": "US"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"requiredClaimKeys": [
|
|
43
|
+
"given_name",
|
|
44
|
+
"family_name",
|
|
45
|
+
"address.street_address",
|
|
46
|
+
"address.country"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"sub": "john_deo_42",
|
|
4
|
+
"given_name": "John",
|
|
5
|
+
"family_name": "Deo",
|
|
6
|
+
"email": "johndeo@example.com",
|
|
7
|
+
"phone": "+1-202-555-0101",
|
|
8
|
+
"address": {
|
|
9
|
+
"street_address": "123 Main St",
|
|
10
|
+
"locality": "Anytown",
|
|
11
|
+
"region": "Anystate",
|
|
12
|
+
"country": "US"
|
|
13
|
+
},
|
|
14
|
+
"birthdate": "1940-01-01"
|
|
15
|
+
},
|
|
16
|
+
"disclosureFrame": {
|
|
17
|
+
"_sd": [
|
|
18
|
+
"sub",
|
|
19
|
+
"given_name",
|
|
20
|
+
"family_name",
|
|
21
|
+
"email",
|
|
22
|
+
"phone",
|
|
23
|
+
"address",
|
|
24
|
+
"birthdate"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"presentationFrames": {
|
|
28
|
+
"given_name": true,
|
|
29
|
+
"family_name": true,
|
|
30
|
+
"address": true
|
|
31
|
+
},
|
|
32
|
+
"presentedClaims": {
|
|
33
|
+
"given_name": "John",
|
|
34
|
+
"family_name": "Deo",
|
|
35
|
+
"address": {
|
|
36
|
+
"street_address": "123 Main St",
|
|
37
|
+
"locality": "Anytown",
|
|
38
|
+
"region": "Anystate",
|
|
39
|
+
"country": "US"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"requiredClaimKeys": [
|
|
43
|
+
"given_name",
|
|
44
|
+
"family_name",
|
|
45
|
+
"address.street_address",
|
|
46
|
+
"address.country"
|
|
47
|
+
]
|
|
48
|
+
}
|
package/test/no_sd.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"recursive": [
|
|
4
|
+
"boring",
|
|
5
|
+
{
|
|
6
|
+
"foo": "bar",
|
|
7
|
+
"baz": {
|
|
8
|
+
"qux": "quxx"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
["foo", "bar"]
|
|
12
|
+
],
|
|
13
|
+
"test2": ["foo", "bar"]
|
|
14
|
+
},
|
|
15
|
+
"disclosureFrame": {},
|
|
16
|
+
"presentationFrames": {},
|
|
17
|
+
"presentedClaims": {
|
|
18
|
+
"recursive": [
|
|
19
|
+
"boring",
|
|
20
|
+
{
|
|
21
|
+
"foo": "bar",
|
|
22
|
+
"baz": {
|
|
23
|
+
"qux": "quxx"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
["foo", "bar"]
|
|
27
|
+
],
|
|
28
|
+
"test2": ["foo", "bar"]
|
|
29
|
+
},
|
|
30
|
+
"requiredClaimKeys": [
|
|
31
|
+
"recursive.0",
|
|
32
|
+
"recursive.1.baz.qux",
|
|
33
|
+
"recursive.2.1",
|
|
34
|
+
"test2.1"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"value_Data_types": {
|
|
4
|
+
"test_null": null,
|
|
5
|
+
"test_int": 42,
|
|
6
|
+
"test_float": 3.14,
|
|
7
|
+
"test_str": "foo",
|
|
8
|
+
"test_bool": true,
|
|
9
|
+
"test_arr": ["Test"],
|
|
10
|
+
"test_object": {
|
|
11
|
+
"foo": "bar"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"disclosureFrame": {
|
|
16
|
+
"value_Data_types": {
|
|
17
|
+
"_sd": [
|
|
18
|
+
"test_null",
|
|
19
|
+
"test_int",
|
|
20
|
+
"test_float",
|
|
21
|
+
"test_str",
|
|
22
|
+
"test_bool",
|
|
23
|
+
"test_arr",
|
|
24
|
+
"test_object"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"presentationFrames": {
|
|
29
|
+
"value_Data_types": {
|
|
30
|
+
"test_null": true,
|
|
31
|
+
"test_int": true,
|
|
32
|
+
"test_float": true,
|
|
33
|
+
"test_str": true,
|
|
34
|
+
"test_bool": true,
|
|
35
|
+
"test_arr": true,
|
|
36
|
+
"test_object": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"presentedClaims": {
|
|
40
|
+
"value_Data_types": {
|
|
41
|
+
"test_null": null,
|
|
42
|
+
"test_int": 42,
|
|
43
|
+
"test_float": 3.14,
|
|
44
|
+
"test_str": "foo",
|
|
45
|
+
"test_bool": true,
|
|
46
|
+
"test_arr": ["Test"],
|
|
47
|
+
"test_object": {
|
|
48
|
+
"foo": "bar"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"requiredClaimKeys": [
|
|
53
|
+
"value_Data_types.test_null",
|
|
54
|
+
"value_Data_types.test_int",
|
|
55
|
+
"value_Data_types.test_float",
|
|
56
|
+
"value_Data_types.test_str",
|
|
57
|
+
"value_Data_types.test_bool",
|
|
58
|
+
"value_Data_types.test_arr",
|
|
59
|
+
"value_Data_types.test_object",
|
|
60
|
+
"value_Data_types.test_object.foo"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
{
|
|
2
|
+
"claims": {
|
|
3
|
+
"foo": ["one", "two"],
|
|
4
|
+
"bar": {
|
|
5
|
+
"red": 1,
|
|
6
|
+
"green": 2
|
|
7
|
+
},
|
|
8
|
+
"qux": [["blue", "yellow"]],
|
|
9
|
+
"baz": [["orange", "purple"], ["black", "white"]],
|
|
10
|
+
"animals": {
|
|
11
|
+
"snake": {
|
|
12
|
+
"name": "python",
|
|
13
|
+
"age": 10
|
|
14
|
+
},
|
|
15
|
+
"bird": {
|
|
16
|
+
"name": "eagle",
|
|
17
|
+
"age": 20
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"disclosureFrame": {
|
|
22
|
+
"foo": {
|
|
23
|
+
"_sd": [0, 1]
|
|
24
|
+
},
|
|
25
|
+
"bar": {
|
|
26
|
+
"_sd": ["red", "green"]
|
|
27
|
+
},
|
|
28
|
+
"qux": {
|
|
29
|
+
"_sd": [0],
|
|
30
|
+
"0": {
|
|
31
|
+
"_sd": [0, 1]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"baz": {
|
|
35
|
+
"_sd": [0, 1],
|
|
36
|
+
"0": {
|
|
37
|
+
"_sd": [0, 1]
|
|
38
|
+
},
|
|
39
|
+
"1": {
|
|
40
|
+
"_sd": [0, 1]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"animals": {
|
|
44
|
+
"_sd": ["snake", "bird"],
|
|
45
|
+
"snake": {
|
|
46
|
+
"_sd": ["name", "age"]
|
|
47
|
+
},
|
|
48
|
+
"bird": {
|
|
49
|
+
"_sd": ["name", "age"]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"presentationFrames": {
|
|
54
|
+
"foo": {
|
|
55
|
+
"1": true
|
|
56
|
+
},
|
|
57
|
+
"bar": {
|
|
58
|
+
"green": true
|
|
59
|
+
},
|
|
60
|
+
"qux": {
|
|
61
|
+
"0": {
|
|
62
|
+
"0": true,
|
|
63
|
+
"1": true
|
|
64
|
+
},
|
|
65
|
+
"1": {
|
|
66
|
+
"0": true,
|
|
67
|
+
"1": true
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"baz": {
|
|
71
|
+
"0": {
|
|
72
|
+
"0": true,
|
|
73
|
+
"1": true
|
|
74
|
+
},
|
|
75
|
+
"1": {
|
|
76
|
+
"0": true,
|
|
77
|
+
"1": true
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"animals": {
|
|
81
|
+
"snake": {
|
|
82
|
+
"age": true
|
|
83
|
+
},
|
|
84
|
+
"bird": {
|
|
85
|
+
"age": true
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"presentedClaims": {
|
|
90
|
+
"foo": ["two"],
|
|
91
|
+
"bar": {
|
|
92
|
+
"green": 2
|
|
93
|
+
},
|
|
94
|
+
"qux": [["blue", "yellow"]],
|
|
95
|
+
"baz": [["orange", "purple"], ["black", "white"]],
|
|
96
|
+
"animals": {
|
|
97
|
+
"snake": {
|
|
98
|
+
"age": 10
|
|
99
|
+
},
|
|
100
|
+
"bird": {
|
|
101
|
+
"age": 20
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"requiredClaimKeys": [
|
|
106
|
+
"foo.1",
|
|
107
|
+
"bar.green",
|
|
108
|
+
"qux.0.0",
|
|
109
|
+
"qux.0.1",
|
|
110
|
+
"baz.0.0",
|
|
111
|
+
"baz.0.1",
|
|
112
|
+
"baz.1.0",
|
|
113
|
+
"baz.1.1",
|
|
114
|
+
"animals.snake.age",
|
|
115
|
+
"animals.bird.age"
|
|
116
|
+
]
|
|
117
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { unpackObj } from '../src/decode';
|
|
3
|
+
import { Disclosure } from '../src/utils';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tests for RFC 9901 validation checks added to unpackObj / unpackObjInternal.
|
|
7
|
+
*
|
|
8
|
+
* Section 7.1 step 4: Duplicate digest rejection
|
|
9
|
+
* Section 7.1 step 5: Unreferenced disclosure rejection
|
|
10
|
+
* Section 7.1 step 3c.ii.3: Claim name collision rejection
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const makeDisclosure = (
|
|
14
|
+
digest: string,
|
|
15
|
+
key: string | undefined,
|
|
16
|
+
value: unknown,
|
|
17
|
+
) =>
|
|
18
|
+
Disclosure.fromArray(key ? ['salt', key, value] : ['salt', value], {
|
|
19
|
+
digest,
|
|
20
|
+
encoded: `encoded-${digest}`,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('RFC 9901 validation', () => {
|
|
24
|
+
// ──────────────────────────────────────────
|
|
25
|
+
// 7.1 step 4 — Duplicate digest in _sd array
|
|
26
|
+
// ──────────────────────────────────────────
|
|
27
|
+
test('rejects duplicate digest in _sd array', () => {
|
|
28
|
+
const digest = 'abc123';
|
|
29
|
+
const payload = { _sd: [digest, digest] };
|
|
30
|
+
const map: Record<string, Disclosure> = {
|
|
31
|
+
[digest]: makeDisclosure(digest, 'foo', 'bar'),
|
|
32
|
+
};
|
|
33
|
+
expect(() => unpackObj(payload, map)).toThrow(
|
|
34
|
+
'Duplicate digest found in SD-JWT payload',
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// ──────────────────────────────────────────
|
|
39
|
+
// 7.1 step 4 — Duplicate digest across nested _sd
|
|
40
|
+
// ──────────────────────────────────────────
|
|
41
|
+
test('rejects duplicate digest across nested _sd arrays', () => {
|
|
42
|
+
const digest = 'dup1';
|
|
43
|
+
const payload = {
|
|
44
|
+
_sd: [digest],
|
|
45
|
+
nested: {
|
|
46
|
+
_sd: [digest],
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
const map: Record<string, Disclosure> = {
|
|
50
|
+
[digest]: makeDisclosure(digest, 'x', 'y'),
|
|
51
|
+
};
|
|
52
|
+
expect(() => unpackObj(payload, map)).toThrow(
|
|
53
|
+
'Duplicate digest found in SD-JWT payload',
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// ──────────────────────────────────────────
|
|
58
|
+
// 7.1 step 4 — Duplicate digest in array items
|
|
59
|
+
// ──────────────────────────────────────────
|
|
60
|
+
test('rejects duplicate digest in array element disclosures', () => {
|
|
61
|
+
const digest = 'arrdup';
|
|
62
|
+
const payload = {
|
|
63
|
+
arr: [{ '...': digest }, { '...': digest }],
|
|
64
|
+
};
|
|
65
|
+
const map: Record<string, Disclosure> = {
|
|
66
|
+
[digest]: makeDisclosure(digest, undefined, 'val'),
|
|
67
|
+
};
|
|
68
|
+
expect(() => unpackObj(payload, map)).toThrow(
|
|
69
|
+
'Duplicate digest found in SD-JWT payload',
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// ──────────────────────────────────────────
|
|
74
|
+
// 7.1 step 5 — Unreferenced disclosure
|
|
75
|
+
// ──────────────────────────────────────────
|
|
76
|
+
test('rejects unreferenced disclosure', () => {
|
|
77
|
+
const usedDigest = 'used1';
|
|
78
|
+
const unusedDigest = 'unused1';
|
|
79
|
+
const payload = { _sd: [usedDigest] };
|
|
80
|
+
const map: Record<string, Disclosure> = {
|
|
81
|
+
[usedDigest]: makeDisclosure(usedDigest, 'a', 1),
|
|
82
|
+
[unusedDigest]: makeDisclosure(unusedDigest, 'b', 2),
|
|
83
|
+
};
|
|
84
|
+
expect(() => unpackObj(payload, map)).toThrow(
|
|
85
|
+
'Unreferenced disclosure(s) detected in SD-JWT',
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('rejects when no digests exist in payload but disclosures provided', () => {
|
|
90
|
+
const payload = { plain: 'value' };
|
|
91
|
+
const map: Record<string, Disclosure> = {
|
|
92
|
+
orphan: makeDisclosure('orphan', 'k', 'v'),
|
|
93
|
+
};
|
|
94
|
+
expect(() => unpackObj(payload, map)).toThrow(
|
|
95
|
+
'Unreferenced disclosure(s) detected in SD-JWT',
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// ──────────────────────────────────────────
|
|
100
|
+
// 7.1 step 3c.ii.3 — Claim name collision
|
|
101
|
+
// ──────────────────────────────────────────
|
|
102
|
+
test('rejects disclosed claim name that conflicts with plaintext key', () => {
|
|
103
|
+
const digest = 'col1';
|
|
104
|
+
// The payload has both a plaintext "name" and a disclosure that would add "name"
|
|
105
|
+
const payload = { name: 'Alice', _sd: [digest] };
|
|
106
|
+
const map: Record<string, Disclosure> = {
|
|
107
|
+
[digest]: makeDisclosure(digest, 'name', 'Mallory'),
|
|
108
|
+
};
|
|
109
|
+
expect(() => unpackObj(payload, map)).toThrow(
|
|
110
|
+
'Disclosed claim name "name" conflicts with existing payload key',
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ──────────────────────────────────────────
|
|
115
|
+
// Positive: valid SD-JWT unpacks without error
|
|
116
|
+
// ──────────────────────────────────────────
|
|
117
|
+
test('unpacks valid SD-JWT without errors', () => {
|
|
118
|
+
const d1 = 'digest1';
|
|
119
|
+
const d2 = 'digest2';
|
|
120
|
+
const payload = { _sd: [d1, d2], plain: 'hello' };
|
|
121
|
+
const map: Record<string, Disclosure> = {
|
|
122
|
+
[d1]: makeDisclosure(d1, 'foo', 'bar'),
|
|
123
|
+
[d2]: makeDisclosure(d2, 'baz', 42),
|
|
124
|
+
};
|
|
125
|
+
const { unpackedObj, disclosureKeymap } = unpackObj(payload, map);
|
|
126
|
+
expect(unpackedObj).toEqual({ plain: 'hello', foo: 'bar', baz: 42 });
|
|
127
|
+
expect(disclosureKeymap).toEqual({ foo: d1, baz: d2 });
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('unpacks valid SD-JWT with array disclosures', () => {
|
|
131
|
+
const d1 = 'arrdig1';
|
|
132
|
+
const d2 = 'arrdig2';
|
|
133
|
+
const payload = {
|
|
134
|
+
arr: [{ '...': d1 }, 'plainItem', { '...': d2 }],
|
|
135
|
+
};
|
|
136
|
+
const map: Record<string, Disclosure> = {
|
|
137
|
+
[d1]: makeDisclosure(d1, undefined, 'secret1'),
|
|
138
|
+
[d2]: makeDisclosure(d2, undefined, 'secret2'),
|
|
139
|
+
};
|
|
140
|
+
const { unpackedObj } = unpackObj(payload, map);
|
|
141
|
+
expect(unpackedObj).toEqual({ arr: ['secret1', 'plainItem', 'secret2'] });
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('allows empty disclosure map with no _sd in payload', () => {
|
|
145
|
+
const payload = { plain: 'value' };
|
|
146
|
+
const map: Record<string, Disclosure> = {};
|
|
147
|
+
const { unpackedObj } = unpackObj(payload, map);
|
|
148
|
+
expect(unpackedObj).toEqual({ plain: 'value' });
|
|
149
|
+
});
|
|
150
|
+
});
|
package/tsconfig.json
ADDED
package/build/base64url.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { Buffer } from 'buffer';
|
|
3
|
-
export declare class Base64url {
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* Encode into base64url string
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
|
-
static encode(input: string | Uint8Array | Buffer): string;
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
* Encode from JSON into a base64url string
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
static encodeFromJson(input: Record<string, unknown> | Array<unknown>): string;
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* Decode from base64url into JSON
|
|
19
|
-
*
|
|
20
|
-
*/
|
|
21
|
-
static decodeToJson<T extends Record<string, unknown> | Array<unknown> = Record<string, unknown>>(input: string): T;
|
|
22
|
-
/**
|
|
23
|
-
*
|
|
24
|
-
* Decode from base64url into a byte array
|
|
25
|
-
*
|
|
26
|
-
*/
|
|
27
|
-
static decode(input: string): Uint8Array;
|
|
28
|
-
}
|