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