@gjsify/crypto 0.3.12 → 0.3.14
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/lib/esm/asn1.js +576 -450
- package/lib/esm/bigint-math.js +37 -28
- package/lib/esm/cipher.js +1252 -1229
- package/lib/esm/constants.js +12 -13
- package/lib/esm/crypto-utils.js +54 -36
- package/lib/esm/dh.js +408 -368
- package/lib/esm/ecdh.js +403 -321
- package/lib/esm/ecdsa.js +138 -111
- package/lib/esm/hash.js +100 -89
- package/lib/esm/hkdf.js +65 -47
- package/lib/esm/hmac.js +95 -90
- package/lib/esm/index.js +75 -148
- package/lib/esm/key-object.js +348 -307
- package/lib/esm/mgf1.js +30 -24
- package/lib/esm/pbkdf2.js +66 -59
- package/lib/esm/public-encrypt.js +203 -156
- package/lib/esm/random.js +137 -124
- package/lib/esm/rsa-oaep.js +94 -87
- package/lib/esm/rsa-pss.js +95 -88
- package/lib/esm/scrypt.js +116 -115
- package/lib/esm/sign.js +267 -237
- package/lib/esm/timing-safe-equal.js +16 -11
- package/lib/esm/x509.js +215 -206
- package/package.json +7 -7
package/lib/esm/key-object.js
CHANGED
|
@@ -1,330 +1,371 @@
|
|
|
1
|
+
import { derToPem, encodePrivateKeyInfo, encodeRsaPrivateKeyPkcs1, encodeRsaPublicKeyPkcs1, encodeSubjectPublicKeyInfo, parsePemKey, rsaKeySize } from "./asn1.js";
|
|
1
2
|
import { Buffer } from "node:buffer";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
encodeSubjectPublicKeyInfo,
|
|
6
|
-
encodeRsaPublicKeyPkcs1,
|
|
7
|
-
encodeRsaPrivateKeyPkcs1,
|
|
8
|
-
encodePrivateKeyInfo,
|
|
9
|
-
derToPem
|
|
10
|
-
} from "./asn1.js";
|
|
3
|
+
|
|
4
|
+
//#region src/key-object.ts
|
|
5
|
+
/** Convert BigInt to base64url-encoded string (no padding). */
|
|
11
6
|
function bigintToBase64url(value) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
if (value === 0n) return "AA";
|
|
8
|
+
const hex = value.toString(16);
|
|
9
|
+
const paddedHex = hex.length % 2 ? "0" + hex : hex;
|
|
10
|
+
const bytes = [];
|
|
11
|
+
for (let i = 0; i < paddedHex.length; i += 2) {
|
|
12
|
+
bytes.push(parseInt(paddedHex.substring(i, i + 2), 16));
|
|
13
|
+
}
|
|
14
|
+
return Buffer.from(bytes).toString("base64url");
|
|
20
15
|
}
|
|
16
|
+
/** Convert base64url-encoded string to BigInt. */
|
|
21
17
|
function base64urlToBigint(b64) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
class KeyObject {
|
|
30
|
-
type;
|
|
31
|
-
/** @internal */
|
|
32
|
-
_handle;
|
|
33
|
-
constructor(type, handle) {
|
|
34
|
-
if (type !== "secret" && type !== "public" && type !== "private") {
|
|
35
|
-
throw new TypeError(`Invalid KeyObject type: ${type}`);
|
|
36
|
-
}
|
|
37
|
-
this.type = type;
|
|
38
|
-
this._handle = handle;
|
|
39
|
-
}
|
|
40
|
-
get symmetricKeySize() {
|
|
41
|
-
if (this.type !== "secret") return void 0;
|
|
42
|
-
return this._handle.byteLength;
|
|
43
|
-
}
|
|
44
|
-
get asymmetricKeyType() {
|
|
45
|
-
if (this.type === "secret") return void 0;
|
|
46
|
-
const handle = this._handle;
|
|
47
|
-
if (handle.parsed.type === "rsa-public" || handle.parsed.type === "rsa-private") {
|
|
48
|
-
return "rsa";
|
|
49
|
-
}
|
|
50
|
-
return void 0;
|
|
51
|
-
}
|
|
52
|
-
get asymmetricKeySize() {
|
|
53
|
-
if (this.type === "secret") return void 0;
|
|
54
|
-
const handle = this._handle;
|
|
55
|
-
if (handle.parsed.type === "rsa-public") {
|
|
56
|
-
return rsaKeySize(handle.parsed.components.n) / 8;
|
|
57
|
-
}
|
|
58
|
-
if (handle.parsed.type === "rsa-private") {
|
|
59
|
-
return rsaKeySize(handle.parsed.components.n) / 8;
|
|
60
|
-
}
|
|
61
|
-
return void 0;
|
|
62
|
-
}
|
|
63
|
-
equals(otherKeyObject) {
|
|
64
|
-
if (!(otherKeyObject instanceof KeyObject)) return false;
|
|
65
|
-
if (this.type !== otherKeyObject.type) return false;
|
|
66
|
-
if (this.type === "secret") {
|
|
67
|
-
const a2 = this._handle;
|
|
68
|
-
const b2 = otherKeyObject._handle;
|
|
69
|
-
if (a2.byteLength !== b2.byteLength) return false;
|
|
70
|
-
for (let i = 0; i < a2.byteLength; i++) {
|
|
71
|
-
if (a2[i] !== b2[i]) return false;
|
|
72
|
-
}
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
const a = this._handle;
|
|
76
|
-
const b = otherKeyObject._handle;
|
|
77
|
-
return a.pem === b.pem;
|
|
78
|
-
}
|
|
79
|
-
export(options) {
|
|
80
|
-
if (this.type === "secret") {
|
|
81
|
-
const key = this._handle;
|
|
82
|
-
if (options?.format === "jwk") {
|
|
83
|
-
return {
|
|
84
|
-
kty: "oct",
|
|
85
|
-
k: Buffer.from(key).toString("base64url")
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
return Buffer.from(key);
|
|
89
|
-
}
|
|
90
|
-
const handle = this._handle;
|
|
91
|
-
const format = options?.format ?? "pem";
|
|
92
|
-
const keyType = options?.type;
|
|
93
|
-
if (format === "jwk") {
|
|
94
|
-
return exportJwk(handle.parsed, this.type);
|
|
95
|
-
}
|
|
96
|
-
if (format === "pem") {
|
|
97
|
-
if (handle.pem && !handle.pem.startsWith("[")) {
|
|
98
|
-
return handle.pem;
|
|
99
|
-
}
|
|
100
|
-
return generatePem(handle.parsed, this.type, keyType);
|
|
101
|
-
}
|
|
102
|
-
if (format === "der") {
|
|
103
|
-
if (handle.pem && !handle.pem.startsWith("[")) {
|
|
104
|
-
const lines = handle.pem.trim().split(/\r?\n/);
|
|
105
|
-
const headerIdx = lines.findIndex((l) => l.startsWith("-----BEGIN "));
|
|
106
|
-
const footerIdx = lines.findIndex((l, i) => i > headerIdx && l.startsWith("-----END "));
|
|
107
|
-
const base64Body = lines.slice(headerIdx + 1, footerIdx).join("");
|
|
108
|
-
return Buffer.from(base64Body, "base64");
|
|
109
|
-
}
|
|
110
|
-
return generateDer(handle.parsed, this.type, keyType);
|
|
111
|
-
}
|
|
112
|
-
throw new TypeError(`Unsupported export format: ${format}`);
|
|
113
|
-
}
|
|
114
|
-
get [Symbol.toStringTag]() {
|
|
115
|
-
return "KeyObject";
|
|
116
|
-
}
|
|
18
|
+
const buf = Buffer.from(b64, "base64url");
|
|
19
|
+
let result = 0n;
|
|
20
|
+
for (let i = 0; i < buf.length; i++) {
|
|
21
|
+
result = result << 8n | BigInt(buf[i]);
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
117
24
|
}
|
|
25
|
+
var KeyObject = class KeyObject {
|
|
26
|
+
type;
|
|
27
|
+
/** @internal */
|
|
28
|
+
_handle;
|
|
29
|
+
constructor(type, handle) {
|
|
30
|
+
if (type !== "secret" && type !== "public" && type !== "private") {
|
|
31
|
+
throw new TypeError(`Invalid KeyObject type: ${type}`);
|
|
32
|
+
}
|
|
33
|
+
this.type = type;
|
|
34
|
+
this._handle = handle;
|
|
35
|
+
}
|
|
36
|
+
get symmetricKeySize() {
|
|
37
|
+
if (this.type !== "secret") return undefined;
|
|
38
|
+
return this._handle.byteLength;
|
|
39
|
+
}
|
|
40
|
+
get asymmetricKeyType() {
|
|
41
|
+
if (this.type === "secret") return undefined;
|
|
42
|
+
const handle = this._handle;
|
|
43
|
+
if (handle.parsed.type === "rsa-public" || handle.parsed.type === "rsa-private") {
|
|
44
|
+
return "rsa";
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
get asymmetricKeySize() {
|
|
49
|
+
if (this.type === "secret") return undefined;
|
|
50
|
+
const handle = this._handle;
|
|
51
|
+
if (handle.parsed.type === "rsa-public") {
|
|
52
|
+
return rsaKeySize(handle.parsed.components.n) / 8;
|
|
53
|
+
}
|
|
54
|
+
if (handle.parsed.type === "rsa-private") {
|
|
55
|
+
return rsaKeySize(handle.parsed.components.n) / 8;
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
equals(otherKeyObject) {
|
|
60
|
+
if (!(otherKeyObject instanceof KeyObject)) return false;
|
|
61
|
+
if (this.type !== otherKeyObject.type) return false;
|
|
62
|
+
if (this.type === "secret") {
|
|
63
|
+
const a = this._handle;
|
|
64
|
+
const b = otherKeyObject._handle;
|
|
65
|
+
if (a.byteLength !== b.byteLength) return false;
|
|
66
|
+
for (let i = 0; i < a.byteLength; i++) {
|
|
67
|
+
if (a[i] !== b[i]) return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
const a = this._handle;
|
|
72
|
+
const b = otherKeyObject._handle;
|
|
73
|
+
return a.pem === b.pem;
|
|
74
|
+
}
|
|
75
|
+
export(options) {
|
|
76
|
+
if (this.type === "secret") {
|
|
77
|
+
const key = this._handle;
|
|
78
|
+
if (options?.format === "jwk") {
|
|
79
|
+
return {
|
|
80
|
+
kty: "oct",
|
|
81
|
+
k: Buffer.from(key).toString("base64url")
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return Buffer.from(key);
|
|
85
|
+
}
|
|
86
|
+
const handle = this._handle;
|
|
87
|
+
const format = options?.format ?? "pem";
|
|
88
|
+
const keyType = options?.type;
|
|
89
|
+
if (format === "jwk") {
|
|
90
|
+
return exportJwk(handle.parsed, this.type);
|
|
91
|
+
}
|
|
92
|
+
if (format === "pem") {
|
|
93
|
+
if (handle.pem && !handle.pem.startsWith("[")) {
|
|
94
|
+
return handle.pem;
|
|
95
|
+
}
|
|
96
|
+
return generatePem(handle.parsed, this.type, keyType);
|
|
97
|
+
}
|
|
98
|
+
if (format === "der") {
|
|
99
|
+
if (handle.pem && !handle.pem.startsWith("[")) {
|
|
100
|
+
const lines = handle.pem.trim().split(/\r?\n/);
|
|
101
|
+
const headerIdx = lines.findIndex((l) => l.startsWith("-----BEGIN "));
|
|
102
|
+
const footerIdx = lines.findIndex((l, i) => i > headerIdx && l.startsWith("-----END "));
|
|
103
|
+
const base64Body = lines.slice(headerIdx + 1, footerIdx).join("");
|
|
104
|
+
return Buffer.from(base64Body, "base64");
|
|
105
|
+
}
|
|
106
|
+
return generateDer(handle.parsed, this.type, keyType);
|
|
107
|
+
}
|
|
108
|
+
throw new TypeError(`Unsupported export format: ${format}`);
|
|
109
|
+
}
|
|
110
|
+
get [Symbol.toStringTag]() {
|
|
111
|
+
return "KeyObject";
|
|
112
|
+
}
|
|
113
|
+
};
|
|
118
114
|
function exportJwk(parsed, keyType) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
115
|
+
if (parsed.type === "rsa-public") {
|
|
116
|
+
return {
|
|
117
|
+
kty: "RSA",
|
|
118
|
+
n: bigintToBase64url(parsed.components.n),
|
|
119
|
+
e: bigintToBase64url(parsed.components.e)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (parsed.type === "rsa-private") {
|
|
123
|
+
if (keyType === "public") {
|
|
124
|
+
return {
|
|
125
|
+
kty: "RSA",
|
|
126
|
+
n: bigintToBase64url(parsed.components.n),
|
|
127
|
+
e: bigintToBase64url(parsed.components.e)
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const { n, e, d, p, q } = parsed.components;
|
|
131
|
+
const dp = d % (p - 1n);
|
|
132
|
+
const dq = d % (q - 1n);
|
|
133
|
+
const qi = modInverse(q, p);
|
|
134
|
+
return {
|
|
135
|
+
kty: "RSA",
|
|
136
|
+
n: bigintToBase64url(n),
|
|
137
|
+
e: bigintToBase64url(e),
|
|
138
|
+
d: bigintToBase64url(d),
|
|
139
|
+
p: bigintToBase64url(p),
|
|
140
|
+
q: bigintToBase64url(q),
|
|
141
|
+
dp: bigintToBase64url(dp),
|
|
142
|
+
dq: bigintToBase64url(dq),
|
|
143
|
+
qi: bigintToBase64url(qi)
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
throw new Error("Unsupported key type for JWK export");
|
|
151
147
|
}
|
|
152
148
|
function importJwkRsa(jwk) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
149
|
+
if (jwk.d) {
|
|
150
|
+
const components = {
|
|
151
|
+
n: base64urlToBigint(jwk.n),
|
|
152
|
+
e: base64urlToBigint(jwk.e),
|
|
153
|
+
d: base64urlToBigint(jwk.d),
|
|
154
|
+
p: base64urlToBigint(jwk.p),
|
|
155
|
+
q: base64urlToBigint(jwk.q)
|
|
156
|
+
};
|
|
157
|
+
const parsed = {
|
|
158
|
+
type: "rsa-private",
|
|
159
|
+
components
|
|
160
|
+
};
|
|
161
|
+
const der = encodeRsaPrivateKeyPkcs1(components);
|
|
162
|
+
const pem = derToPem(der, "RSA PRIVATE KEY");
|
|
163
|
+
return {
|
|
164
|
+
parsed,
|
|
165
|
+
pem
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const components = {
|
|
169
|
+
n: base64urlToBigint(jwk.n),
|
|
170
|
+
e: base64urlToBigint(jwk.e)
|
|
171
|
+
};
|
|
172
|
+
const parsed = {
|
|
173
|
+
type: "rsa-public",
|
|
174
|
+
components
|
|
175
|
+
};
|
|
176
|
+
const der = encodeSubjectPublicKeyInfo(components);
|
|
177
|
+
const pem = derToPem(der, "PUBLIC KEY");
|
|
178
|
+
return {
|
|
179
|
+
parsed,
|
|
180
|
+
pem
|
|
181
|
+
};
|
|
174
182
|
}
|
|
175
183
|
function generatePem(parsed, keyType, type) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
184
|
+
if (parsed.type === "rsa-public") {
|
|
185
|
+
if (type === "pkcs1") {
|
|
186
|
+
const der = encodeRsaPublicKeyPkcs1(parsed.components);
|
|
187
|
+
return derToPem(der, "RSA PUBLIC KEY");
|
|
188
|
+
}
|
|
189
|
+
const der = encodeSubjectPublicKeyInfo(parsed.components);
|
|
190
|
+
return derToPem(der, "PUBLIC KEY");
|
|
191
|
+
}
|
|
192
|
+
if (parsed.type === "rsa-private" && keyType === "public") {
|
|
193
|
+
const pubComponents = {
|
|
194
|
+
n: parsed.components.n,
|
|
195
|
+
e: parsed.components.e
|
|
196
|
+
};
|
|
197
|
+
if (type === "pkcs1") {
|
|
198
|
+
const der = encodeRsaPublicKeyPkcs1(pubComponents);
|
|
199
|
+
return derToPem(der, "RSA PUBLIC KEY");
|
|
200
|
+
}
|
|
201
|
+
const der = encodeSubjectPublicKeyInfo(pubComponents);
|
|
202
|
+
return derToPem(der, "PUBLIC KEY");
|
|
203
|
+
}
|
|
204
|
+
if (parsed.type === "rsa-private") {
|
|
205
|
+
if (type === "pkcs8") {
|
|
206
|
+
const der = encodePrivateKeyInfo(parsed.components);
|
|
207
|
+
return derToPem(der, "PRIVATE KEY");
|
|
208
|
+
}
|
|
209
|
+
const der = encodeRsaPrivateKeyPkcs1(parsed.components);
|
|
210
|
+
return derToPem(der, "RSA PRIVATE KEY");
|
|
211
|
+
}
|
|
212
|
+
throw new Error("Cannot generate PEM for this key type");
|
|
205
213
|
}
|
|
206
214
|
function generateDer(parsed, keyType, type) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
215
|
+
if (parsed.type === "rsa-public") {
|
|
216
|
+
if (type === "pkcs1") {
|
|
217
|
+
return Buffer.from(encodeRsaPublicKeyPkcs1(parsed.components));
|
|
218
|
+
}
|
|
219
|
+
return Buffer.from(encodeSubjectPublicKeyInfo(parsed.components));
|
|
220
|
+
}
|
|
221
|
+
if (parsed.type === "rsa-private" && keyType === "public") {
|
|
222
|
+
const pubComponents = {
|
|
223
|
+
n: parsed.components.n,
|
|
224
|
+
e: parsed.components.e
|
|
225
|
+
};
|
|
226
|
+
if (type === "pkcs1") {
|
|
227
|
+
return Buffer.from(encodeRsaPublicKeyPkcs1(pubComponents));
|
|
228
|
+
}
|
|
229
|
+
return Buffer.from(encodeSubjectPublicKeyInfo(pubComponents));
|
|
230
|
+
}
|
|
231
|
+
if (parsed.type === "rsa-private") {
|
|
232
|
+
if (type === "pkcs8") {
|
|
233
|
+
return Buffer.from(encodePrivateKeyInfo(parsed.components));
|
|
234
|
+
}
|
|
235
|
+
return Buffer.from(encodeRsaPrivateKeyPkcs1(parsed.components));
|
|
236
|
+
}
|
|
237
|
+
throw new Error("Cannot generate DER for this key type");
|
|
230
238
|
}
|
|
231
239
|
function modInverse(a, m) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
+
let [old_r, r] = [a % m, m];
|
|
241
|
+
let [old_s, s] = [1n, 0n];
|
|
242
|
+
while (r !== 0n) {
|
|
243
|
+
const q = old_r / r;
|
|
244
|
+
[old_r, r] = [r, old_r - q * r];
|
|
245
|
+
[old_s, s] = [s, old_s - q * s];
|
|
246
|
+
}
|
|
247
|
+
return (old_s % m + m) % m;
|
|
240
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Create a secret key from raw bytes.
|
|
251
|
+
*/
|
|
241
252
|
function createSecretKey(key, encoding) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
253
|
+
let keyBuf;
|
|
254
|
+
if (typeof key === "string") {
|
|
255
|
+
keyBuf = Buffer.from(key, encoding ?? "utf8");
|
|
256
|
+
} else {
|
|
257
|
+
keyBuf = new Uint8Array(key);
|
|
258
|
+
}
|
|
259
|
+
return new KeyObject("secret", keyBuf);
|
|
249
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Create a public key from PEM, DER, JWK, or another KeyObject.
|
|
263
|
+
*/
|
|
250
264
|
function createPublicKey(key) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
265
|
+
if (key instanceof KeyObject) {
|
|
266
|
+
if (key.type === "public") return key;
|
|
267
|
+
if (key.type === "private") {
|
|
268
|
+
const handle = key._handle;
|
|
269
|
+
if (handle.parsed.type === "rsa-private") {
|
|
270
|
+
const pubComponents = {
|
|
271
|
+
n: handle.parsed.components.n,
|
|
272
|
+
e: handle.parsed.components.e
|
|
273
|
+
};
|
|
274
|
+
const pubParsed = {
|
|
275
|
+
type: "rsa-public",
|
|
276
|
+
components: pubComponents
|
|
277
|
+
};
|
|
278
|
+
const der = encodeSubjectPublicKeyInfo(pubComponents);
|
|
279
|
+
const pem = derToPem(der, "PUBLIC KEY");
|
|
280
|
+
return new KeyObject("public", {
|
|
281
|
+
parsed: pubParsed,
|
|
282
|
+
pem
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
throw new TypeError("Cannot create public key from secret key");
|
|
287
|
+
}
|
|
288
|
+
if (typeof key === "object" && !Buffer.isBuffer(key) && "key" in key) {
|
|
289
|
+
const input = key;
|
|
290
|
+
if (input.format === "jwk") {
|
|
291
|
+
const jwk = input.key;
|
|
292
|
+
if (jwk.kty === "RSA") {
|
|
293
|
+
const { parsed, pem } = importJwkRsa({
|
|
294
|
+
n: jwk.n,
|
|
295
|
+
e: jwk.e
|
|
296
|
+
});
|
|
297
|
+
return new KeyObject("public", {
|
|
298
|
+
parsed,
|
|
299
|
+
pem
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
throw new Error(`Unsupported JWK key type: ${jwk.kty}`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const pem = normalizePem(key);
|
|
306
|
+
const parsed = parsePemKey(pem);
|
|
307
|
+
if (parsed.type === "rsa-private") {
|
|
308
|
+
const pubComponents = {
|
|
309
|
+
n: parsed.components.n,
|
|
310
|
+
e: parsed.components.e
|
|
311
|
+
};
|
|
312
|
+
const pubParsed = {
|
|
313
|
+
type: "rsa-public",
|
|
314
|
+
components: pubComponents
|
|
315
|
+
};
|
|
316
|
+
const der = encodeSubjectPublicKeyInfo(pubComponents);
|
|
317
|
+
const pubPem = derToPem(der, "PUBLIC KEY");
|
|
318
|
+
return new KeyObject("public", {
|
|
319
|
+
parsed: pubParsed,
|
|
320
|
+
pem: pubPem
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
return new KeyObject("public", {
|
|
324
|
+
parsed,
|
|
325
|
+
pem
|
|
326
|
+
});
|
|
292
327
|
}
|
|
328
|
+
/**
|
|
329
|
+
* Create a private key from PEM, DER, JWK, or KeyInput.
|
|
330
|
+
*/
|
|
293
331
|
function createPrivateKey(key) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
332
|
+
if (typeof key === "object" && !Buffer.isBuffer(key) && "key" in key) {
|
|
333
|
+
const input = key;
|
|
334
|
+
if (input.format === "jwk") {
|
|
335
|
+
const jwk = input.key;
|
|
336
|
+
if (jwk.kty === "RSA" && jwk.d) {
|
|
337
|
+
const { parsed, pem } = importJwkRsa(jwk);
|
|
338
|
+
return new KeyObject("private", {
|
|
339
|
+
parsed,
|
|
340
|
+
pem
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
throw new Error("JWK does not contain a private key");
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const pem = normalizePem(key);
|
|
347
|
+
const parsed = parsePemKey(pem);
|
|
348
|
+
if (parsed.type !== "rsa-private") {
|
|
349
|
+
throw new TypeError("Key is not a private key");
|
|
350
|
+
}
|
|
351
|
+
return new KeyObject("private", {
|
|
352
|
+
parsed,
|
|
353
|
+
pem
|
|
354
|
+
});
|
|
311
355
|
}
|
|
312
356
|
function normalizePem(key) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
357
|
+
if (typeof key === "string") return key;
|
|
358
|
+
if (Buffer.isBuffer(key)) return key.toString("utf8");
|
|
359
|
+
if (key && typeof key === "object" && "key" in key) {
|
|
360
|
+
const input = key;
|
|
361
|
+
if (typeof input.key === "string") return input.key;
|
|
362
|
+
if (Buffer.isBuffer(input.key)) return input.key.toString(input.encoding ?? "utf8");
|
|
363
|
+
if (input.key instanceof KeyObject) {
|
|
364
|
+
return input.key.export({ format: "pem" });
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
throw new TypeError("Invalid key input");
|
|
324
368
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
createPublicKey,
|
|
329
|
-
createSecretKey
|
|
330
|
-
};
|
|
369
|
+
|
|
370
|
+
//#endregion
|
|
371
|
+
export { KeyObject, createPrivateKey, createPublicKey, createSecretKey };
|