@sd-jwt/core 0.4.1-next.12 → 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 +5 -8
- package/dist/index.d.ts +5 -8
- package/dist/index.js +16 -32
- package/dist/index.mjs +17 -33
- package/package.json +7 -7
- package/src/jwt.ts +9 -30
- package/src/kbjwt.ts +3 -2
- package/src/test/index.spec.ts +1 -36
- package/src/test/jwt.spec.ts +0 -61
- package/src/test/sdjwt.spec.ts +1 -3
package/dist/index.d.mts
CHANGED
|
@@ -6,13 +6,11 @@ type JwtData<Header extends Record<string, unknown>, Payload extends Record<stri
|
|
|
6
6
|
header?: Header;
|
|
7
7
|
payload?: Payload;
|
|
8
8
|
signature?: Base64urlString;
|
|
9
|
-
encoded?: string;
|
|
10
9
|
};
|
|
11
10
|
declare class Jwt<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>> {
|
|
12
11
|
header?: Header;
|
|
13
12
|
payload?: Payload;
|
|
14
13
|
signature?: Base64urlString;
|
|
15
|
-
private encoded?;
|
|
16
14
|
constructor(data?: JwtData<Header, Payload>);
|
|
17
15
|
static decodeJWT<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>>(jwt: string): {
|
|
18
16
|
header: Header;
|
|
@@ -22,12 +20,11 @@ declare class Jwt<Header extends Record<string, unknown> = Record<string, unknow
|
|
|
22
20
|
static fromEncode<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>>(encodedJwt: string): Jwt<Header, Payload>;
|
|
23
21
|
setHeader(header: Header): Jwt<Header, Payload>;
|
|
24
22
|
setPayload(payload: Payload): Jwt<Header, Payload>;
|
|
25
|
-
protected getUnsignedToken(): string;
|
|
26
23
|
sign(signer: Signer): Promise<string>;
|
|
27
24
|
encodeJwt(): string;
|
|
28
25
|
verify(verifier: Verifier): Promise<{
|
|
29
|
-
payload: Payload
|
|
30
|
-
header: Header
|
|
26
|
+
payload: Payload;
|
|
27
|
+
header: Header;
|
|
31
28
|
}>;
|
|
32
29
|
}
|
|
33
30
|
|
|
@@ -95,11 +92,11 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
95
92
|
}): Promise<SDJWTCompact>;
|
|
96
93
|
verify(encodedSDJwt: string, requiredClaimKeys?: string[], requireKeyBindings?: boolean): Promise<{
|
|
97
94
|
payload: unknown;
|
|
98
|
-
header: Record<string, unknown
|
|
95
|
+
header: Record<string, unknown>;
|
|
99
96
|
kb?: undefined;
|
|
100
97
|
} | {
|
|
101
98
|
payload: unknown;
|
|
102
|
-
header: Record<string, unknown
|
|
99
|
+
header: Record<string, unknown>;
|
|
103
100
|
kb: {
|
|
104
101
|
payload: _sd_jwt_types.kbPayload;
|
|
105
102
|
header: _sd_jwt_types.kbHeader;
|
|
@@ -108,7 +105,7 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
108
105
|
private calculateSDHash;
|
|
109
106
|
validate(encodedSDJwt: string): Promise<{
|
|
110
107
|
payload: unknown;
|
|
111
|
-
header: Record<string, unknown
|
|
108
|
+
header: Record<string, unknown>;
|
|
112
109
|
}>;
|
|
113
110
|
config(newConfig: SDJWTConfig): void;
|
|
114
111
|
encode(sdJwt: SDJwt): SDJWTCompact;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,13 +6,11 @@ type JwtData<Header extends Record<string, unknown>, Payload extends Record<stri
|
|
|
6
6
|
header?: Header;
|
|
7
7
|
payload?: Payload;
|
|
8
8
|
signature?: Base64urlString;
|
|
9
|
-
encoded?: string;
|
|
10
9
|
};
|
|
11
10
|
declare class Jwt<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>> {
|
|
12
11
|
header?: Header;
|
|
13
12
|
payload?: Payload;
|
|
14
13
|
signature?: Base64urlString;
|
|
15
|
-
private encoded?;
|
|
16
14
|
constructor(data?: JwtData<Header, Payload>);
|
|
17
15
|
static decodeJWT<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>>(jwt: string): {
|
|
18
16
|
header: Header;
|
|
@@ -22,12 +20,11 @@ declare class Jwt<Header extends Record<string, unknown> = Record<string, unknow
|
|
|
22
20
|
static fromEncode<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>>(encodedJwt: string): Jwt<Header, Payload>;
|
|
23
21
|
setHeader(header: Header): Jwt<Header, Payload>;
|
|
24
22
|
setPayload(payload: Payload): Jwt<Header, Payload>;
|
|
25
|
-
protected getUnsignedToken(): string;
|
|
26
23
|
sign(signer: Signer): Promise<string>;
|
|
27
24
|
encodeJwt(): string;
|
|
28
25
|
verify(verifier: Verifier): Promise<{
|
|
29
|
-
payload: Payload
|
|
30
|
-
header: Header
|
|
26
|
+
payload: Payload;
|
|
27
|
+
header: Header;
|
|
31
28
|
}>;
|
|
32
29
|
}
|
|
33
30
|
|
|
@@ -95,11 +92,11 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
95
92
|
}): Promise<SDJWTCompact>;
|
|
96
93
|
verify(encodedSDJwt: string, requiredClaimKeys?: string[], requireKeyBindings?: boolean): Promise<{
|
|
97
94
|
payload: unknown;
|
|
98
|
-
header: Record<string, unknown
|
|
95
|
+
header: Record<string, unknown>;
|
|
99
96
|
kb?: undefined;
|
|
100
97
|
} | {
|
|
101
98
|
payload: unknown;
|
|
102
|
-
header: Record<string, unknown
|
|
99
|
+
header: Record<string, unknown>;
|
|
103
100
|
kb: {
|
|
104
101
|
payload: _sd_jwt_types.kbPayload;
|
|
105
102
|
header: _sd_jwt_types.kbHeader;
|
|
@@ -108,7 +105,7 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
108
105
|
private calculateSDHash;
|
|
109
106
|
validate(encodedSDJwt: string): Promise<{
|
|
110
107
|
payload: unknown;
|
|
111
|
-
header: Record<string, unknown
|
|
108
|
+
header: Record<string, unknown>;
|
|
112
109
|
}>;
|
|
113
110
|
config(newConfig: SDJWTConfig): void;
|
|
114
111
|
encode(sdJwt: SDJwt): SDJWTCompact;
|
package/dist/index.js
CHANGED
|
@@ -76,7 +76,6 @@ var Jwt = class _Jwt {
|
|
|
76
76
|
this.header = data == null ? void 0 : data.header;
|
|
77
77
|
this.payload = data == null ? void 0 : data.payload;
|
|
78
78
|
this.signature = data == null ? void 0 : data.signature;
|
|
79
|
-
this.encoded = data == null ? void 0 : data.encoded;
|
|
80
79
|
}
|
|
81
80
|
static decodeJWT(jwt) {
|
|
82
81
|
return (0, import_decode.decodeJwt)(jwt);
|
|
@@ -88,48 +87,31 @@ var Jwt = class _Jwt {
|
|
|
88
87
|
const jwt = new _Jwt({
|
|
89
88
|
header,
|
|
90
89
|
payload,
|
|
91
|
-
signature
|
|
92
|
-
encoded: encodedJwt
|
|
90
|
+
signature
|
|
93
91
|
});
|
|
94
92
|
return jwt;
|
|
95
93
|
}
|
|
96
94
|
setHeader(header) {
|
|
97
95
|
this.header = header;
|
|
98
|
-
this.encoded = void 0;
|
|
99
96
|
return this;
|
|
100
97
|
}
|
|
101
98
|
setPayload(payload) {
|
|
102
99
|
this.payload = payload;
|
|
103
|
-
this.encoded = void 0;
|
|
104
100
|
return this;
|
|
105
101
|
}
|
|
106
|
-
getUnsignedToken() {
|
|
107
|
-
if (!this.header || !this.payload) {
|
|
108
|
-
throw new import_utils.SDJWTException("Serialize Error: Invalid JWT");
|
|
109
|
-
}
|
|
110
|
-
if (this.encoded) {
|
|
111
|
-
const parts = this.encoded.split(".");
|
|
112
|
-
if (parts.length !== 3) {
|
|
113
|
-
throw new import_utils.SDJWTException(`Invalid JWT format: ${this.encoded}`);
|
|
114
|
-
}
|
|
115
|
-
const unsignedToken = parts.slice(0, 2).join(".");
|
|
116
|
-
return unsignedToken;
|
|
117
|
-
}
|
|
118
|
-
const header = (0, import_utils.Base64urlEncode)(JSON.stringify(this.header));
|
|
119
|
-
const payload = (0, import_utils.Base64urlEncode)(JSON.stringify(this.payload));
|
|
120
|
-
return `${header}.${payload}`;
|
|
121
|
-
}
|
|
122
102
|
sign(signer) {
|
|
123
103
|
return __async(this, null, function* () {
|
|
124
|
-
|
|
104
|
+
if (!this.header || !this.payload) {
|
|
105
|
+
throw new import_utils.SDJWTException("Sign Error: Invalid JWT");
|
|
106
|
+
}
|
|
107
|
+
const header = (0, import_utils.Base64urlEncode)(JSON.stringify(this.header));
|
|
108
|
+
const payload = (0, import_utils.Base64urlEncode)(JSON.stringify(this.payload));
|
|
109
|
+
const data = `${header}.${payload}`;
|
|
125
110
|
this.signature = yield signer(data);
|
|
126
111
|
return this.encodeJwt();
|
|
127
112
|
});
|
|
128
113
|
}
|
|
129
114
|
encodeJwt() {
|
|
130
|
-
if (this.encoded) {
|
|
131
|
-
return this.encoded;
|
|
132
|
-
}
|
|
133
115
|
if (!this.header || !this.payload || !this.signature) {
|
|
134
116
|
throw new import_utils.SDJWTException("Serialize Error: Invalid JWT");
|
|
135
117
|
}
|
|
@@ -137,15 +119,16 @@ var Jwt = class _Jwt {
|
|
|
137
119
|
const payload = (0, import_utils.Base64urlEncode)(JSON.stringify(this.payload));
|
|
138
120
|
const signature = this.signature;
|
|
139
121
|
const compact = `${header}.${payload}.${signature}`;
|
|
140
|
-
this.encoded = compact;
|
|
141
122
|
return compact;
|
|
142
123
|
}
|
|
143
124
|
verify(verifier) {
|
|
144
125
|
return __async(this, null, function* () {
|
|
145
|
-
if (!this.signature) {
|
|
146
|
-
throw new import_utils.SDJWTException("Verify Error:
|
|
126
|
+
if (!this.header || !this.payload || !this.signature) {
|
|
127
|
+
throw new import_utils.SDJWTException("Verify Error: Invalid JWT");
|
|
147
128
|
}
|
|
148
|
-
const
|
|
129
|
+
const header = (0, import_utils.Base64urlEncode)(JSON.stringify(this.header));
|
|
130
|
+
const payload = (0, import_utils.Base64urlEncode)(JSON.stringify(this.payload));
|
|
131
|
+
const data = `${header}.${payload}`;
|
|
149
132
|
const verified = yield verifier(data, this.signature);
|
|
150
133
|
if (!verified) {
|
|
151
134
|
throw new import_utils.SDJWTException("Verify Error: Invalid JWT Signature");
|
|
@@ -171,7 +154,9 @@ var KBJwt = class _KBJwt extends Jwt {
|
|
|
171
154
|
!(this.payload.sd_hash || ((_a = this.payload) == null ? void 0 : _a._sd_hash))) {
|
|
172
155
|
throw new import_utils2.SDJWTException("Invalid Key Binding Jwt");
|
|
173
156
|
}
|
|
174
|
-
const
|
|
157
|
+
const header = (0, import_utils2.Base64urlEncode)(JSON.stringify(this.header));
|
|
158
|
+
const payload = (0, import_utils2.Base64urlEncode)(JSON.stringify(this.payload));
|
|
159
|
+
const data = `${header}.${payload}`;
|
|
175
160
|
const verified = yield values.verifier(
|
|
176
161
|
data,
|
|
177
162
|
this.signature,
|
|
@@ -191,8 +176,7 @@ var KBJwt = class _KBJwt extends Jwt {
|
|
|
191
176
|
const jwt = new _KBJwt({
|
|
192
177
|
header,
|
|
193
178
|
payload,
|
|
194
|
-
signature
|
|
195
|
-
encoded: encodedJwt
|
|
179
|
+
signature
|
|
196
180
|
});
|
|
197
181
|
return jwt;
|
|
198
182
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -49,7 +49,6 @@ var Jwt = class _Jwt {
|
|
|
49
49
|
this.header = data == null ? void 0 : data.header;
|
|
50
50
|
this.payload = data == null ? void 0 : data.payload;
|
|
51
51
|
this.signature = data == null ? void 0 : data.signature;
|
|
52
|
-
this.encoded = data == null ? void 0 : data.encoded;
|
|
53
52
|
}
|
|
54
53
|
static decodeJWT(jwt) {
|
|
55
54
|
return decodeJwt(jwt);
|
|
@@ -61,48 +60,31 @@ var Jwt = class _Jwt {
|
|
|
61
60
|
const jwt = new _Jwt({
|
|
62
61
|
header,
|
|
63
62
|
payload,
|
|
64
|
-
signature
|
|
65
|
-
encoded: encodedJwt
|
|
63
|
+
signature
|
|
66
64
|
});
|
|
67
65
|
return jwt;
|
|
68
66
|
}
|
|
69
67
|
setHeader(header) {
|
|
70
68
|
this.header = header;
|
|
71
|
-
this.encoded = void 0;
|
|
72
69
|
return this;
|
|
73
70
|
}
|
|
74
71
|
setPayload(payload) {
|
|
75
72
|
this.payload = payload;
|
|
76
|
-
this.encoded = void 0;
|
|
77
73
|
return this;
|
|
78
74
|
}
|
|
79
|
-
getUnsignedToken() {
|
|
80
|
-
if (!this.header || !this.payload) {
|
|
81
|
-
throw new SDJWTException("Serialize Error: Invalid JWT");
|
|
82
|
-
}
|
|
83
|
-
if (this.encoded) {
|
|
84
|
-
const parts = this.encoded.split(".");
|
|
85
|
-
if (parts.length !== 3) {
|
|
86
|
-
throw new SDJWTException(`Invalid JWT format: ${this.encoded}`);
|
|
87
|
-
}
|
|
88
|
-
const unsignedToken = parts.slice(0, 2).join(".");
|
|
89
|
-
return unsignedToken;
|
|
90
|
-
}
|
|
91
|
-
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
92
|
-
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
93
|
-
return `${header}.${payload}`;
|
|
94
|
-
}
|
|
95
75
|
sign(signer) {
|
|
96
76
|
return __async(this, null, function* () {
|
|
97
|
-
|
|
77
|
+
if (!this.header || !this.payload) {
|
|
78
|
+
throw new SDJWTException("Sign Error: Invalid JWT");
|
|
79
|
+
}
|
|
80
|
+
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
81
|
+
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
82
|
+
const data = `${header}.${payload}`;
|
|
98
83
|
this.signature = yield signer(data);
|
|
99
84
|
return this.encodeJwt();
|
|
100
85
|
});
|
|
101
86
|
}
|
|
102
87
|
encodeJwt() {
|
|
103
|
-
if (this.encoded) {
|
|
104
|
-
return this.encoded;
|
|
105
|
-
}
|
|
106
88
|
if (!this.header || !this.payload || !this.signature) {
|
|
107
89
|
throw new SDJWTException("Serialize Error: Invalid JWT");
|
|
108
90
|
}
|
|
@@ -110,15 +92,16 @@ var Jwt = class _Jwt {
|
|
|
110
92
|
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
111
93
|
const signature = this.signature;
|
|
112
94
|
const compact = `${header}.${payload}.${signature}`;
|
|
113
|
-
this.encoded = compact;
|
|
114
95
|
return compact;
|
|
115
96
|
}
|
|
116
97
|
verify(verifier) {
|
|
117
98
|
return __async(this, null, function* () {
|
|
118
|
-
if (!this.signature) {
|
|
119
|
-
throw new SDJWTException("Verify Error:
|
|
99
|
+
if (!this.header || !this.payload || !this.signature) {
|
|
100
|
+
throw new SDJWTException("Verify Error: Invalid JWT");
|
|
120
101
|
}
|
|
121
|
-
const
|
|
102
|
+
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
103
|
+
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
104
|
+
const data = `${header}.${payload}`;
|
|
122
105
|
const verified = yield verifier(data, this.signature);
|
|
123
106
|
if (!verified) {
|
|
124
107
|
throw new SDJWTException("Verify Error: Invalid JWT Signature");
|
|
@@ -129,7 +112,7 @@ var Jwt = class _Jwt {
|
|
|
129
112
|
};
|
|
130
113
|
|
|
131
114
|
// src/kbjwt.ts
|
|
132
|
-
import { SDJWTException as SDJWTException2 } from "@sd-jwt/utils";
|
|
115
|
+
import { Base64urlEncode as Base64urlEncode2, SDJWTException as SDJWTException2 } from "@sd-jwt/utils";
|
|
133
116
|
import {
|
|
134
117
|
KB_JWT_TYP
|
|
135
118
|
} from "@sd-jwt/types";
|
|
@@ -146,7 +129,9 @@ var KBJwt = class _KBJwt extends Jwt {
|
|
|
146
129
|
!(this.payload.sd_hash || ((_a = this.payload) == null ? void 0 : _a._sd_hash))) {
|
|
147
130
|
throw new SDJWTException2("Invalid Key Binding Jwt");
|
|
148
131
|
}
|
|
149
|
-
const
|
|
132
|
+
const header = Base64urlEncode2(JSON.stringify(this.header));
|
|
133
|
+
const payload = Base64urlEncode2(JSON.stringify(this.payload));
|
|
134
|
+
const data = `${header}.${payload}`;
|
|
150
135
|
const verified = yield values.verifier(
|
|
151
136
|
data,
|
|
152
137
|
this.signature,
|
|
@@ -166,8 +151,7 @@ var KBJwt = class _KBJwt extends Jwt {
|
|
|
166
151
|
const jwt = new _KBJwt({
|
|
167
152
|
header,
|
|
168
153
|
payload,
|
|
169
|
-
signature
|
|
170
|
-
encoded: encodedJwt
|
|
154
|
+
signature
|
|
171
155
|
});
|
|
172
156
|
return jwt;
|
|
173
157
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/core",
|
|
3
|
-
"version": "0.4.1-next.
|
|
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,13 +38,13 @@
|
|
|
38
38
|
},
|
|
39
39
|
"license": "Apache-2.0",
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@sd-jwt/crypto-nodejs": "0.4.1-next.
|
|
41
|
+
"@sd-jwt/crypto-nodejs": "0.4.1-next.2+b11bedf"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@sd-jwt/decode": "0.4.1-next.
|
|
45
|
-
"@sd-jwt/present": "0.4.1-next.
|
|
46
|
-
"@sd-jwt/types": "0.4.1-next.
|
|
47
|
-
"@sd-jwt/utils": "0.4.1-next.
|
|
44
|
+
"@sd-jwt/decode": "0.4.1-next.2+b11bedf",
|
|
45
|
+
"@sd-jwt/present": "0.4.1-next.2+b11bedf",
|
|
46
|
+
"@sd-jwt/types": "0.4.1-next.2+b11bedf",
|
|
47
|
+
"@sd-jwt/utils": "0.4.1-next.2+b11bedf"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"esm"
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "b11bedfe62dd1827653a76226ebdca3e0da1bbe0"
|
|
66
66
|
}
|
package/src/jwt.ts
CHANGED
|
@@ -9,7 +9,6 @@ export type JwtData<
|
|
|
9
9
|
header?: Header;
|
|
10
10
|
payload?: Payload;
|
|
11
11
|
signature?: Base64urlString;
|
|
12
|
-
encoded?: string;
|
|
13
12
|
};
|
|
14
13
|
|
|
15
14
|
// This class is used to create and verify JWT
|
|
@@ -21,13 +20,11 @@ export class Jwt<
|
|
|
21
20
|
public header?: Header;
|
|
22
21
|
public payload?: Payload;
|
|
23
22
|
public signature?: Base64urlString;
|
|
24
|
-
private encoded?: string;
|
|
25
23
|
|
|
26
24
|
constructor(data?: JwtData<Header, Payload>) {
|
|
27
25
|
this.header = data?.header;
|
|
28
26
|
this.payload = data?.payload;
|
|
29
27
|
this.signature = data?.signature;
|
|
30
|
-
this.encoded = data?.encoded;
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
public static decodeJWT<
|
|
@@ -51,7 +48,6 @@ export class Jwt<
|
|
|
51
48
|
header,
|
|
52
49
|
payload,
|
|
53
50
|
signature,
|
|
54
|
-
encoded: encodedJwt,
|
|
55
51
|
});
|
|
56
52
|
|
|
57
53
|
return jwt;
|
|
@@ -59,47 +55,28 @@ export class Jwt<
|
|
|
59
55
|
|
|
60
56
|
public setHeader(header: Header): Jwt<Header, Payload> {
|
|
61
57
|
this.header = header;
|
|
62
|
-
this.encoded = undefined;
|
|
63
58
|
return this;
|
|
64
59
|
}
|
|
65
60
|
|
|
66
61
|
public setPayload(payload: Payload): Jwt<Header, Payload> {
|
|
67
62
|
this.payload = payload;
|
|
68
|
-
this.encoded = undefined;
|
|
69
63
|
return this;
|
|
70
64
|
}
|
|
71
65
|
|
|
72
|
-
|
|
66
|
+
public async sign(signer: Signer) {
|
|
73
67
|
if (!this.header || !this.payload) {
|
|
74
|
-
throw new SDJWTException('
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (this.encoded) {
|
|
78
|
-
const parts = this.encoded.split('.');
|
|
79
|
-
if (parts.length !== 3) {
|
|
80
|
-
throw new SDJWTException(`Invalid JWT format: ${this.encoded}`);
|
|
81
|
-
}
|
|
82
|
-
const unsignedToken = parts.slice(0, 2).join('.');
|
|
83
|
-
return unsignedToken;
|
|
68
|
+
throw new SDJWTException('Sign Error: Invalid JWT');
|
|
84
69
|
}
|
|
85
70
|
|
|
86
71
|
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
87
72
|
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
public async sign(signer: Signer) {
|
|
92
|
-
const data = this.getUnsignedToken();
|
|
73
|
+
const data = `${header}.${payload}`;
|
|
93
74
|
this.signature = await signer(data);
|
|
94
75
|
|
|
95
76
|
return this.encodeJwt();
|
|
96
77
|
}
|
|
97
78
|
|
|
98
79
|
public encodeJwt(): string {
|
|
99
|
-
if (this.encoded) {
|
|
100
|
-
return this.encoded;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
80
|
if (!this.header || !this.payload || !this.signature) {
|
|
104
81
|
throw new SDJWTException('Serialize Error: Invalid JWT');
|
|
105
82
|
}
|
|
@@ -108,16 +85,18 @@ export class Jwt<
|
|
|
108
85
|
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
109
86
|
const signature = this.signature;
|
|
110
87
|
const compact = `${header}.${payload}.${signature}`;
|
|
111
|
-
this.encoded = compact;
|
|
112
88
|
|
|
113
89
|
return compact;
|
|
114
90
|
}
|
|
115
91
|
|
|
116
92
|
public async verify(verifier: Verifier) {
|
|
117
|
-
if (!this.signature) {
|
|
118
|
-
throw new SDJWTException('Verify Error:
|
|
93
|
+
if (!this.header || !this.payload || !this.signature) {
|
|
94
|
+
throw new SDJWTException('Verify Error: Invalid JWT');
|
|
119
95
|
}
|
|
120
|
-
|
|
96
|
+
|
|
97
|
+
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
98
|
+
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
99
|
+
const data = `${header}.${payload}`;
|
|
121
100
|
|
|
122
101
|
const verified = await verifier(data, this.signature);
|
|
123
102
|
if (!verified) {
|
package/src/kbjwt.ts
CHANGED
|
@@ -36,7 +36,9 @@ export class KBJwt<
|
|
|
36
36
|
throw new SDJWTException('Invalid Key Binding Jwt');
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const
|
|
39
|
+
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
40
|
+
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
41
|
+
const data = `${header}.${payload}`;
|
|
40
42
|
const verified = await values.verifier(
|
|
41
43
|
data,
|
|
42
44
|
this.signature,
|
|
@@ -61,7 +63,6 @@ export class KBJwt<
|
|
|
61
63
|
header,
|
|
62
64
|
payload,
|
|
63
65
|
signature,
|
|
64
|
-
encoded: encodedJwt,
|
|
65
66
|
});
|
|
66
67
|
|
|
67
68
|
return jwt;
|
package/src/test/index.spec.ts
CHANGED
|
@@ -2,15 +2,9 @@ import { SDJwtInstance, type SdJwtPayload } from '../index';
|
|
|
2
2
|
import type { Signer, Verifier, KbVerifier, JwtPayload } from '@sd-jwt/types';
|
|
3
3
|
import Crypto, { type KeyLike } from 'node:crypto';
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
5
|
-
import { digest, generateSalt
|
|
5
|
+
import { digest, generateSalt } from '@sd-jwt/crypto-nodejs';
|
|
6
6
|
import { importJWK, exportJWK, type JWK } from 'jose';
|
|
7
7
|
|
|
8
|
-
// Extract the major version as a number
|
|
9
|
-
const nodeVersionMajor = Number.parseInt(
|
|
10
|
-
process.version.split('.')[0].substring(1),
|
|
11
|
-
10,
|
|
12
|
-
);
|
|
13
|
-
|
|
14
8
|
export const createSignerVerifier = () => {
|
|
15
9
|
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
16
10
|
const signer: Signer = async (data: string) => {
|
|
@@ -596,33 +590,4 @@ describe('index', () => {
|
|
|
596
590
|
expect(decoded.disclosures).toBeDefined();
|
|
597
591
|
expect(decoded.kbJwt).toBeDefined();
|
|
598
592
|
});
|
|
599
|
-
|
|
600
|
-
(nodeVersionMajor < 20 ? test.skip : test)(
|
|
601
|
-
'validate sd-jwt that created in other implemenation',
|
|
602
|
-
async () => {
|
|
603
|
-
const publicKeyExampleJwt: JsonWebKey = {
|
|
604
|
-
kty: 'EC',
|
|
605
|
-
crv: 'P-256',
|
|
606
|
-
x: 'b28d4MwZMjw8-00CG4xfnn9SLMVMM19SlqZpVb_uNtQ',
|
|
607
|
-
y: 'Xv5zWwuoaTgdS6hV43yI6gBwTnjukmFQQnJ_kCxzqk8',
|
|
608
|
-
};
|
|
609
|
-
const kbPubkey: JsonWebKey = {
|
|
610
|
-
kty: 'EC',
|
|
611
|
-
crv: 'P-256',
|
|
612
|
-
x: 'TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc',
|
|
613
|
-
y: 'ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ',
|
|
614
|
-
};
|
|
615
|
-
const encodedJwt =
|
|
616
|
-
'eyJhbGciOiAiRVMyNTYiLCAidHlwIjogInZjK3NkLWp3dCIsICJraWQiOiAiZG9jLXNpZ25lci0wNS0yNS0yMDIyIn0.eyJfc2QiOiBbIjA5dktySk1PbHlUV00wc2pwdV9wZE9CVkJRMk0xeTNLaHBINTE1blhrcFkiLCAiMnJzakdiYUMwa3k4bVQwcEpyUGlvV1RxMF9kYXcxc1g3NnBvVWxnQ3diSSIsICJFa084ZGhXMGRIRUpidlVIbEVfVkNldUM5dVJFTE9pZUxaaGg3WGJVVHRBIiwgIklsRHpJS2VpWmREd3BxcEs2WmZieXBoRnZ6NUZnbldhLXNONndxUVhDaXciLCAiSnpZakg0c3ZsaUgwUjNQeUVNZmVadTZKdDY5dTVxZWhabzdGN0VQWWxTRSIsICJQb3JGYnBLdVZ1Nnh5bUphZ3ZrRnNGWEFiUm9jMkpHbEFVQTJCQTRvN2NJIiwgIlRHZjRvTGJnd2Q1SlFhSHlLVlFaVTlVZEdFMHc1cnREc3JaemZVYW9tTG8iLCAiamRyVEU4WWNiWTRFaWZ1Z2loaUFlX0JQZWt4SlFaSUNlaVVRd1k5UXF4SSIsICJqc3U5eVZ1bHdRUWxoRmxNXzNKbHpNYVNGemdsaFFHMERwZmF5UXdMVUs0Il0sICJpc3MiOiAiaHR0cHM6Ly9leGFtcGxlLmNvbS9pc3N1ZXIiLCAiaWF0IjogMTY4MzAwMDAwMCwgImV4cCI6IDE4ODMwMDAwMDAsICJ2Y3QiOiAiaHR0cHM6Ly9jcmVkZW50aWFscy5leGFtcGxlLmNvbS9pZGVudGl0eV9jcmVkZW50aWFsIiwgIl9zZF9hbGciOiAic2hhLTI1NiIsICJjbmYiOiB7Imp3ayI6IHsia3R5IjogIkVDIiwgImNydiI6ICJQLTI1NiIsICJ4IjogIlRDQUVSMTladnUzT0hGNGo0VzR2ZlNWb0hJUDFJTGlsRGxzN3ZDZUdlbWMiLCAieSI6ICJaeGppV1diWk1RR0hWV0tWUTRoYlNJaXJzVmZ1ZWNDRTZ0NGpUOUYySFpRIn19fQ.QXgzrePAdq_WZVGCwDxP-l8h0iyckrHBNidxVqGtKJ0LMzObqgaXUD1cgGEf7d9TexPkBcgQYqjuzlfbeCxxuA~WyJRZ19PNjR6cUF4ZTQxMmExMDhpcm9BIiwgImFkZHJlc3MiLCB7InN0cmVldF9hZGRyZXNzIjogIjEyMyBNYWluIFN0IiwgImxvY2FsaXR5IjogIkFueXRvd24iLCAicmVnaW9uIjogIkFueXN0YXRlIiwgImNvdW50cnkiOiAiVVMifV0~WyI2SWo3dE0tYTVpVlBHYm9TNXRtdlZBIiwgImVtYWlsIiwgImpvaG5kb2VAZXhhbXBsZS5jb20iXQ~WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwgImZhbWlseV9uYW1lIiwgIkRvZSJd~WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3IiwgImdpdmVuX25hbWUiLCAiSm9obiJd~eyJhbGciOiAiRVMyNTYiLCAidHlwIjogImtiK2p3dCJ9.eyJub25jZSI6ICIxMjM0NTY3ODkwIiwgImF1ZCI6ICJodHRwczovL2V4YW1wbGUuY29tL3ZlcmlmaWVyIiwgImlhdCI6IDE3MDk5OTYxODUsICJzZF9oYXNoIjogIjc4cFFEazJOblNEM1dKQm5SN015aWpmeUVqcGJ5a01yRnlpb2ZYSjlsN0kifQ.7k4goAlxM4a3tHnvCBCe70j_I-BCwtzhBRXQNk9cWJnQWxxt2kIqCyzcwzzUc0gTwtbGWVQoeWCiL5K6y3a4VQ';
|
|
617
|
-
|
|
618
|
-
const sdjwt = new SDJwtInstance({
|
|
619
|
-
hasher: digest,
|
|
620
|
-
verifier: await ES256.getVerifier(publicKeyExampleJwt),
|
|
621
|
-
kbVerifier: await ES256.getVerifier(kbPubkey),
|
|
622
|
-
});
|
|
623
|
-
|
|
624
|
-
const decode = await sdjwt.verify(encodedJwt, undefined, true);
|
|
625
|
-
expect(decode).toBeDefined();
|
|
626
|
-
},
|
|
627
|
-
);
|
|
628
593
|
});
|
package/src/test/jwt.spec.ts
CHANGED
|
@@ -138,65 +138,4 @@ describe('JWT', () => {
|
|
|
138
138
|
expect(e).toBeInstanceOf(SDJWTException);
|
|
139
139
|
}
|
|
140
140
|
});
|
|
141
|
-
|
|
142
|
-
test('getUnsignedToken failed', async () => {
|
|
143
|
-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
144
|
-
const testSigner: Signer = async (data: string) => {
|
|
145
|
-
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
146
|
-
return Buffer.from(sig).toString('base64url');
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const jwt = new Jwt({
|
|
150
|
-
header: { alg: 'EdDSA' },
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
await jwt.sign(testSigner);
|
|
155
|
-
} catch (e: unknown) {
|
|
156
|
-
expect(e).toBeInstanceOf(SDJWTException);
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test('wrong encoded field', async () => {
|
|
161
|
-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
162
|
-
const testSigner: Signer = async (data: string) => {
|
|
163
|
-
const sig = Crypto.sign(null, Buffer.from(data), privateKey);
|
|
164
|
-
return Buffer.from(sig).toString('base64url');
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const jwt = new Jwt({
|
|
168
|
-
header: { alg: 'EdDSA' },
|
|
169
|
-
payload: { foo: 'bar' },
|
|
170
|
-
encoded: 'asfasfafaf.dfasfafafasf', // it has to be 3 parts
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
try {
|
|
174
|
-
await jwt.sign(testSigner);
|
|
175
|
-
} catch (e: unknown) {
|
|
176
|
-
expect(e).toBeInstanceOf(SDJWTException);
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
test('verify failed no signature', async () => {
|
|
181
|
-
const { privateKey, publicKey } = Crypto.generateKeyPairSync('ed25519');
|
|
182
|
-
const testVerifier: Verifier = async (data: string, sig: string) => {
|
|
183
|
-
return Crypto.verify(
|
|
184
|
-
null,
|
|
185
|
-
Buffer.from(data),
|
|
186
|
-
publicKey,
|
|
187
|
-
Buffer.from(sig, 'base64url'),
|
|
188
|
-
);
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
const jwt = new Jwt({
|
|
192
|
-
header: { alg: 'EdDSA' },
|
|
193
|
-
payload: { foo: 'bar' },
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
try {
|
|
197
|
-
await jwt.verify(testVerifier);
|
|
198
|
-
} catch (e: unknown) {
|
|
199
|
-
expect(e).toBeInstanceOf(SDJWTException);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
141
|
});
|
package/src/test/sdjwt.spec.ts
CHANGED
|
@@ -376,9 +376,7 @@ describe('SD JWT', () => {
|
|
|
376
376
|
|
|
377
377
|
const credential = sdJwt.encodeSDJwt();
|
|
378
378
|
const decoded = await SDJwt.decodeSDJwt(credential, hasher);
|
|
379
|
-
expect(jwt
|
|
380
|
-
expect(jwt.payload).toEqual(decoded.jwt.payload);
|
|
381
|
-
expect(jwt.signature).toEqual(decoded.jwt.signature);
|
|
379
|
+
expect(jwt).toEqual(decoded.jwt);
|
|
382
380
|
expect(decoded.disclosures).toEqual([]);
|
|
383
381
|
});
|
|
384
382
|
});
|