@sd-jwt/crypto-nodejs 0.17.2-next.0 → 0.17.2-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 +59 -1
- package/dist/index.d.ts +59 -1
- package/dist/index.js +155 -66
- package/dist/index.mjs +149 -65
- package/package.json +2 -2
- package/src/crypto.ts +164 -62
- package/src/test/crypto.spec.ts +21 -19
package/dist/index.d.mts
CHANGED
|
@@ -2,8 +2,66 @@ import * as crypto from 'crypto';
|
|
|
2
2
|
|
|
3
3
|
declare const generateSalt: (length: number) => string;
|
|
4
4
|
declare const digest: (data: string | ArrayBuffer, algorithm?: string) => Uint8Array;
|
|
5
|
+
type GenerateKeyAlgorithm = RsaHashedKeyGenParams | EcKeyGenParams;
|
|
6
|
+
type ImportKeyAlgorithm = AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm;
|
|
7
|
+
type SignAlgorithm = AlgorithmIdentifier | RsaPssParams | EcdsaParams;
|
|
8
|
+
type VerifyAlgorithm = AlgorithmIdentifier | RsaPssParams | EcdsaParams;
|
|
9
|
+
declare function generateKeyPair(keyAlgorithm: GenerateKeyAlgorithm): Promise<{
|
|
10
|
+
publicKey: crypto.webcrypto.JsonWebKey;
|
|
11
|
+
privateKey: crypto.webcrypto.JsonWebKey;
|
|
12
|
+
}>;
|
|
13
|
+
declare function getSigner(privateKeyJWK: object, keyAlgorithm: ImportKeyAlgorithm, signAlgorithm: SignAlgorithm): Promise<(data: string) => Promise<string>>;
|
|
14
|
+
declare function getVerifier(publicKeyJWK: object, keyAlgorithm: ImportKeyAlgorithm, verifyAlgorithm: VerifyAlgorithm): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
5
15
|
declare const ES256: {
|
|
6
16
|
alg: string;
|
|
17
|
+
_keyAlgorithm: {
|
|
18
|
+
name: string;
|
|
19
|
+
namedCurve: string;
|
|
20
|
+
};
|
|
21
|
+
_hashAlgorithm: {
|
|
22
|
+
name: string;
|
|
23
|
+
hash: {
|
|
24
|
+
name: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
generateKeyPair(): Promise<{
|
|
28
|
+
publicKey: crypto.webcrypto.JsonWebKey;
|
|
29
|
+
privateKey: crypto.webcrypto.JsonWebKey;
|
|
30
|
+
}>;
|
|
31
|
+
getSigner(privateKeyJWK: object): Promise<(data: string) => Promise<string>>;
|
|
32
|
+
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
33
|
+
};
|
|
34
|
+
declare const ES384: {
|
|
35
|
+
alg: string;
|
|
36
|
+
_keyAlgorithm: {
|
|
37
|
+
name: string;
|
|
38
|
+
namedCurve: string;
|
|
39
|
+
};
|
|
40
|
+
_hashAlgorithm: {
|
|
41
|
+
name: string;
|
|
42
|
+
hash: {
|
|
43
|
+
name: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
generateKeyPair(): Promise<{
|
|
47
|
+
publicKey: crypto.webcrypto.JsonWebKey;
|
|
48
|
+
privateKey: crypto.webcrypto.JsonWebKey;
|
|
49
|
+
}>;
|
|
50
|
+
getSigner(privateKeyJWK: object): Promise<(data: string) => Promise<string>>;
|
|
51
|
+
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
52
|
+
};
|
|
53
|
+
declare const ES512: {
|
|
54
|
+
alg: string;
|
|
55
|
+
_keyAlgorithm: {
|
|
56
|
+
name: string;
|
|
57
|
+
namedCurve: string;
|
|
58
|
+
};
|
|
59
|
+
_hashAlgorithm: {
|
|
60
|
+
name: string;
|
|
61
|
+
hash: {
|
|
62
|
+
name: string;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
7
65
|
generateKeyPair(): Promise<{
|
|
8
66
|
publicKey: crypto.webcrypto.JsonWebKey;
|
|
9
67
|
privateKey: crypto.webcrypto.JsonWebKey;
|
|
@@ -12,4 +70,4 @@ declare const ES256: {
|
|
|
12
70
|
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
13
71
|
};
|
|
14
72
|
|
|
15
|
-
export { ES256, digest, generateSalt };
|
|
73
|
+
export { ES256, ES384, ES512, digest, generateKeyPair, generateSalt, getSigner, getVerifier };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,66 @@ import * as crypto from 'crypto';
|
|
|
2
2
|
|
|
3
3
|
declare const generateSalt: (length: number) => string;
|
|
4
4
|
declare const digest: (data: string | ArrayBuffer, algorithm?: string) => Uint8Array;
|
|
5
|
+
type GenerateKeyAlgorithm = RsaHashedKeyGenParams | EcKeyGenParams;
|
|
6
|
+
type ImportKeyAlgorithm = AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm;
|
|
7
|
+
type SignAlgorithm = AlgorithmIdentifier | RsaPssParams | EcdsaParams;
|
|
8
|
+
type VerifyAlgorithm = AlgorithmIdentifier | RsaPssParams | EcdsaParams;
|
|
9
|
+
declare function generateKeyPair(keyAlgorithm: GenerateKeyAlgorithm): Promise<{
|
|
10
|
+
publicKey: crypto.webcrypto.JsonWebKey;
|
|
11
|
+
privateKey: crypto.webcrypto.JsonWebKey;
|
|
12
|
+
}>;
|
|
13
|
+
declare function getSigner(privateKeyJWK: object, keyAlgorithm: ImportKeyAlgorithm, signAlgorithm: SignAlgorithm): Promise<(data: string) => Promise<string>>;
|
|
14
|
+
declare function getVerifier(publicKeyJWK: object, keyAlgorithm: ImportKeyAlgorithm, verifyAlgorithm: VerifyAlgorithm): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
5
15
|
declare const ES256: {
|
|
6
16
|
alg: string;
|
|
17
|
+
_keyAlgorithm: {
|
|
18
|
+
name: string;
|
|
19
|
+
namedCurve: string;
|
|
20
|
+
};
|
|
21
|
+
_hashAlgorithm: {
|
|
22
|
+
name: string;
|
|
23
|
+
hash: {
|
|
24
|
+
name: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
generateKeyPair(): Promise<{
|
|
28
|
+
publicKey: crypto.webcrypto.JsonWebKey;
|
|
29
|
+
privateKey: crypto.webcrypto.JsonWebKey;
|
|
30
|
+
}>;
|
|
31
|
+
getSigner(privateKeyJWK: object): Promise<(data: string) => Promise<string>>;
|
|
32
|
+
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
33
|
+
};
|
|
34
|
+
declare const ES384: {
|
|
35
|
+
alg: string;
|
|
36
|
+
_keyAlgorithm: {
|
|
37
|
+
name: string;
|
|
38
|
+
namedCurve: string;
|
|
39
|
+
};
|
|
40
|
+
_hashAlgorithm: {
|
|
41
|
+
name: string;
|
|
42
|
+
hash: {
|
|
43
|
+
name: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
generateKeyPair(): Promise<{
|
|
47
|
+
publicKey: crypto.webcrypto.JsonWebKey;
|
|
48
|
+
privateKey: crypto.webcrypto.JsonWebKey;
|
|
49
|
+
}>;
|
|
50
|
+
getSigner(privateKeyJWK: object): Promise<(data: string) => Promise<string>>;
|
|
51
|
+
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
52
|
+
};
|
|
53
|
+
declare const ES512: {
|
|
54
|
+
alg: string;
|
|
55
|
+
_keyAlgorithm: {
|
|
56
|
+
name: string;
|
|
57
|
+
namedCurve: string;
|
|
58
|
+
};
|
|
59
|
+
_hashAlgorithm: {
|
|
60
|
+
name: string;
|
|
61
|
+
hash: {
|
|
62
|
+
name: string;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
7
65
|
generateKeyPair(): Promise<{
|
|
8
66
|
publicKey: crypto.webcrypto.JsonWebKey;
|
|
9
67
|
privateKey: crypto.webcrypto.JsonWebKey;
|
|
@@ -12,4 +70,4 @@ declare const ES256: {
|
|
|
12
70
|
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
13
71
|
};
|
|
14
72
|
|
|
15
|
-
export { ES256, digest, generateSalt };
|
|
73
|
+
export { ES256, ES384, ES512, digest, generateKeyPair, generateSalt, getSigner, getVerifier };
|
package/dist/index.js
CHANGED
|
@@ -41,8 +41,13 @@ var __async = (__this, __arguments, generator) => {
|
|
|
41
41
|
var index_exports = {};
|
|
42
42
|
__export(index_exports, {
|
|
43
43
|
ES256: () => ES256,
|
|
44
|
+
ES384: () => ES384,
|
|
45
|
+
ES512: () => ES512,
|
|
44
46
|
digest: () => digest,
|
|
45
|
-
|
|
47
|
+
generateKeyPair: () => generateKeyPair,
|
|
48
|
+
generateSalt: () => generateSalt,
|
|
49
|
+
getSigner: () => getSigner,
|
|
50
|
+
getVerifier: () => getVerifier
|
|
46
51
|
});
|
|
47
52
|
module.exports = __toCommonJS(index_exports);
|
|
48
53
|
|
|
@@ -68,93 +73,177 @@ var digest = (data, algorithm = "sha-256") => {
|
|
|
68
73
|
return new Uint8Array(hashBuffer);
|
|
69
74
|
};
|
|
70
75
|
var toNodeCryptoAlg = (hashAlg) => hashAlg.replace("-", "").toLowerCase();
|
|
76
|
+
function generateKeyPair(keyAlgorithm) {
|
|
77
|
+
return __async(this, null, function* () {
|
|
78
|
+
const keyPair = yield import_node_crypto.subtle.generateKey(
|
|
79
|
+
keyAlgorithm,
|
|
80
|
+
true,
|
|
81
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
82
|
+
["sign", "verify"]
|
|
83
|
+
// can be used to sign and verify signatures
|
|
84
|
+
);
|
|
85
|
+
const publicKeyJWK = yield import_node_crypto.subtle.exportKey("jwk", keyPair.publicKey);
|
|
86
|
+
const privateKeyJWK = yield import_node_crypto.subtle.exportKey("jwk", keyPair.privateKey);
|
|
87
|
+
return { publicKey: publicKeyJWK, privateKey: privateKeyJWK };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function getSigner(privateKeyJWK, keyAlgorithm, signAlgorithm) {
|
|
91
|
+
return __async(this, null, function* () {
|
|
92
|
+
const privateKey = yield import_node_crypto.subtle.importKey(
|
|
93
|
+
"jwk",
|
|
94
|
+
privateKeyJWK,
|
|
95
|
+
keyAlgorithm,
|
|
96
|
+
true,
|
|
97
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
98
|
+
["sign"]
|
|
99
|
+
);
|
|
100
|
+
return (data) => __async(null, null, function* () {
|
|
101
|
+
const encoder = new TextEncoder();
|
|
102
|
+
const signature = yield import_node_crypto.subtle.sign(
|
|
103
|
+
signAlgorithm,
|
|
104
|
+
privateKey,
|
|
105
|
+
encoder.encode(data)
|
|
106
|
+
);
|
|
107
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function getVerifier(publicKeyJWK, keyAlgorithm, verifyAlgorithm) {
|
|
112
|
+
return __async(this, null, function* () {
|
|
113
|
+
const publicKey = yield import_node_crypto.subtle.importKey(
|
|
114
|
+
"jwk",
|
|
115
|
+
publicKeyJWK,
|
|
116
|
+
keyAlgorithm,
|
|
117
|
+
true,
|
|
118
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
119
|
+
["verify"]
|
|
120
|
+
);
|
|
121
|
+
return (data, signatureBase64url) => __async(null, null, function* () {
|
|
122
|
+
const encoder = new TextEncoder();
|
|
123
|
+
const signature = Uint8Array.from(
|
|
124
|
+
atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
|
|
125
|
+
(c) => c.charCodeAt(0)
|
|
126
|
+
);
|
|
127
|
+
const isValid = yield import_node_crypto.subtle.verify(
|
|
128
|
+
verifyAlgorithm,
|
|
129
|
+
publicKey,
|
|
130
|
+
signature,
|
|
131
|
+
encoder.encode(data)
|
|
132
|
+
);
|
|
133
|
+
return isValid;
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
71
137
|
var ES256 = {
|
|
72
138
|
alg: "ES256",
|
|
139
|
+
_keyAlgorithm: {
|
|
140
|
+
name: "ECDSA",
|
|
141
|
+
namedCurve: "P-256"
|
|
142
|
+
},
|
|
143
|
+
_hashAlgorithm: {
|
|
144
|
+
name: "ECDSA",
|
|
145
|
+
hash: { name: "sha-256" }
|
|
146
|
+
},
|
|
73
147
|
generateKeyPair() {
|
|
74
148
|
return __async(this, null, function* () {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
149
|
+
return yield generateKeyPair(ES256._keyAlgorithm);
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
getSigner(privateKeyJWK) {
|
|
153
|
+
return __async(this, null, function* () {
|
|
154
|
+
return yield getSigner(
|
|
155
|
+
privateKeyJWK,
|
|
156
|
+
ES256._keyAlgorithm,
|
|
157
|
+
ES256._hashAlgorithm
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
},
|
|
161
|
+
getVerifier(publicKeyJWK) {
|
|
162
|
+
return __async(this, null, function* () {
|
|
163
|
+
return yield getVerifier(
|
|
164
|
+
publicKeyJWK,
|
|
165
|
+
ES256._keyAlgorithm,
|
|
166
|
+
ES256._hashAlgorithm
|
|
85
167
|
);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
var ES384 = {
|
|
172
|
+
alg: "ES384",
|
|
173
|
+
_keyAlgorithm: {
|
|
174
|
+
name: "ECDSA",
|
|
175
|
+
namedCurve: "P-384"
|
|
176
|
+
},
|
|
177
|
+
_hashAlgorithm: {
|
|
178
|
+
name: "ECDSA",
|
|
179
|
+
hash: { name: "sha-384" }
|
|
180
|
+
},
|
|
181
|
+
generateKeyPair() {
|
|
182
|
+
return __async(this, null, function* () {
|
|
183
|
+
return yield generateKeyPair(ES384._keyAlgorithm);
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
getSigner(privateKeyJWK) {
|
|
187
|
+
return __async(this, null, function* () {
|
|
188
|
+
return yield getSigner(
|
|
189
|
+
privateKeyJWK,
|
|
190
|
+
ES384._keyAlgorithm,
|
|
191
|
+
ES384._hashAlgorithm
|
|
192
|
+
);
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
getVerifier(publicKeyJWK) {
|
|
196
|
+
return __async(this, null, function* () {
|
|
197
|
+
return yield getVerifier(
|
|
198
|
+
publicKeyJWK,
|
|
199
|
+
ES384._keyAlgorithm,
|
|
200
|
+
ES384._hashAlgorithm
|
|
201
|
+
);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
var ES512 = {
|
|
206
|
+
alg: "ES512",
|
|
207
|
+
_keyAlgorithm: {
|
|
208
|
+
name: "ECDSA",
|
|
209
|
+
namedCurve: "P-521"
|
|
210
|
+
},
|
|
211
|
+
_hashAlgorithm: {
|
|
212
|
+
name: "ECDSA",
|
|
213
|
+
hash: { name: "sha-512" }
|
|
214
|
+
},
|
|
215
|
+
generateKeyPair() {
|
|
216
|
+
return __async(this, null, function* () {
|
|
217
|
+
return yield generateKeyPair(ES512._keyAlgorithm);
|
|
89
218
|
});
|
|
90
219
|
},
|
|
91
220
|
getSigner(privateKeyJWK) {
|
|
92
221
|
return __async(this, null, function* () {
|
|
93
|
-
|
|
94
|
-
"jwk",
|
|
222
|
+
return yield getSigner(
|
|
95
223
|
privateKeyJWK,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
namedCurve: "P-256"
|
|
99
|
-
// Must match the curve used to generate the key
|
|
100
|
-
},
|
|
101
|
-
true,
|
|
102
|
-
// whether the key is extractable (i.e., can be used in exportKey)
|
|
103
|
-
["sign"]
|
|
224
|
+
ES512._keyAlgorithm,
|
|
225
|
+
ES512._hashAlgorithm
|
|
104
226
|
);
|
|
105
|
-
return (data) => __async(null, null, function* () {
|
|
106
|
-
const encoder = new TextEncoder();
|
|
107
|
-
const signature = yield import_node_crypto.subtle.sign(
|
|
108
|
-
{
|
|
109
|
-
name: "ECDSA",
|
|
110
|
-
hash: { name: "sha-256" }
|
|
111
|
-
// Required for ES256
|
|
112
|
-
},
|
|
113
|
-
privateKey,
|
|
114
|
-
encoder.encode(data)
|
|
115
|
-
);
|
|
116
|
-
return btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
117
|
-
});
|
|
118
227
|
});
|
|
119
228
|
},
|
|
120
229
|
getVerifier(publicKeyJWK) {
|
|
121
230
|
return __async(this, null, function* () {
|
|
122
|
-
|
|
123
|
-
"jwk",
|
|
231
|
+
return yield getVerifier(
|
|
124
232
|
publicKeyJWK,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
namedCurve: "P-256"
|
|
128
|
-
// Must match the curve used to generate the key
|
|
129
|
-
},
|
|
130
|
-
true,
|
|
131
|
-
// whether the key is extractable (i.e., can be used in exportKey)
|
|
132
|
-
["verify"]
|
|
233
|
+
ES512._keyAlgorithm,
|
|
234
|
+
ES512._hashAlgorithm
|
|
133
235
|
);
|
|
134
|
-
return (data, signatureBase64url) => __async(null, null, function* () {
|
|
135
|
-
const encoder = new TextEncoder();
|
|
136
|
-
const signature = Uint8Array.from(
|
|
137
|
-
atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
|
|
138
|
-
(c) => c.charCodeAt(0)
|
|
139
|
-
);
|
|
140
|
-
const isValid = yield import_node_crypto.subtle.verify(
|
|
141
|
-
{
|
|
142
|
-
name: "ECDSA",
|
|
143
|
-
hash: { name: "sha-256" }
|
|
144
|
-
// Required for ES256
|
|
145
|
-
},
|
|
146
|
-
publicKey,
|
|
147
|
-
signature,
|
|
148
|
-
encoder.encode(data)
|
|
149
|
-
);
|
|
150
|
-
return isValid;
|
|
151
|
-
});
|
|
152
236
|
});
|
|
153
237
|
}
|
|
154
238
|
};
|
|
155
239
|
// Annotate the CommonJS export names for ESM import in node:
|
|
156
240
|
0 && (module.exports = {
|
|
157
241
|
ES256,
|
|
242
|
+
ES384,
|
|
243
|
+
ES512,
|
|
158
244
|
digest,
|
|
159
|
-
|
|
245
|
+
generateKeyPair,
|
|
246
|
+
generateSalt,
|
|
247
|
+
getSigner,
|
|
248
|
+
getVerifier
|
|
160
249
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -41,92 +41,176 @@ var digest = (data, algorithm = "sha-256") => {
|
|
|
41
41
|
return new Uint8Array(hashBuffer);
|
|
42
42
|
};
|
|
43
43
|
var toNodeCryptoAlg = (hashAlg) => hashAlg.replace("-", "").toLowerCase();
|
|
44
|
+
function generateKeyPair(keyAlgorithm) {
|
|
45
|
+
return __async(this, null, function* () {
|
|
46
|
+
const keyPair = yield subtle.generateKey(
|
|
47
|
+
keyAlgorithm,
|
|
48
|
+
true,
|
|
49
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
50
|
+
["sign", "verify"]
|
|
51
|
+
// can be used to sign and verify signatures
|
|
52
|
+
);
|
|
53
|
+
const publicKeyJWK = yield subtle.exportKey("jwk", keyPair.publicKey);
|
|
54
|
+
const privateKeyJWK = yield subtle.exportKey("jwk", keyPair.privateKey);
|
|
55
|
+
return { publicKey: publicKeyJWK, privateKey: privateKeyJWK };
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function getSigner(privateKeyJWK, keyAlgorithm, signAlgorithm) {
|
|
59
|
+
return __async(this, null, function* () {
|
|
60
|
+
const privateKey = yield subtle.importKey(
|
|
61
|
+
"jwk",
|
|
62
|
+
privateKeyJWK,
|
|
63
|
+
keyAlgorithm,
|
|
64
|
+
true,
|
|
65
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
66
|
+
["sign"]
|
|
67
|
+
);
|
|
68
|
+
return (data) => __async(null, null, function* () {
|
|
69
|
+
const encoder = new TextEncoder();
|
|
70
|
+
const signature = yield subtle.sign(
|
|
71
|
+
signAlgorithm,
|
|
72
|
+
privateKey,
|
|
73
|
+
encoder.encode(data)
|
|
74
|
+
);
|
|
75
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function getVerifier(publicKeyJWK, keyAlgorithm, verifyAlgorithm) {
|
|
80
|
+
return __async(this, null, function* () {
|
|
81
|
+
const publicKey = yield subtle.importKey(
|
|
82
|
+
"jwk",
|
|
83
|
+
publicKeyJWK,
|
|
84
|
+
keyAlgorithm,
|
|
85
|
+
true,
|
|
86
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
87
|
+
["verify"]
|
|
88
|
+
);
|
|
89
|
+
return (data, signatureBase64url) => __async(null, null, function* () {
|
|
90
|
+
const encoder = new TextEncoder();
|
|
91
|
+
const signature = Uint8Array.from(
|
|
92
|
+
atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
|
|
93
|
+
(c) => c.charCodeAt(0)
|
|
94
|
+
);
|
|
95
|
+
const isValid = yield subtle.verify(
|
|
96
|
+
verifyAlgorithm,
|
|
97
|
+
publicKey,
|
|
98
|
+
signature,
|
|
99
|
+
encoder.encode(data)
|
|
100
|
+
);
|
|
101
|
+
return isValid;
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
44
105
|
var ES256 = {
|
|
45
106
|
alg: "ES256",
|
|
107
|
+
_keyAlgorithm: {
|
|
108
|
+
name: "ECDSA",
|
|
109
|
+
namedCurve: "P-256"
|
|
110
|
+
},
|
|
111
|
+
_hashAlgorithm: {
|
|
112
|
+
name: "ECDSA",
|
|
113
|
+
hash: { name: "sha-256" }
|
|
114
|
+
},
|
|
46
115
|
generateKeyPair() {
|
|
47
116
|
return __async(this, null, function* () {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
117
|
+
return yield generateKeyPair(ES256._keyAlgorithm);
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
getSigner(privateKeyJWK) {
|
|
121
|
+
return __async(this, null, function* () {
|
|
122
|
+
return yield getSigner(
|
|
123
|
+
privateKeyJWK,
|
|
124
|
+
ES256._keyAlgorithm,
|
|
125
|
+
ES256._hashAlgorithm
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
getVerifier(publicKeyJWK) {
|
|
130
|
+
return __async(this, null, function* () {
|
|
131
|
+
return yield getVerifier(
|
|
132
|
+
publicKeyJWK,
|
|
133
|
+
ES256._keyAlgorithm,
|
|
134
|
+
ES256._hashAlgorithm
|
|
58
135
|
);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
var ES384 = {
|
|
140
|
+
alg: "ES384",
|
|
141
|
+
_keyAlgorithm: {
|
|
142
|
+
name: "ECDSA",
|
|
143
|
+
namedCurve: "P-384"
|
|
144
|
+
},
|
|
145
|
+
_hashAlgorithm: {
|
|
146
|
+
name: "ECDSA",
|
|
147
|
+
hash: { name: "sha-384" }
|
|
148
|
+
},
|
|
149
|
+
generateKeyPair() {
|
|
150
|
+
return __async(this, null, function* () {
|
|
151
|
+
return yield generateKeyPair(ES384._keyAlgorithm);
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
getSigner(privateKeyJWK) {
|
|
155
|
+
return __async(this, null, function* () {
|
|
156
|
+
return yield getSigner(
|
|
157
|
+
privateKeyJWK,
|
|
158
|
+
ES384._keyAlgorithm,
|
|
159
|
+
ES384._hashAlgorithm
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
getVerifier(publicKeyJWK) {
|
|
164
|
+
return __async(this, null, function* () {
|
|
165
|
+
return yield getVerifier(
|
|
166
|
+
publicKeyJWK,
|
|
167
|
+
ES384._keyAlgorithm,
|
|
168
|
+
ES384._hashAlgorithm
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
var ES512 = {
|
|
174
|
+
alg: "ES512",
|
|
175
|
+
_keyAlgorithm: {
|
|
176
|
+
name: "ECDSA",
|
|
177
|
+
namedCurve: "P-521"
|
|
178
|
+
},
|
|
179
|
+
_hashAlgorithm: {
|
|
180
|
+
name: "ECDSA",
|
|
181
|
+
hash: { name: "sha-512" }
|
|
182
|
+
},
|
|
183
|
+
generateKeyPair() {
|
|
184
|
+
return __async(this, null, function* () {
|
|
185
|
+
return yield generateKeyPair(ES512._keyAlgorithm);
|
|
62
186
|
});
|
|
63
187
|
},
|
|
64
188
|
getSigner(privateKeyJWK) {
|
|
65
189
|
return __async(this, null, function* () {
|
|
66
|
-
|
|
67
|
-
"jwk",
|
|
190
|
+
return yield getSigner(
|
|
68
191
|
privateKeyJWK,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
namedCurve: "P-256"
|
|
72
|
-
// Must match the curve used to generate the key
|
|
73
|
-
},
|
|
74
|
-
true,
|
|
75
|
-
// whether the key is extractable (i.e., can be used in exportKey)
|
|
76
|
-
["sign"]
|
|
192
|
+
ES512._keyAlgorithm,
|
|
193
|
+
ES512._hashAlgorithm
|
|
77
194
|
);
|
|
78
|
-
return (data) => __async(null, null, function* () {
|
|
79
|
-
const encoder = new TextEncoder();
|
|
80
|
-
const signature = yield subtle.sign(
|
|
81
|
-
{
|
|
82
|
-
name: "ECDSA",
|
|
83
|
-
hash: { name: "sha-256" }
|
|
84
|
-
// Required for ES256
|
|
85
|
-
},
|
|
86
|
-
privateKey,
|
|
87
|
-
encoder.encode(data)
|
|
88
|
-
);
|
|
89
|
-
return btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
90
|
-
});
|
|
91
195
|
});
|
|
92
196
|
},
|
|
93
197
|
getVerifier(publicKeyJWK) {
|
|
94
198
|
return __async(this, null, function* () {
|
|
95
|
-
|
|
96
|
-
"jwk",
|
|
199
|
+
return yield getVerifier(
|
|
97
200
|
publicKeyJWK,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
namedCurve: "P-256"
|
|
101
|
-
// Must match the curve used to generate the key
|
|
102
|
-
},
|
|
103
|
-
true,
|
|
104
|
-
// whether the key is extractable (i.e., can be used in exportKey)
|
|
105
|
-
["verify"]
|
|
201
|
+
ES512._keyAlgorithm,
|
|
202
|
+
ES512._hashAlgorithm
|
|
106
203
|
);
|
|
107
|
-
return (data, signatureBase64url) => __async(null, null, function* () {
|
|
108
|
-
const encoder = new TextEncoder();
|
|
109
|
-
const signature = Uint8Array.from(
|
|
110
|
-
atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
|
|
111
|
-
(c) => c.charCodeAt(0)
|
|
112
|
-
);
|
|
113
|
-
const isValid = yield subtle.verify(
|
|
114
|
-
{
|
|
115
|
-
name: "ECDSA",
|
|
116
|
-
hash: { name: "sha-256" }
|
|
117
|
-
// Required for ES256
|
|
118
|
-
},
|
|
119
|
-
publicKey,
|
|
120
|
-
signature,
|
|
121
|
-
encoder.encode(data)
|
|
122
|
-
);
|
|
123
|
-
return isValid;
|
|
124
|
-
});
|
|
125
204
|
});
|
|
126
205
|
}
|
|
127
206
|
};
|
|
128
207
|
export {
|
|
129
208
|
ES256,
|
|
209
|
+
ES384,
|
|
210
|
+
ES512,
|
|
130
211
|
digest,
|
|
131
|
-
|
|
212
|
+
generateKeyPair,
|
|
213
|
+
generateSalt,
|
|
214
|
+
getSigner,
|
|
215
|
+
getVerifier
|
|
132
216
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/crypto-nodejs",
|
|
3
|
-
"version": "0.17.2-next.
|
|
3
|
+
"version": "0.17.2-next.2+4a4c1b0",
|
|
4
4
|
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"esm"
|
|
52
52
|
]
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "4a4c1b0c04615bcf0e455d51cd1b9234cbcd0d78"
|
|
55
55
|
}
|
package/src/crypto.ts
CHANGED
|
@@ -27,85 +27,187 @@ export const digest = (
|
|
|
27
27
|
const toNodeCryptoAlg = (hashAlg: string): string =>
|
|
28
28
|
hashAlg.replace('-', '').toLowerCase();
|
|
29
29
|
|
|
30
|
+
// All derived from the subtle functions being called below
|
|
31
|
+
type GenerateKeyAlgorithm = RsaHashedKeyGenParams | EcKeyGenParams;
|
|
32
|
+
type ImportKeyAlgorithm =
|
|
33
|
+
| AlgorithmIdentifier
|
|
34
|
+
| RsaHashedImportParams
|
|
35
|
+
| EcKeyImportParams
|
|
36
|
+
| HmacImportParams
|
|
37
|
+
| AesKeyAlgorithm;
|
|
38
|
+
type SignAlgorithm = AlgorithmIdentifier | RsaPssParams | EcdsaParams;
|
|
39
|
+
type VerifyAlgorithm = AlgorithmIdentifier | RsaPssParams | EcdsaParams;
|
|
40
|
+
|
|
41
|
+
export async function generateKeyPair(keyAlgorithm: GenerateKeyAlgorithm) {
|
|
42
|
+
const keyPair = await subtle.generateKey(
|
|
43
|
+
keyAlgorithm,
|
|
44
|
+
true, // whether the key is extractable (i.e., can be used in exportKey)
|
|
45
|
+
['sign', 'verify'], // can be used to sign and verify signatures
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Export the public and private keys in JWK format
|
|
49
|
+
const publicKeyJWK = await subtle.exportKey('jwk', keyPair.publicKey);
|
|
50
|
+
const privateKeyJWK = await subtle.exportKey('jwk', keyPair.privateKey);
|
|
51
|
+
|
|
52
|
+
return { publicKey: publicKeyJWK, privateKey: privateKeyJWK };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function getSigner(
|
|
56
|
+
privateKeyJWK: object,
|
|
57
|
+
keyAlgorithm: ImportKeyAlgorithm,
|
|
58
|
+
signAlgorithm: SignAlgorithm,
|
|
59
|
+
) {
|
|
60
|
+
const privateKey = await subtle.importKey(
|
|
61
|
+
'jwk',
|
|
62
|
+
privateKeyJWK,
|
|
63
|
+
keyAlgorithm,
|
|
64
|
+
true, // whether the key is extractable (i.e., can be used in exportKey)
|
|
65
|
+
['sign'],
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return async (data: string) => {
|
|
69
|
+
const encoder = new TextEncoder();
|
|
70
|
+
const signature = await subtle.sign(
|
|
71
|
+
signAlgorithm,
|
|
72
|
+
privateKey,
|
|
73
|
+
encoder.encode(data),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature)))
|
|
77
|
+
.replace(/\+/g, '-')
|
|
78
|
+
.replace(/\//g, '_')
|
|
79
|
+
.replace(/=+$/, ''); // Convert to base64url format
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function getVerifier(
|
|
84
|
+
publicKeyJWK: object,
|
|
85
|
+
keyAlgorithm: ImportKeyAlgorithm,
|
|
86
|
+
verifyAlgorithm: VerifyAlgorithm,
|
|
87
|
+
) {
|
|
88
|
+
const publicKey = await subtle.importKey(
|
|
89
|
+
'jwk',
|
|
90
|
+
publicKeyJWK,
|
|
91
|
+
keyAlgorithm,
|
|
92
|
+
true, // whether the key is extractable (i.e., can be used in exportKey)
|
|
93
|
+
['verify'],
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
return async (data: string, signatureBase64url: string) => {
|
|
97
|
+
const encoder = new TextEncoder();
|
|
98
|
+
const signature = Uint8Array.from(
|
|
99
|
+
atob(signatureBase64url.replace(/-/g, '+').replace(/_/g, '/')),
|
|
100
|
+
(c) => c.charCodeAt(0),
|
|
101
|
+
);
|
|
102
|
+
const isValid = await subtle.verify(
|
|
103
|
+
verifyAlgorithm,
|
|
104
|
+
publicKey,
|
|
105
|
+
signature,
|
|
106
|
+
encoder.encode(data),
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
return isValid;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
30
113
|
export const ES256 = {
|
|
31
114
|
alg: 'ES256',
|
|
32
115
|
|
|
116
|
+
_keyAlgorithm: {
|
|
117
|
+
name: 'ECDSA',
|
|
118
|
+
namedCurve: 'P-256',
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
_hashAlgorithm: {
|
|
122
|
+
name: 'ECDSA',
|
|
123
|
+
hash: { name: 'sha-256' },
|
|
124
|
+
},
|
|
125
|
+
|
|
33
126
|
async generateKeyPair() {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
127
|
+
return await generateKeyPair(ES256._keyAlgorithm);
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
async getSigner(privateKeyJWK: object) {
|
|
131
|
+
return await getSigner(
|
|
132
|
+
privateKeyJWK,
|
|
133
|
+
ES256._keyAlgorithm,
|
|
134
|
+
ES256._hashAlgorithm,
|
|
135
|
+
);
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
async getVerifier(publicKeyJWK: object) {
|
|
139
|
+
return await getVerifier(
|
|
140
|
+
publicKeyJWK,
|
|
141
|
+
ES256._keyAlgorithm,
|
|
142
|
+
ES256._hashAlgorithm,
|
|
41
143
|
);
|
|
144
|
+
},
|
|
145
|
+
};
|
|
42
146
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
147
|
+
export const ES384 = {
|
|
148
|
+
alg: 'ES384',
|
|
149
|
+
|
|
150
|
+
_keyAlgorithm: {
|
|
151
|
+
name: 'ECDSA',
|
|
152
|
+
namedCurve: 'P-384',
|
|
153
|
+
},
|
|
46
154
|
|
|
47
|
-
|
|
155
|
+
_hashAlgorithm: {
|
|
156
|
+
name: 'ECDSA',
|
|
157
|
+
hash: { name: 'sha-384' },
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
async generateKeyPair() {
|
|
161
|
+
return await generateKeyPair(ES384._keyAlgorithm);
|
|
48
162
|
},
|
|
49
163
|
|
|
50
164
|
async getSigner(privateKeyJWK: object) {
|
|
51
|
-
|
|
52
|
-
'jwk',
|
|
165
|
+
return await getSigner(
|
|
53
166
|
privateKeyJWK,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
namedCurve: 'P-256', // Must match the curve used to generate the key
|
|
57
|
-
},
|
|
58
|
-
true, // whether the key is extractable (i.e., can be used in exportKey)
|
|
59
|
-
['sign'],
|
|
167
|
+
ES384._keyAlgorithm,
|
|
168
|
+
ES384._hashAlgorithm,
|
|
60
169
|
);
|
|
61
|
-
|
|
62
|
-
return async (data: string) => {
|
|
63
|
-
const encoder = new TextEncoder();
|
|
64
|
-
const signature = await subtle.sign(
|
|
65
|
-
{
|
|
66
|
-
name: 'ECDSA',
|
|
67
|
-
hash: { name: 'sha-256' }, // Required for ES256
|
|
68
|
-
},
|
|
69
|
-
privateKey,
|
|
70
|
-
encoder.encode(data),
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
return btoa(String.fromCharCode(...new Uint8Array(signature)))
|
|
74
|
-
.replace(/\+/g, '-')
|
|
75
|
-
.replace(/\//g, '_')
|
|
76
|
-
.replace(/=+$/, ''); // Convert to base64url format
|
|
77
|
-
};
|
|
78
170
|
},
|
|
79
171
|
|
|
80
172
|
async getVerifier(publicKeyJWK: object) {
|
|
81
|
-
|
|
82
|
-
'jwk',
|
|
173
|
+
return await getVerifier(
|
|
83
174
|
publicKeyJWK,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
175
|
+
ES384._keyAlgorithm,
|
|
176
|
+
ES384._hashAlgorithm,
|
|
177
|
+
);
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export const ES512 = {
|
|
182
|
+
alg: 'ES512',
|
|
183
|
+
|
|
184
|
+
_keyAlgorithm: {
|
|
185
|
+
name: 'ECDSA',
|
|
186
|
+
namedCurve: 'P-521',
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
_hashAlgorithm: {
|
|
190
|
+
name: 'ECDSA',
|
|
191
|
+
hash: { name: 'sha-512' },
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
async generateKeyPair() {
|
|
195
|
+
return await generateKeyPair(ES512._keyAlgorithm);
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
async getSigner(privateKeyJWK: object) {
|
|
199
|
+
return await getSigner(
|
|
200
|
+
privateKeyJWK,
|
|
201
|
+
ES512._keyAlgorithm,
|
|
202
|
+
ES512._hashAlgorithm,
|
|
90
203
|
);
|
|
204
|
+
},
|
|
91
205
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const isValid = await subtle.verify(
|
|
99
|
-
{
|
|
100
|
-
name: 'ECDSA',
|
|
101
|
-
hash: { name: 'sha-256' }, // Required for ES256
|
|
102
|
-
},
|
|
103
|
-
publicKey,
|
|
104
|
-
signature,
|
|
105
|
-
encoder.encode(data),
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
return isValid;
|
|
109
|
-
};
|
|
206
|
+
async getVerifier(publicKeyJWK: object) {
|
|
207
|
+
return await getVerifier(
|
|
208
|
+
publicKeyJWK,
|
|
209
|
+
ES512._keyAlgorithm,
|
|
210
|
+
ES512._hashAlgorithm,
|
|
211
|
+
);
|
|
110
212
|
},
|
|
111
213
|
};
|
package/src/test/crypto.spec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from 'vitest';
|
|
2
|
-
import { digest, ES256, generateSalt } from '../index';
|
|
2
|
+
import { digest, ES256, ES384, ES512, generateSalt } from '../index';
|
|
3
3
|
|
|
4
4
|
// Extract the major version as a number
|
|
5
5
|
const nodeVersionMajor = Number.parseInt(
|
|
@@ -34,22 +34,24 @@ describe('This file is for utility functions', () => {
|
|
|
34
34
|
expect(s1.length).toBe(64);
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
37
|
+
for (const algObj of [ES256, ES384, ES512]) {
|
|
38
|
+
(nodeVersionMajor < 20 ? test.skip : test)(algObj.alg, async () => {
|
|
39
|
+
const { privateKey, publicKey } = await algObj.generateKeyPair();
|
|
40
|
+
expect(privateKey).toBeDefined();
|
|
41
|
+
expect(publicKey).toBeDefined();
|
|
42
|
+
expect(typeof privateKey).toBe('object');
|
|
43
|
+
expect(typeof publicKey).toBe('object');
|
|
44
|
+
|
|
45
|
+
const data =
|
|
46
|
+
'In cryptography, a salt is random data that is used as an additional input to a one-way function that hashes data, a password or passphrase.';
|
|
47
|
+
const signer = await algObj.getSigner(privateKey);
|
|
48
|
+
const signature = await signer(data);
|
|
49
|
+
expect(signature).toBeDefined();
|
|
50
|
+
expect(typeof signature).toBe('string');
|
|
51
|
+
|
|
52
|
+
const verifier = await algObj.getVerifier(publicKey);
|
|
53
|
+
const result = await verifier(data, signature);
|
|
54
|
+
expect(result).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
55
57
|
});
|