@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
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { SDJWTException } from '@sd-jwt/utils';
|
|
2
|
+
import { Jwt } from '../jwt';
|
|
3
|
+
import Crypto from 'node:crypto';
|
|
4
|
+
import { Signer, Verifier } from '@sd-jwt/types';
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
describe('JWT', () => {
|
|
8
|
+
test('create', async () => {
|
|
9
|
+
const jwt = new Jwt({
|
|
10
|
+
header: { alg: 'EdDSA' },
|
|
11
|
+
payload: { foo: 'bar' },
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
expect(jwt.header).toEqual({ alg: 'EdDSA' });
|
|
15
|
+
expect(jwt.payload).toEqual({ foo: 'bar' });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('returns decoded JWT when correct JWT string is provided', () => {
|
|
19
|
+
// Two objects are created separately, the first: { alg: 'HS256', typ: 'JWT' } represents a JWT Header and the second: { sub: '1234567890', name: 'John Doe' } represents a JWT Payload.
|
|
20
|
+
// These objects are turned into strings with JSON.stringify. The resulting strings are encoded with base64 encoding using Buffer.from(string).toString('base64').
|
|
21
|
+
// These base64 encoded strings are concatenated with a period (.) between them, following the structure of a JWT, which is composed of three Base64-URL strings separated by dots (header.payload.signature).
|
|
22
|
+
// A 'signature' string is added at the end to represent a JWT signature.
|
|
23
|
+
// So, the jwt variable ends up being a string with the format of a base64Url encoded Header, a period, a base64Url encoded Payload, another period, and a 'signature' string.
|
|
24
|
+
// It's important to note that the 'signature' here is just a placeholder string and not an actual cryptographic signature generated from the header and payload data.
|
|
25
|
+
const jwt = `${Buffer.from(
|
|
26
|
+
JSON.stringify({ alg: 'HS256', typ: 'JWT' }),
|
|
27
|
+
).toString('base64')}.${Buffer.from(
|
|
28
|
+
JSON.stringify({ sub: '1234567890', name: 'John Doe' }),
|
|
29
|
+
).toString('base64')}.signature`;
|
|
30
|
+
const result = Jwt.decodeJWT(jwt);
|
|
31
|
+
expect(result).toEqual({
|
|
32
|
+
header: { alg: 'HS256', typ: 'JWT' },
|
|
33
|
+
payload: { sub: '1234567890', name: 'John Doe' },
|
|
34
|
+
signature: 'signature',
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('throws an error when JWT string is not correctly formed', () => {
|
|
39
|
+
const jwt = 'abc.def';
|
|
40
|
+
expect(() => Jwt.decodeJWT(jwt)).toThrow('Invalid JWT as input');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('throws an error when JWT parts are missing', () => {
|
|
44
|
+
const jwt = `${Buffer.from(
|
|
45
|
+
JSON.stringify({ alg: 'HS256', typ: 'JWT' }),
|
|
46
|
+
).toString('base64')}`;
|
|
47
|
+
expect(() => Jwt.decodeJWT(jwt)).toThrow('Invalid JWT as input');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('set', async () => {
|
|
51
|
+
const jwt = new Jwt();
|
|
52
|
+
jwt.setHeader({ alg: 'EdDSA' });
|
|
53
|
+
jwt.setPayload({ foo: 'bar' });
|
|
54
|
+
|
|
55
|
+
expect(jwt.header).toEqual({ alg: 'EdDSA' });
|
|
56
|
+
expect(jwt.payload).toEqual({ foo: 'bar' });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('sign', async () => {
|
|
60
|
+
const { privateKey } = Crypto.generateKeyPairSync('ed25519');
|
|
61
|
+
const testSigner: Signer = async (data: string) => {
|
|
62
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
63
|
+
return Buffer.from(sig).toString('base64url');
|
|
64
|
+
};
|
|
65
|
+
const jwt = new Jwt({
|
|
66
|
+
header: { alg: 'EdDSA' },
|
|
67
|
+
payload: { foo: 'bar' },
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const encodedJwt = await jwt.sign(testSigner);
|
|
71
|
+
expect(typeof encodedJwt).toBe('string');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('verify', async () => {
|
|
75
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
76
|
+
const testSigner: Signer = async (data: string) => {
|
|
77
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
78
|
+
return Buffer.from(sig).toString('base64url');
|
|
79
|
+
};
|
|
80
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
81
|
+
return Crypto.verify(
|
|
82
|
+
null,
|
|
83
|
+
Buffer.from(data),
|
|
84
|
+
publicKey,
|
|
85
|
+
Buffer.from(sig, 'base64url'),
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const jwt = new Jwt({
|
|
90
|
+
header: { alg: 'EdDSA' },
|
|
91
|
+
payload: { foo: 'bar' },
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const encodedJwt = await jwt.sign(testSigner);
|
|
95
|
+
const newJwt = Jwt.fromEncode(encodedJwt);
|
|
96
|
+
const verified = await newJwt.verify(testVerifier);
|
|
97
|
+
expect(verified).toStrictEqual({
|
|
98
|
+
header: { alg: 'EdDSA' },
|
|
99
|
+
payload: { foo: 'bar' },
|
|
100
|
+
});
|
|
101
|
+
try {
|
|
102
|
+
await newJwt.verify(() => false);
|
|
103
|
+
} catch (e: unknown) {
|
|
104
|
+
expect(e).toBeInstanceOf(SDJWTException);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('encode', async () => {
|
|
109
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
110
|
+
const testSigner: Signer = async (data: string) => {
|
|
111
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
112
|
+
return Buffer.from(sig).toString('base64url');
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const jwt = new Jwt({
|
|
116
|
+
header: { alg: 'EdDSA' },
|
|
117
|
+
payload: { foo: 'bar' },
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const encodedJwt = await jwt.sign(testSigner);
|
|
121
|
+
const newJwt = Jwt.fromEncode(encodedJwt);
|
|
122
|
+
const newEncodedJwt = newJwt.encodeJwt();
|
|
123
|
+
expect(newEncodedJwt).toBe(encodedJwt);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('decode failed', () => {
|
|
127
|
+
expect(() => Jwt.fromEncode('asfasfas')).toThrow();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('encode failed', async () => {
|
|
131
|
+
const jwt = new Jwt({
|
|
132
|
+
header: { alg: 'EdDSA' },
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
jwt.encodeJwt();
|
|
137
|
+
} catch (e: unknown) {
|
|
138
|
+
expect(e).toBeInstanceOf(SDJWTException);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { SDJWTException } from '@sd-jwt/utils';
|
|
2
|
+
import { KBJwt } from '../kbjwt';
|
|
3
|
+
import { KB_JWT_TYP, Signer, Verifier } from '@sd-jwt/types';
|
|
4
|
+
import Crypto from 'node:crypto';
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
describe('KB JWT', () => {
|
|
8
|
+
test('create', async () => {
|
|
9
|
+
const kbJwt = new KBJwt({
|
|
10
|
+
header: {
|
|
11
|
+
typ: KB_JWT_TYP,
|
|
12
|
+
alg: 'EdDSA',
|
|
13
|
+
},
|
|
14
|
+
payload: {
|
|
15
|
+
iat: 1,
|
|
16
|
+
aud: 'aud',
|
|
17
|
+
nonce: 'nonce',
|
|
18
|
+
sd_hash: 'hash',
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
expect(kbJwt.header).toEqual({
|
|
23
|
+
typ: KB_JWT_TYP,
|
|
24
|
+
alg: 'EdDSA',
|
|
25
|
+
});
|
|
26
|
+
expect(kbJwt.payload).toEqual({
|
|
27
|
+
iat: 1,
|
|
28
|
+
aud: 'aud',
|
|
29
|
+
nonce: 'nonce',
|
|
30
|
+
sd_hash: 'hash',
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('decode', async () => {
|
|
35
|
+
const { privateKey } = Crypto.generateKeyPairSync('ed25519');
|
|
36
|
+
const testSigner: Signer = async (data: string) => {
|
|
37
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
38
|
+
return Buffer.from(sig).toString('base64url');
|
|
39
|
+
};
|
|
40
|
+
const kbJwt = new KBJwt({
|
|
41
|
+
header: {
|
|
42
|
+
typ: KB_JWT_TYP,
|
|
43
|
+
alg: 'EdDSA',
|
|
44
|
+
},
|
|
45
|
+
payload: {
|
|
46
|
+
iat: 1,
|
|
47
|
+
aud: 'aud',
|
|
48
|
+
nonce: 'nonce',
|
|
49
|
+
sd_hash: 'hash',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const encodedKbJwt = await kbJwt.sign(testSigner);
|
|
53
|
+
const decoded = KBJwt.fromKBEncode(encodedKbJwt);
|
|
54
|
+
expect(decoded.header).toEqual({
|
|
55
|
+
typ: KB_JWT_TYP,
|
|
56
|
+
alg: 'EdDSA',
|
|
57
|
+
});
|
|
58
|
+
expect(decoded.payload).toEqual({
|
|
59
|
+
iat: 1,
|
|
60
|
+
aud: 'aud',
|
|
61
|
+
nonce: 'nonce',
|
|
62
|
+
sd_hash: 'hash',
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('verify', async () => {
|
|
67
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
68
|
+
const testSigner: Signer = async (data: string) => {
|
|
69
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
70
|
+
return Buffer.from(sig).toString('base64url');
|
|
71
|
+
};
|
|
72
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
73
|
+
return Crypto.verify(
|
|
74
|
+
null,
|
|
75
|
+
Buffer.from(data),
|
|
76
|
+
publicKey,
|
|
77
|
+
Buffer.from(sig, 'base64url'),
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
const kbJwt = new KBJwt({
|
|
81
|
+
header: {
|
|
82
|
+
typ: KB_JWT_TYP,
|
|
83
|
+
alg: 'EdDSA',
|
|
84
|
+
},
|
|
85
|
+
payload: {
|
|
86
|
+
iat: 1,
|
|
87
|
+
aud: 'aud',
|
|
88
|
+
nonce: 'nonce',
|
|
89
|
+
sd_hash: 'hash',
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const encodedKbJwt = await kbJwt.sign(testSigner);
|
|
93
|
+
const decoded = KBJwt.fromKBEncode(encodedKbJwt);
|
|
94
|
+
const verified = await decoded.verify(testVerifier);
|
|
95
|
+
expect(verified).toStrictEqual({
|
|
96
|
+
header: {
|
|
97
|
+
typ: KB_JWT_TYP,
|
|
98
|
+
alg: 'EdDSA',
|
|
99
|
+
},
|
|
100
|
+
payload: {
|
|
101
|
+
iat: 1,
|
|
102
|
+
aud: 'aud',
|
|
103
|
+
nonce: 'nonce',
|
|
104
|
+
sd_hash: 'hash',
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('verify failed', async () => {
|
|
110
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
111
|
+
const testSigner: Signer = async (data: string) => {
|
|
112
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
113
|
+
return Buffer.from(sig).toString('base64url');
|
|
114
|
+
};
|
|
115
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
116
|
+
return Crypto.verify(
|
|
117
|
+
null,
|
|
118
|
+
Buffer.from(data),
|
|
119
|
+
publicKey,
|
|
120
|
+
Buffer.from(sig, 'base64url'),
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const kbJwt = new KBJwt({
|
|
125
|
+
header: {
|
|
126
|
+
typ: KB_JWT_TYP,
|
|
127
|
+
alg: 'EdDSA',
|
|
128
|
+
},
|
|
129
|
+
payload: {
|
|
130
|
+
iat: 1,
|
|
131
|
+
aud: 'aud',
|
|
132
|
+
nonce: 'nonce',
|
|
133
|
+
sd_hash: '',
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
const encodedKbJwt = await kbJwt.sign(testSigner);
|
|
137
|
+
const decoded = KBJwt.fromKBEncode(encodedKbJwt);
|
|
138
|
+
try {
|
|
139
|
+
await decoded.verify(testVerifier);
|
|
140
|
+
} catch (e: unknown) {
|
|
141
|
+
const error = e as SDJWTException;
|
|
142
|
+
expect(error.message).toBe('Invalid Key Binding Jwt');
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
test('verify with custom Verifier', async () => {
|
|
147
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
148
|
+
const testSigner: Signer = async (data: string) => {
|
|
149
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
150
|
+
return Buffer.from(sig).toString('base64url');
|
|
151
|
+
};
|
|
152
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
153
|
+
return Crypto.verify(
|
|
154
|
+
null,
|
|
155
|
+
Buffer.from(data),
|
|
156
|
+
publicKey,
|
|
157
|
+
Buffer.from(sig, 'base64url'),
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const kbJwt = new KBJwt({
|
|
162
|
+
header: {
|
|
163
|
+
typ: KB_JWT_TYP,
|
|
164
|
+
alg: 'EdDSA',
|
|
165
|
+
},
|
|
166
|
+
payload: {
|
|
167
|
+
iat: 1,
|
|
168
|
+
aud: 'aud',
|
|
169
|
+
nonce: 'nonce',
|
|
170
|
+
sd_hash: 'hash',
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const encodedKbJwt = await kbJwt.sign(testSigner);
|
|
175
|
+
const decoded = KBJwt.fromKBEncode(encodedKbJwt);
|
|
176
|
+
const verified = await decoded.verify(testVerifier);
|
|
177
|
+
expect(verified).toStrictEqual({
|
|
178
|
+
header: {
|
|
179
|
+
typ: KB_JWT_TYP,
|
|
180
|
+
alg: 'EdDSA',
|
|
181
|
+
},
|
|
182
|
+
payload: {
|
|
183
|
+
iat: 1,
|
|
184
|
+
aud: 'aud',
|
|
185
|
+
nonce: 'nonce',
|
|
186
|
+
sd_hash: 'hash',
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('verify failed with custom Verifier', async () => {
|
|
192
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
193
|
+
const testSigner: Signer = async (data: string) => {
|
|
194
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
195
|
+
return Buffer.from(sig).toString('base64url');
|
|
196
|
+
};
|
|
197
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
198
|
+
return Crypto.verify(
|
|
199
|
+
null,
|
|
200
|
+
Buffer.from(data),
|
|
201
|
+
publicKey,
|
|
202
|
+
Buffer.from(sig, 'base64url'),
|
|
203
|
+
);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const kbJwt = new KBJwt({
|
|
207
|
+
header: {
|
|
208
|
+
typ: KB_JWT_TYP,
|
|
209
|
+
alg: 'EdDSA',
|
|
210
|
+
},
|
|
211
|
+
payload: {
|
|
212
|
+
iat: 1,
|
|
213
|
+
aud: 'aud',
|
|
214
|
+
nonce: 'nonce',
|
|
215
|
+
sd_hash: '',
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const encodedKbJwt = await kbJwt.sign(testSigner);
|
|
220
|
+
const decoded = KBJwt.fromKBEncode(encodedKbJwt);
|
|
221
|
+
try {
|
|
222
|
+
await decoded.verify(testVerifier);
|
|
223
|
+
} catch (e: unknown) {
|
|
224
|
+
const error = e as SDJWTException;
|
|
225
|
+
expect(error.message).toBe('Invalid Key Binding Jwt');
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test('compatibility test for version 06', async () => {
|
|
230
|
+
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
231
|
+
const testSigner: Signer = async (data: string) => {
|
|
232
|
+
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
233
|
+
return Buffer.from(sig).toString('base64url');
|
|
234
|
+
};
|
|
235
|
+
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
236
|
+
return Crypto.verify(
|
|
237
|
+
null,
|
|
238
|
+
Buffer.from(data),
|
|
239
|
+
publicKey,
|
|
240
|
+
Buffer.from(sig, 'base64url'),
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
const kbJwt = new KBJwt({
|
|
244
|
+
header: {
|
|
245
|
+
typ: KB_JWT_TYP,
|
|
246
|
+
alg: 'EdDSA',
|
|
247
|
+
},
|
|
248
|
+
payload: {
|
|
249
|
+
iat: 1,
|
|
250
|
+
aud: 'aud',
|
|
251
|
+
nonce: 'nonce',
|
|
252
|
+
sd_hash: 'hash',
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
(kbJwt.payload as Record<string, unknown>)._sd_hash = 'hash';
|
|
257
|
+
(kbJwt.payload as Record<string, unknown>).sd_hash = undefined;
|
|
258
|
+
|
|
259
|
+
const encodedKbJwt = await kbJwt.sign(testSigner);
|
|
260
|
+
const decoded = KBJwt.fromKBEncode(encodedKbJwt);
|
|
261
|
+
const verified = await decoded.verify(testVerifier);
|
|
262
|
+
expect(verified).toStrictEqual({
|
|
263
|
+
header: {
|
|
264
|
+
typ: KB_JWT_TYP,
|
|
265
|
+
alg: 'EdDSA',
|
|
266
|
+
},
|
|
267
|
+
payload: {
|
|
268
|
+
iat: 1,
|
|
269
|
+
aud: 'aud',
|
|
270
|
+
nonce: 'nonce',
|
|
271
|
+
_sd_hash: 'hash',
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|