@sd-jwt/crypto-browser 0.3.2-next.71 → 0.3.2-next.73
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 +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +92 -0
- package/dist/index.mjs +91 -0
- package/package.json +2 -2
- package/src/crypto.ts +90 -0
- package/src/test/crypto.spec.ts +23 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
declare const generateSalt: (length: number) => string;
|
|
2
2
|
declare function digest(data: string, algorithm?: string): Promise<Uint8Array>;
|
|
3
3
|
declare const getHasher: (algorithm?: string) => (data: string) => Promise<Uint8Array>;
|
|
4
|
+
declare const ES256: {
|
|
5
|
+
alg: string;
|
|
6
|
+
generateKeyPair(): Promise<{
|
|
7
|
+
publicKey: JsonWebKey;
|
|
8
|
+
privateKey: JsonWebKey;
|
|
9
|
+
}>;
|
|
10
|
+
getSigner(privateKeyJWK: object): Promise<(data: string) => Promise<string>>;
|
|
11
|
+
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
12
|
+
};
|
|
4
13
|
|
|
5
|
-
export { digest, generateSalt, getHasher };
|
|
14
|
+
export { ES256, digest, generateSalt, getHasher };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
declare const generateSalt: (length: number) => string;
|
|
2
2
|
declare function digest(data: string, algorithm?: string): Promise<Uint8Array>;
|
|
3
3
|
declare const getHasher: (algorithm?: string) => (data: string) => Promise<Uint8Array>;
|
|
4
|
+
declare const ES256: {
|
|
5
|
+
alg: string;
|
|
6
|
+
generateKeyPair(): Promise<{
|
|
7
|
+
publicKey: JsonWebKey;
|
|
8
|
+
privateKey: JsonWebKey;
|
|
9
|
+
}>;
|
|
10
|
+
getSigner(privateKeyJWK: object): Promise<(data: string) => Promise<string>>;
|
|
11
|
+
getVerifier(publicKeyJWK: object): Promise<(data: string, signatureBase64url: string) => Promise<boolean>>;
|
|
12
|
+
};
|
|
4
13
|
|
|
5
|
-
export { digest, generateSalt, getHasher };
|
|
14
|
+
export { ES256, digest, generateSalt, getHasher };
|
package/dist/index.js
CHANGED
|
@@ -40,6 +40,7 @@ var __async = (__this, __arguments, generator) => {
|
|
|
40
40
|
// src/index.ts
|
|
41
41
|
var src_exports = {};
|
|
42
42
|
__export(src_exports, {
|
|
43
|
+
ES256: () => ES256,
|
|
43
44
|
digest: () => digest,
|
|
44
45
|
generateSalt: () => generateSalt,
|
|
45
46
|
getHasher: () => getHasher
|
|
@@ -69,8 +70,99 @@ function digest(data, algorithm = "SHA-256") {
|
|
|
69
70
|
var getHasher = (algorithm = "SHA-256") => {
|
|
70
71
|
return (data) => digest(data, algorithm);
|
|
71
72
|
};
|
|
73
|
+
var ES256 = {
|
|
74
|
+
alg: "ES256",
|
|
75
|
+
generateKeyPair() {
|
|
76
|
+
return __async(this, null, function* () {
|
|
77
|
+
const keyPair = yield window.crypto.subtle.generateKey(
|
|
78
|
+
{
|
|
79
|
+
name: "ECDSA",
|
|
80
|
+
namedCurve: "P-256"
|
|
81
|
+
// ES256
|
|
82
|
+
},
|
|
83
|
+
true,
|
|
84
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
85
|
+
["sign", "verify"]
|
|
86
|
+
// can be used to sign and verify signatures
|
|
87
|
+
);
|
|
88
|
+
const publicKeyJWK = yield window.crypto.subtle.exportKey(
|
|
89
|
+
"jwk",
|
|
90
|
+
keyPair.publicKey
|
|
91
|
+
);
|
|
92
|
+
const privateKeyJWK = yield window.crypto.subtle.exportKey(
|
|
93
|
+
"jwk",
|
|
94
|
+
keyPair.privateKey
|
|
95
|
+
);
|
|
96
|
+
return { publicKey: publicKeyJWK, privateKey: privateKeyJWK };
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
getSigner(privateKeyJWK) {
|
|
100
|
+
return __async(this, null, function* () {
|
|
101
|
+
const privateKey = yield window.crypto.subtle.importKey(
|
|
102
|
+
"jwk",
|
|
103
|
+
privateKeyJWK,
|
|
104
|
+
{
|
|
105
|
+
name: "ECDSA",
|
|
106
|
+
namedCurve: "P-256"
|
|
107
|
+
// Must match the curve used to generate the key
|
|
108
|
+
},
|
|
109
|
+
true,
|
|
110
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
111
|
+
["sign"]
|
|
112
|
+
);
|
|
113
|
+
return (data) => __async(this, null, function* () {
|
|
114
|
+
const encoder = new TextEncoder();
|
|
115
|
+
const signature = yield window.crypto.subtle.sign(
|
|
116
|
+
{
|
|
117
|
+
name: "ECDSA",
|
|
118
|
+
hash: { name: "SHA-256" }
|
|
119
|
+
// Required for ES256
|
|
120
|
+
},
|
|
121
|
+
privateKey,
|
|
122
|
+
encoder.encode(data)
|
|
123
|
+
);
|
|
124
|
+
return window.btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
},
|
|
128
|
+
getVerifier(publicKeyJWK) {
|
|
129
|
+
return __async(this, null, function* () {
|
|
130
|
+
const publicKey = yield window.crypto.subtle.importKey(
|
|
131
|
+
"jwk",
|
|
132
|
+
publicKeyJWK,
|
|
133
|
+
{
|
|
134
|
+
name: "ECDSA",
|
|
135
|
+
namedCurve: "P-256"
|
|
136
|
+
// Must match the curve used to generate the key
|
|
137
|
+
},
|
|
138
|
+
true,
|
|
139
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
140
|
+
["verify"]
|
|
141
|
+
);
|
|
142
|
+
return (data, signatureBase64url) => __async(this, null, function* () {
|
|
143
|
+
const encoder = new TextEncoder();
|
|
144
|
+
const signature = Uint8Array.from(
|
|
145
|
+
atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
|
|
146
|
+
(c) => c.charCodeAt(0)
|
|
147
|
+
);
|
|
148
|
+
const isValid = yield window.crypto.subtle.verify(
|
|
149
|
+
{
|
|
150
|
+
name: "ECDSA",
|
|
151
|
+
hash: { name: "SHA-256" }
|
|
152
|
+
// Required for ES256
|
|
153
|
+
},
|
|
154
|
+
publicKey,
|
|
155
|
+
signature,
|
|
156
|
+
encoder.encode(data)
|
|
157
|
+
);
|
|
158
|
+
return isValid;
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
};
|
|
72
163
|
// Annotate the CommonJS export names for ESM import in node:
|
|
73
164
|
0 && (module.exports = {
|
|
165
|
+
ES256,
|
|
74
166
|
digest,
|
|
75
167
|
generateSalt,
|
|
76
168
|
getHasher
|
package/dist/index.mjs
CHANGED
|
@@ -42,7 +42,98 @@ function digest(data, algorithm = "SHA-256") {
|
|
|
42
42
|
var getHasher = (algorithm = "SHA-256") => {
|
|
43
43
|
return (data) => digest(data, algorithm);
|
|
44
44
|
};
|
|
45
|
+
var ES256 = {
|
|
46
|
+
alg: "ES256",
|
|
47
|
+
generateKeyPair() {
|
|
48
|
+
return __async(this, null, function* () {
|
|
49
|
+
const keyPair = yield window.crypto.subtle.generateKey(
|
|
50
|
+
{
|
|
51
|
+
name: "ECDSA",
|
|
52
|
+
namedCurve: "P-256"
|
|
53
|
+
// ES256
|
|
54
|
+
},
|
|
55
|
+
true,
|
|
56
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
57
|
+
["sign", "verify"]
|
|
58
|
+
// can be used to sign and verify signatures
|
|
59
|
+
);
|
|
60
|
+
const publicKeyJWK = yield window.crypto.subtle.exportKey(
|
|
61
|
+
"jwk",
|
|
62
|
+
keyPair.publicKey
|
|
63
|
+
);
|
|
64
|
+
const privateKeyJWK = yield window.crypto.subtle.exportKey(
|
|
65
|
+
"jwk",
|
|
66
|
+
keyPair.privateKey
|
|
67
|
+
);
|
|
68
|
+
return { publicKey: publicKeyJWK, privateKey: privateKeyJWK };
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
getSigner(privateKeyJWK) {
|
|
72
|
+
return __async(this, null, function* () {
|
|
73
|
+
const privateKey = yield window.crypto.subtle.importKey(
|
|
74
|
+
"jwk",
|
|
75
|
+
privateKeyJWK,
|
|
76
|
+
{
|
|
77
|
+
name: "ECDSA",
|
|
78
|
+
namedCurve: "P-256"
|
|
79
|
+
// Must match the curve used to generate the key
|
|
80
|
+
},
|
|
81
|
+
true,
|
|
82
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
83
|
+
["sign"]
|
|
84
|
+
);
|
|
85
|
+
return (data) => __async(this, null, function* () {
|
|
86
|
+
const encoder = new TextEncoder();
|
|
87
|
+
const signature = yield window.crypto.subtle.sign(
|
|
88
|
+
{
|
|
89
|
+
name: "ECDSA",
|
|
90
|
+
hash: { name: "SHA-256" }
|
|
91
|
+
// Required for ES256
|
|
92
|
+
},
|
|
93
|
+
privateKey,
|
|
94
|
+
encoder.encode(data)
|
|
95
|
+
);
|
|
96
|
+
return window.btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
getVerifier(publicKeyJWK) {
|
|
101
|
+
return __async(this, null, function* () {
|
|
102
|
+
const publicKey = yield window.crypto.subtle.importKey(
|
|
103
|
+
"jwk",
|
|
104
|
+
publicKeyJWK,
|
|
105
|
+
{
|
|
106
|
+
name: "ECDSA",
|
|
107
|
+
namedCurve: "P-256"
|
|
108
|
+
// Must match the curve used to generate the key
|
|
109
|
+
},
|
|
110
|
+
true,
|
|
111
|
+
// whether the key is extractable (i.e., can be used in exportKey)
|
|
112
|
+
["verify"]
|
|
113
|
+
);
|
|
114
|
+
return (data, signatureBase64url) => __async(this, null, function* () {
|
|
115
|
+
const encoder = new TextEncoder();
|
|
116
|
+
const signature = Uint8Array.from(
|
|
117
|
+
atob(signatureBase64url.replace(/-/g, "+").replace(/_/g, "/")),
|
|
118
|
+
(c) => c.charCodeAt(0)
|
|
119
|
+
);
|
|
120
|
+
const isValid = yield window.crypto.subtle.verify(
|
|
121
|
+
{
|
|
122
|
+
name: "ECDSA",
|
|
123
|
+
hash: { name: "SHA-256" }
|
|
124
|
+
// Required for ES256
|
|
125
|
+
},
|
|
126
|
+
publicKey,
|
|
127
|
+
signature,
|
|
128
|
+
encoder.encode(data)
|
|
129
|
+
);
|
|
130
|
+
return isValid;
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
};
|
|
45
135
|
export {
|
|
136
|
+
ES256,
|
|
46
137
|
digest,
|
|
47
138
|
generateSalt,
|
|
48
139
|
getHasher
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/crypto-browser",
|
|
3
|
-
"version": "0.3.2-next.
|
|
3
|
+
"version": "0.3.2-next.73+2d8206e",
|
|
4
4
|
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"esm"
|
|
50
50
|
]
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "2d8206e45a61630743be32fe8d490bf001d82a5e"
|
|
53
53
|
}
|
package/src/crypto.ts
CHANGED
|
@@ -25,3 +25,93 @@ export async function digest(
|
|
|
25
25
|
export const getHasher = (algorithm = 'SHA-256') => {
|
|
26
26
|
return (data: string) => digest(data, algorithm);
|
|
27
27
|
};
|
|
28
|
+
|
|
29
|
+
export const ES256 = {
|
|
30
|
+
alg: 'ES256',
|
|
31
|
+
|
|
32
|
+
async generateKeyPair() {
|
|
33
|
+
const keyPair = await window.crypto.subtle.generateKey(
|
|
34
|
+
{
|
|
35
|
+
name: 'ECDSA',
|
|
36
|
+
namedCurve: 'P-256', // ES256
|
|
37
|
+
},
|
|
38
|
+
true, // whether the key is extractable (i.e., can be used in exportKey)
|
|
39
|
+
['sign', 'verify'], // can be used to sign and verify signatures
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Export the public and private keys in JWK format
|
|
43
|
+
const publicKeyJWK = await window.crypto.subtle.exportKey(
|
|
44
|
+
'jwk',
|
|
45
|
+
keyPair.publicKey,
|
|
46
|
+
);
|
|
47
|
+
const privateKeyJWK = await window.crypto.subtle.exportKey(
|
|
48
|
+
'jwk',
|
|
49
|
+
keyPair.privateKey,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return { publicKey: publicKeyJWK, privateKey: privateKeyJWK };
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
async getSigner(privateKeyJWK: object) {
|
|
56
|
+
const privateKey = await window.crypto.subtle.importKey(
|
|
57
|
+
'jwk',
|
|
58
|
+
privateKeyJWK,
|
|
59
|
+
{
|
|
60
|
+
name: 'ECDSA',
|
|
61
|
+
namedCurve: 'P-256', // Must match the curve used to generate the key
|
|
62
|
+
},
|
|
63
|
+
true, // whether the key is extractable (i.e., can be used in exportKey)
|
|
64
|
+
['sign'],
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return async (data: string) => {
|
|
68
|
+
const encoder = new TextEncoder();
|
|
69
|
+
const signature = await window.crypto.subtle.sign(
|
|
70
|
+
{
|
|
71
|
+
name: 'ECDSA',
|
|
72
|
+
hash: { name: 'SHA-256' }, // Required for ES256
|
|
73
|
+
},
|
|
74
|
+
privateKey,
|
|
75
|
+
encoder.encode(data),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
return window
|
|
79
|
+
.btoa(String.fromCharCode(...new Uint8Array(signature)))
|
|
80
|
+
.replace(/\+/g, '-')
|
|
81
|
+
.replace(/\//g, '_')
|
|
82
|
+
.replace(/=+$/, ''); // Convert to base64url format
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
async getVerifier(publicKeyJWK: object) {
|
|
87
|
+
const publicKey = await window.crypto.subtle.importKey(
|
|
88
|
+
'jwk',
|
|
89
|
+
publicKeyJWK,
|
|
90
|
+
{
|
|
91
|
+
name: 'ECDSA',
|
|
92
|
+
namedCurve: 'P-256', // Must match the curve used to generate the key
|
|
93
|
+
},
|
|
94
|
+
true, // whether the key is extractable (i.e., can be used in exportKey)
|
|
95
|
+
['verify'],
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
return async (data: string, signatureBase64url: string) => {
|
|
99
|
+
const encoder = new TextEncoder();
|
|
100
|
+
const signature = Uint8Array.from(
|
|
101
|
+
atob(signatureBase64url.replace(/-/g, '+').replace(/_/g, '/')),
|
|
102
|
+
(c) => c.charCodeAt(0),
|
|
103
|
+
);
|
|
104
|
+
const isValid = await window.crypto.subtle.verify(
|
|
105
|
+
{
|
|
106
|
+
name: 'ECDSA',
|
|
107
|
+
hash: { name: 'SHA-256' }, // Required for ES256
|
|
108
|
+
},
|
|
109
|
+
publicKey,
|
|
110
|
+
signature,
|
|
111
|
+
encoder.encode(data),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return isValid;
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
};
|
package/src/test/crypto.spec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { describe, expect, test
|
|
2
|
-
import { generateSalt, digest, getHasher } from '../index';
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { generateSalt, digest, getHasher, ES256 } from '../index';
|
|
3
3
|
|
|
4
4
|
// Extract the major version as a number
|
|
5
5
|
const nodeVersionMajor = parseInt(
|
|
@@ -41,4 +41,25 @@ describe('This file is for utility functions', () => {
|
|
|
41
41
|
const hash = await getHasher('SHA-512')('test1');
|
|
42
42
|
expect(hash).toBeDefined();
|
|
43
43
|
});
|
|
44
|
+
|
|
45
|
+
(nodeVersionMajor < 20 ? test.skip : test)('ES256 alg', () => {
|
|
46
|
+
expect(ES256.alg).toBe('ES256');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
(nodeVersionMajor < 20 ? test.skip : test)('ES256', async () => {
|
|
50
|
+
const { privateKey, publicKey } = await ES256.generateKeyPair();
|
|
51
|
+
expect(privateKey).toBeDefined();
|
|
52
|
+
expect(publicKey).toBeDefined();
|
|
53
|
+
expect(typeof privateKey).toBe('object');
|
|
54
|
+
expect(typeof publicKey).toBe('object');
|
|
55
|
+
|
|
56
|
+
const data =
|
|
57
|
+
'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.';
|
|
58
|
+
const signature = await (await ES256.getSigner(privateKey))(data);
|
|
59
|
+
expect(signature).toBeDefined();
|
|
60
|
+
expect(typeof signature).toBe('string');
|
|
61
|
+
|
|
62
|
+
const result = await (await ES256.getVerifier(publicKey))(data, signature);
|
|
63
|
+
expect(result).toBe(true);
|
|
64
|
+
});
|
|
44
65
|
});
|