@certd/acme-client 1.20.14 → 1.20.16
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/README.md +19 -20
- package/package.json +11 -11
- package/src/api.js +1 -17
- package/src/auto.js +36 -30
- package/src/axios.js +1 -4
- package/src/client.js +18 -42
- package/src/crypto/forge.js +18 -31
- package/src/crypto/index.js +25 -40
- package/src/http.js +3 -14
- package/src/index.js +4 -8
- package/src/logger.js +1 -3
- package/src/util.js +2 -13
- package/src/verify.js +1 -6
- package/src/wait.js +9 -0
- package/types/index.d.ts +0 -6
- package/types/index.test-d.ts +0 -1
- package/types/rfc8555.d.ts +0 -4
package/src/crypto/index.js
CHANGED
|
@@ -22,7 +22,6 @@ const subjectAltNameOID = '2.5.29.17';
|
|
|
22
22
|
/* id-pe-acmeIdentifier - https://datatracker.ietf.org/doc/html/rfc8737#section-6.1 */
|
|
23
23
|
const alpnAcmeIdentifierOID = '1.3.6.1.5.5.7.1.31';
|
|
24
24
|
|
|
25
|
-
|
|
26
25
|
/**
|
|
27
26
|
* Determine key type and info by attempting to derive public key
|
|
28
27
|
*
|
|
@@ -35,7 +34,7 @@ function getKeyInfo(keyPem) {
|
|
|
35
34
|
const result = {
|
|
36
35
|
isRSA: false,
|
|
37
36
|
isECDSA: false,
|
|
38
|
-
publicKey: crypto.createPublicKey(keyPem)
|
|
37
|
+
publicKey: crypto.createPublicKey(keyPem),
|
|
39
38
|
};
|
|
40
39
|
|
|
41
40
|
if (result.publicKey.asymmetricKeyType === 'rsa') {
|
|
@@ -51,7 +50,6 @@ function getKeyInfo(keyPem) {
|
|
|
51
50
|
return result;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
|
|
55
53
|
/**
|
|
56
54
|
* Generate a private RSA key
|
|
57
55
|
*
|
|
@@ -74,8 +72,8 @@ async function createPrivateRsaKey(modulusLength = 2048) {
|
|
|
74
72
|
modulusLength,
|
|
75
73
|
privateKeyEncoding: {
|
|
76
74
|
type: 'pkcs8',
|
|
77
|
-
format: 'pem'
|
|
78
|
-
}
|
|
75
|
+
format: 'pem',
|
|
76
|
+
},
|
|
79
77
|
});
|
|
80
78
|
|
|
81
79
|
return Buffer.from(pair.privateKey);
|
|
@@ -83,7 +81,6 @@ async function createPrivateRsaKey(modulusLength = 2048) {
|
|
|
83
81
|
|
|
84
82
|
exports.createPrivateRsaKey = createPrivateRsaKey;
|
|
85
83
|
|
|
86
|
-
|
|
87
84
|
/**
|
|
88
85
|
* Alias of `createPrivateRsaKey()`
|
|
89
86
|
*
|
|
@@ -92,7 +89,6 @@ exports.createPrivateRsaKey = createPrivateRsaKey;
|
|
|
92
89
|
|
|
93
90
|
exports.createPrivateKey = createPrivateRsaKey;
|
|
94
91
|
|
|
95
|
-
|
|
96
92
|
/**
|
|
97
93
|
* Generate a private ECDSA key
|
|
98
94
|
*
|
|
@@ -115,14 +111,13 @@ exports.createPrivateEcdsaKey = async (namedCurve = 'P-256') => {
|
|
|
115
111
|
namedCurve,
|
|
116
112
|
privateKeyEncoding: {
|
|
117
113
|
type: 'pkcs8',
|
|
118
|
-
format: 'pem'
|
|
119
|
-
}
|
|
114
|
+
format: 'pem',
|
|
115
|
+
},
|
|
120
116
|
});
|
|
121
117
|
|
|
122
118
|
return Buffer.from(pair.privateKey);
|
|
123
119
|
};
|
|
124
120
|
|
|
125
|
-
|
|
126
121
|
/**
|
|
127
122
|
* Get a public key derived from a RSA or ECDSA key
|
|
128
123
|
*
|
|
@@ -140,13 +135,12 @@ exports.getPublicKey = (keyPem) => {
|
|
|
140
135
|
|
|
141
136
|
const publicKey = info.publicKey.export({
|
|
142
137
|
type: info.isECDSA ? 'spki' : 'pkcs1',
|
|
143
|
-
format: 'pem'
|
|
138
|
+
format: 'pem',
|
|
144
139
|
});
|
|
145
140
|
|
|
146
141
|
return Buffer.from(publicKey);
|
|
147
142
|
};
|
|
148
143
|
|
|
149
|
-
|
|
150
144
|
/**
|
|
151
145
|
* Get a JSON Web Key derived from a RSA or ECDSA key
|
|
152
146
|
*
|
|
@@ -163,7 +157,7 @@ exports.getPublicKey = (keyPem) => {
|
|
|
163
157
|
|
|
164
158
|
function getJwk(keyPem) {
|
|
165
159
|
const jwk = crypto.createPublicKey(keyPem).export({
|
|
166
|
-
format: 'jwk'
|
|
160
|
+
format: 'jwk',
|
|
167
161
|
});
|
|
168
162
|
|
|
169
163
|
/* Sort keys */
|
|
@@ -175,7 +169,6 @@ function getJwk(keyPem) {
|
|
|
175
169
|
|
|
176
170
|
exports.getJwk = getJwk;
|
|
177
171
|
|
|
178
|
-
|
|
179
172
|
/**
|
|
180
173
|
* Produce CryptoKeyPair and signing algorithm from a PEM encoded private key
|
|
181
174
|
*
|
|
@@ -191,7 +184,7 @@ async function getWebCryptoKeyPair(keyPem) {
|
|
|
191
184
|
/* Signing algorithm */
|
|
192
185
|
const sigalg = {
|
|
193
186
|
name: 'RSASSA-PKCS1-v1_5',
|
|
194
|
-
hash: { name: 'SHA-256' }
|
|
187
|
+
hash: { name: 'SHA-256' },
|
|
195
188
|
};
|
|
196
189
|
|
|
197
190
|
if (info.isECDSA) {
|
|
@@ -215,7 +208,6 @@ async function getWebCryptoKeyPair(keyPem) {
|
|
|
215
208
|
return [{ privateKey, publicKey }, sigalg];
|
|
216
209
|
}
|
|
217
210
|
|
|
218
|
-
|
|
219
211
|
/**
|
|
220
212
|
* Split chain of PEM encoded objects from string into array
|
|
221
213
|
*
|
|
@@ -235,7 +227,6 @@ function splitPemChain(chainPem) {
|
|
|
235
227
|
|
|
236
228
|
exports.splitPemChain = splitPemChain;
|
|
237
229
|
|
|
238
|
-
|
|
239
230
|
/**
|
|
240
231
|
* Parse body of PEM encoded object and return a Base64URL string
|
|
241
232
|
* If multiple objects are chained, the first body will be returned
|
|
@@ -256,7 +247,6 @@ exports.getPemBodyAsB64u = (pem) => {
|
|
|
256
247
|
return Buffer.from(dec).toString('base64url');
|
|
257
248
|
};
|
|
258
249
|
|
|
259
|
-
|
|
260
250
|
/**
|
|
261
251
|
* Parse domains from a certificate or CSR
|
|
262
252
|
*
|
|
@@ -277,11 +267,10 @@ function parseDomains(input) {
|
|
|
277
267
|
|
|
278
268
|
return {
|
|
279
269
|
commonName,
|
|
280
|
-
altNames
|
|
270
|
+
altNames,
|
|
281
271
|
};
|
|
282
272
|
}
|
|
283
273
|
|
|
284
|
-
|
|
285
274
|
/**
|
|
286
275
|
* Read domains from a Certificate Signing Request
|
|
287
276
|
*
|
|
@@ -307,7 +296,6 @@ exports.readCsrDomains = (csrPem) => {
|
|
|
307
296
|
return parseDomains(csr);
|
|
308
297
|
};
|
|
309
298
|
|
|
310
|
-
|
|
311
299
|
/**
|
|
312
300
|
* Read information from a certificate
|
|
313
301
|
* If multiple certificates are chained, the first will be read
|
|
@@ -338,15 +326,14 @@ exports.readCertificateInfo = (certPem) => {
|
|
|
338
326
|
|
|
339
327
|
return {
|
|
340
328
|
issuer: {
|
|
341
|
-
commonName: cert.issuerName.getField('CN').pop() || null
|
|
329
|
+
commonName: cert.issuerName.getField('CN').pop() || null,
|
|
342
330
|
},
|
|
343
331
|
domains: parseDomains(cert),
|
|
344
332
|
notBefore: cert.notBefore,
|
|
345
|
-
notAfter: cert.notAfter
|
|
333
|
+
notAfter: cert.notAfter,
|
|
346
334
|
};
|
|
347
335
|
};
|
|
348
336
|
|
|
349
|
-
|
|
350
337
|
/**
|
|
351
338
|
* Determine ASN.1 character string type for CSR subject field name
|
|
352
339
|
*
|
|
@@ -369,7 +356,6 @@ function getCsrAsn1CharStringType(field) {
|
|
|
369
356
|
}
|
|
370
357
|
}
|
|
371
358
|
|
|
372
|
-
|
|
373
359
|
/**
|
|
374
360
|
* Create array of subject fields for a Certificate Signing Request
|
|
375
361
|
*
|
|
@@ -391,7 +377,6 @@ function createCsrSubject(input) {
|
|
|
391
377
|
}, []);
|
|
392
378
|
}
|
|
393
379
|
|
|
394
|
-
|
|
395
380
|
/**
|
|
396
381
|
* Create x509 subject alternate name extension
|
|
397
382
|
*
|
|
@@ -409,7 +394,6 @@ function createSubjectAltNameExtension(altNames) {
|
|
|
409
394
|
}));
|
|
410
395
|
}
|
|
411
396
|
|
|
412
|
-
|
|
413
397
|
/**
|
|
414
398
|
* Create a Certificate Signing Request
|
|
415
399
|
*
|
|
@@ -429,29 +413,30 @@ function createSubjectAltNameExtension(altNames) {
|
|
|
429
413
|
* @example Create a Certificate Signing Request
|
|
430
414
|
* ```js
|
|
431
415
|
* const [certificateKey, certificateRequest] = await acme.crypto.createCsr({
|
|
432
|
-
*
|
|
416
|
+
* altNames: ['test.example.com'],
|
|
433
417
|
* });
|
|
434
418
|
* ```
|
|
435
419
|
*
|
|
436
420
|
* @example Certificate Signing Request with both common and alternative names
|
|
421
|
+
* > *Warning*: Certificate subject common name has been [deprecated](https://letsencrypt.org/docs/glossary/#def-CN) and its use is [discouraged](https://cabforum.org/uploads/BRv1.2.3.pdf).
|
|
437
422
|
* ```js
|
|
438
423
|
* const [certificateKey, certificateRequest] = await acme.crypto.createCsr({
|
|
439
424
|
* keySize: 4096,
|
|
440
425
|
* commonName: 'test.example.com',
|
|
441
|
-
* altNames: ['foo.example.com', 'bar.example.com']
|
|
426
|
+
* altNames: ['foo.example.com', 'bar.example.com'],
|
|
442
427
|
* });
|
|
443
428
|
* ```
|
|
444
429
|
*
|
|
445
430
|
* @example Certificate Signing Request with additional information
|
|
446
431
|
* ```js
|
|
447
432
|
* const [certificateKey, certificateRequest] = await acme.crypto.createCsr({
|
|
448
|
-
*
|
|
433
|
+
* altNames: ['test.example.com'],
|
|
449
434
|
* country: 'US',
|
|
450
435
|
* state: 'California',
|
|
451
436
|
* locality: 'Los Angeles',
|
|
452
437
|
* organization: 'The Company Inc.',
|
|
453
438
|
* organizationUnit: 'IT Department',
|
|
454
|
-
* emailAddress: 'contact@example.com'
|
|
439
|
+
* emailAddress: 'contact@example.com',
|
|
455
440
|
* });
|
|
456
441
|
* ```
|
|
457
442
|
*
|
|
@@ -460,8 +445,9 @@ function createSubjectAltNameExtension(altNames) {
|
|
|
460
445
|
* const certificateKey = await acme.crypto.createPrivateEcdsaKey();
|
|
461
446
|
*
|
|
462
447
|
* const [, certificateRequest] = await acme.crypto.createCsr({
|
|
463
|
-
*
|
|
448
|
+
* altNames: ['test.example.com'],
|
|
464
449
|
* }, certificateKey);
|
|
450
|
+
* ```
|
|
465
451
|
*/
|
|
466
452
|
|
|
467
453
|
exports.createCsr = async (data, keyPem = null) => {
|
|
@@ -489,7 +475,7 @@ exports.createCsr = async (data, keyPem = null) => {
|
|
|
489
475
|
new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature | x509.KeyUsageFlags.keyEncipherment), // eslint-disable-line no-bitwise
|
|
490
476
|
|
|
491
477
|
/* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 */
|
|
492
|
-
createSubjectAltNameExtension(data.altNames)
|
|
478
|
+
createSubjectAltNameExtension(data.altNames),
|
|
493
479
|
];
|
|
494
480
|
|
|
495
481
|
/* Create CSR */
|
|
@@ -504,8 +490,8 @@ exports.createCsr = async (data, keyPem = null) => {
|
|
|
504
490
|
L: data.locality,
|
|
505
491
|
O: data.organization,
|
|
506
492
|
OU: data.organizationUnit,
|
|
507
|
-
E: data.emailAddress
|
|
508
|
-
})
|
|
493
|
+
E: data.emailAddress,
|
|
494
|
+
}),
|
|
509
495
|
});
|
|
510
496
|
|
|
511
497
|
/* Done */
|
|
@@ -513,7 +499,6 @@ exports.createCsr = async (data, keyPem = null) => {
|
|
|
513
499
|
return [keyPem, Buffer.from(pem)];
|
|
514
500
|
};
|
|
515
501
|
|
|
516
|
-
|
|
517
502
|
/**
|
|
518
503
|
* Create a self-signed ALPN certificate for TLS-ALPN-01 challenges
|
|
519
504
|
*
|
|
@@ -533,6 +518,7 @@ exports.createCsr = async (data, keyPem = null) => {
|
|
|
533
518
|
* ```js
|
|
534
519
|
* const alpnKey = await acme.crypto.createPrivateEcdsaKey();
|
|
535
520
|
* const [, alpnCertificate] = await acme.crypto.createAlpnCertificate(authz, keyAuthorization, alpnKey);
|
|
521
|
+
* ```
|
|
536
522
|
*/
|
|
537
523
|
|
|
538
524
|
exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) => {
|
|
@@ -564,7 +550,7 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
|
|
|
564
550
|
await x509.SubjectKeyIdentifierExtension.create(keys.publicKey),
|
|
565
551
|
|
|
566
552
|
/* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 */
|
|
567
|
-
createSubjectAltNameExtension([commonName])
|
|
553
|
+
createSubjectAltNameExtension([commonName]),
|
|
568
554
|
];
|
|
569
555
|
|
|
570
556
|
/* ALPN extension */
|
|
@@ -581,8 +567,8 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
|
|
|
581
567
|
notBefore: now,
|
|
582
568
|
notAfter: now,
|
|
583
569
|
name: createCsrSubject({
|
|
584
|
-
CN: commonName
|
|
585
|
-
})
|
|
570
|
+
CN: commonName,
|
|
571
|
+
}),
|
|
586
572
|
});
|
|
587
573
|
|
|
588
574
|
/* Done */
|
|
@@ -590,7 +576,6 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
|
|
|
590
576
|
return [keyPem, Buffer.from(pem)];
|
|
591
577
|
};
|
|
592
578
|
|
|
593
|
-
|
|
594
579
|
/**
|
|
595
580
|
* Validate that a ALPN certificate contains the expected key authorization
|
|
596
581
|
*
|
package/src/http.js
CHANGED
|
@@ -40,7 +40,6 @@ class HttpClient {
|
|
|
40
40
|
this.jwk = null;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
44
43
|
/**
|
|
45
44
|
* HTTP request
|
|
46
45
|
*
|
|
@@ -70,7 +69,6 @@ class HttpClient {
|
|
|
70
69
|
return resp;
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
|
|
74
72
|
/**
|
|
75
73
|
* Ensure provider directory exists
|
|
76
74
|
*
|
|
@@ -95,7 +93,6 @@ class HttpClient {
|
|
|
95
93
|
}
|
|
96
94
|
}
|
|
97
95
|
|
|
98
|
-
|
|
99
96
|
/**
|
|
100
97
|
* Get JSON Web Key
|
|
101
98
|
*
|
|
@@ -110,7 +107,6 @@ class HttpClient {
|
|
|
110
107
|
return this.jwk;
|
|
111
108
|
}
|
|
112
109
|
|
|
113
|
-
|
|
114
110
|
/**
|
|
115
111
|
* Get nonce from directory API endpoint
|
|
116
112
|
*
|
|
@@ -130,7 +126,6 @@ class HttpClient {
|
|
|
130
126
|
return resp.headers['replay-nonce'];
|
|
131
127
|
}
|
|
132
128
|
|
|
133
|
-
|
|
134
129
|
/**
|
|
135
130
|
* Get URL for a directory resource
|
|
136
131
|
*
|
|
@@ -148,7 +143,6 @@ class HttpClient {
|
|
|
148
143
|
return this.directory[resource];
|
|
149
144
|
}
|
|
150
145
|
|
|
151
|
-
|
|
152
146
|
/**
|
|
153
147
|
* Get directory meta field
|
|
154
148
|
*
|
|
@@ -166,7 +160,6 @@ class HttpClient {
|
|
|
166
160
|
return null;
|
|
167
161
|
}
|
|
168
162
|
|
|
169
|
-
|
|
170
163
|
/**
|
|
171
164
|
* Prepare HTTP request body for signature
|
|
172
165
|
*
|
|
@@ -199,11 +192,10 @@ class HttpClient {
|
|
|
199
192
|
/* Body */
|
|
200
193
|
return {
|
|
201
194
|
payload: payload ? Buffer.from(JSON.stringify(payload)).toString('base64url') : '',
|
|
202
|
-
protected: Buffer.from(JSON.stringify(header)).toString('base64url')
|
|
195
|
+
protected: Buffer.from(JSON.stringify(header)).toString('base64url'),
|
|
203
196
|
};
|
|
204
197
|
}
|
|
205
198
|
|
|
206
|
-
|
|
207
199
|
/**
|
|
208
200
|
* Create JWS HTTP request body using HMAC
|
|
209
201
|
*
|
|
@@ -226,7 +218,6 @@ class HttpClient {
|
|
|
226
218
|
return result;
|
|
227
219
|
}
|
|
228
220
|
|
|
229
|
-
|
|
230
221
|
/**
|
|
231
222
|
* Create JWS HTTP request body using RSA or ECC
|
|
232
223
|
*
|
|
@@ -267,13 +258,12 @@ class HttpClient {
|
|
|
267
258
|
result.signature = signer.sign({
|
|
268
259
|
key: this.accountKey,
|
|
269
260
|
padding: RSA_PKCS1_PADDING,
|
|
270
|
-
dsaEncoding: 'ieee-p1363'
|
|
261
|
+
dsaEncoding: 'ieee-p1363',
|
|
271
262
|
}, 'base64url');
|
|
272
263
|
|
|
273
264
|
return result;
|
|
274
265
|
}
|
|
275
266
|
|
|
276
|
-
|
|
277
267
|
/**
|
|
278
268
|
* Signed HTTP request
|
|
279
269
|
*
|
|
@@ -309,7 +299,7 @@ class HttpClient {
|
|
|
309
299
|
const data = this.createSignedBody(url, payload, { nonce, kid });
|
|
310
300
|
const resp = await this.request(url, 'post', { data });
|
|
311
301
|
|
|
312
|
-
/* Retry on bad nonce - https://datatracker.ietf.org/doc/html/
|
|
302
|
+
/* Retry on bad nonce - https://datatracker.ietf.org/doc/html/rfc8555#section-6.5 */
|
|
313
303
|
if (resp.data && resp.data.type && (resp.status === 400) && (resp.data.type === 'urn:ietf:params:acme:error:badNonce') && (attempts < this.maxBadNonceRetries)) {
|
|
314
304
|
nonce = resp.headers['replay-nonce'] || null;
|
|
315
305
|
attempts += 1;
|
|
@@ -323,6 +313,5 @@ class HttpClient {
|
|
|
323
313
|
}
|
|
324
314
|
}
|
|
325
315
|
|
|
326
|
-
|
|
327
316
|
/* Export client */
|
|
328
317
|
module.exports = HttpClient;
|
package/src/index.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
exports.Client = require('./client');
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
/**
|
|
9
8
|
* Directory URLs
|
|
10
9
|
*/
|
|
@@ -12,18 +11,17 @@ exports.Client = require('./client');
|
|
|
12
11
|
exports.directory = {
|
|
13
12
|
buypass: {
|
|
14
13
|
staging: 'https://api.test4.buypass.no/acme/directory',
|
|
15
|
-
production: 'https://api.buypass.com/acme/directory'
|
|
14
|
+
production: 'https://api.buypass.com/acme/directory',
|
|
16
15
|
},
|
|
17
16
|
letsencrypt: {
|
|
18
17
|
staging: 'https://acme-staging-v02.api.letsencrypt.org/directory',
|
|
19
|
-
production: 'https://acme-v02.api.letsencrypt.org/directory'
|
|
18
|
+
production: 'https://acme-v02.api.letsencrypt.org/directory',
|
|
20
19
|
},
|
|
21
20
|
zerossl: {
|
|
22
|
-
production: 'https://acme.zerossl.com/v2/DV90'
|
|
23
|
-
}
|
|
21
|
+
production: 'https://acme.zerossl.com/v2/DV90',
|
|
22
|
+
},
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
|
|
27
25
|
/**
|
|
28
26
|
* Crypto
|
|
29
27
|
*/
|
|
@@ -31,14 +29,12 @@ exports.directory = {
|
|
|
31
29
|
exports.crypto = require('./crypto');
|
|
32
30
|
exports.forge = require('./crypto/forge');
|
|
33
31
|
|
|
34
|
-
|
|
35
32
|
/**
|
|
36
33
|
* Axios
|
|
37
34
|
*/
|
|
38
35
|
|
|
39
36
|
exports.axios = require('./axios');
|
|
40
37
|
|
|
41
|
-
|
|
42
38
|
/**
|
|
43
39
|
* Logger
|
|
44
40
|
*/
|
package/src/logger.js
CHANGED
|
@@ -6,7 +6,6 @@ const debug = require('debug')('acme-client');
|
|
|
6
6
|
|
|
7
7
|
let logger = () => {};
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
/**
|
|
11
10
|
* Set logger function
|
|
12
11
|
*
|
|
@@ -17,11 +16,10 @@ exports.setLogger = (fn) => {
|
|
|
17
16
|
logger = fn;
|
|
18
17
|
};
|
|
19
18
|
|
|
20
|
-
|
|
21
19
|
/**
|
|
22
20
|
* Log message
|
|
23
21
|
*
|
|
24
|
-
* @param {string} Message
|
|
22
|
+
* @param {string} msg Message
|
|
25
23
|
*/
|
|
26
24
|
|
|
27
25
|
exports.log = (msg) => {
|
package/src/util.js
CHANGED
|
@@ -7,7 +7,6 @@ const dns = require('dns').promises;
|
|
|
7
7
|
const { readCertificateInfo, splitPemChain } = require('./crypto');
|
|
8
8
|
const { log } = require('./logger');
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
/**
|
|
12
11
|
* Exponential backoff
|
|
13
12
|
*
|
|
@@ -26,7 +25,6 @@ class Backoff {
|
|
|
26
25
|
this.attempts = 0;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
|
|
30
28
|
/**
|
|
31
29
|
* Get backoff duration
|
|
32
30
|
*
|
|
@@ -40,7 +38,6 @@ class Backoff {
|
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
|
|
44
41
|
/**
|
|
45
42
|
* Retry promise
|
|
46
43
|
*
|
|
@@ -70,7 +67,6 @@ async function retryPromise(fn, attempts, backoff) {
|
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
|
|
74
70
|
/**
|
|
75
71
|
* Retry promise
|
|
76
72
|
*
|
|
@@ -87,7 +83,6 @@ function retry(fn, { attempts = 5, min = 5000, max = 30000 } = {}) {
|
|
|
87
83
|
return retryPromise(fn, attempts, backoff);
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
|
|
91
86
|
/**
|
|
92
87
|
* Parse URLs from link header
|
|
93
88
|
*
|
|
@@ -107,7 +102,6 @@ function parseLinkHeader(header, rel = 'alternate') {
|
|
|
107
102
|
return results.filter((r) => r);
|
|
108
103
|
}
|
|
109
104
|
|
|
110
|
-
|
|
111
105
|
/**
|
|
112
106
|
* Find certificate chain with preferred issuer common name
|
|
113
107
|
* - If issuer is found in multiple chains, the closest to root wins
|
|
@@ -157,7 +151,6 @@ function findCertificateChainForIssuer(chains, issuer) {
|
|
|
157
151
|
return chains[0];
|
|
158
152
|
}
|
|
159
153
|
|
|
160
|
-
|
|
161
154
|
/**
|
|
162
155
|
* Find and format error in response object
|
|
163
156
|
*
|
|
@@ -178,7 +171,6 @@ function formatResponseError(resp) {
|
|
|
178
171
|
return result.replace(/\n/g, '');
|
|
179
172
|
}
|
|
180
173
|
|
|
181
|
-
|
|
182
174
|
/**
|
|
183
175
|
* Resolve root domain name by looking for SOA record
|
|
184
176
|
*
|
|
@@ -204,7 +196,6 @@ async function resolveDomainBySoaRecord(recordName) {
|
|
|
204
196
|
}
|
|
205
197
|
}
|
|
206
198
|
|
|
207
|
-
|
|
208
199
|
/**
|
|
209
200
|
* Get DNS resolver using domains authoritative NS records
|
|
210
201
|
*
|
|
@@ -245,7 +236,6 @@ async function getAuthoritativeDnsResolver(recordName) {
|
|
|
245
236
|
return resolver;
|
|
246
237
|
}
|
|
247
238
|
|
|
248
|
-
|
|
249
239
|
/**
|
|
250
240
|
* Attempt to retrieve TLS ALPN certificate from peer
|
|
251
241
|
*
|
|
@@ -267,7 +257,7 @@ async function retrieveTlsAlpnCertificate(host, port, timeout = 30000) {
|
|
|
267
257
|
port,
|
|
268
258
|
servername: host,
|
|
269
259
|
rejectUnauthorized: false,
|
|
270
|
-
ALPNProtocols: ['acme-tls/1']
|
|
260
|
+
ALPNProtocols: ['acme-tls/1'],
|
|
271
261
|
});
|
|
272
262
|
|
|
273
263
|
socket.setTimeout(timeout);
|
|
@@ -299,7 +289,6 @@ async function retrieveTlsAlpnCertificate(host, port, timeout = 30000) {
|
|
|
299
289
|
});
|
|
300
290
|
}
|
|
301
291
|
|
|
302
|
-
|
|
303
292
|
/**
|
|
304
293
|
* Export utils
|
|
305
294
|
*/
|
|
@@ -310,5 +299,5 @@ module.exports = {
|
|
|
310
299
|
findCertificateChainForIssuer,
|
|
311
300
|
formatResponseError,
|
|
312
301
|
getAuthoritativeDnsResolver,
|
|
313
|
-
retrieveTlsAlpnCertificate
|
|
302
|
+
retrieveTlsAlpnCertificate,
|
|
314
303
|
};
|
package/src/verify.js
CHANGED
|
@@ -9,7 +9,6 @@ const axios = require('./axios');
|
|
|
9
9
|
const util = require('./util');
|
|
10
10
|
const { isAlpnCertificateAuthorizationValid } = require('./crypto');
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
/**
|
|
14
13
|
* Verify ACME HTTP challenge
|
|
15
14
|
*
|
|
@@ -43,7 +42,6 @@ async function verifyHttpChallenge(authz, challenge, keyAuthorization, suffix =
|
|
|
43
42
|
return true;
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
|
|
47
45
|
/**
|
|
48
46
|
* Walk DNS until TXT records are found
|
|
49
47
|
*/
|
|
@@ -81,7 +79,6 @@ async function walkDnsChallengeRecord(recordName, resolver = dns) {
|
|
|
81
79
|
throw new Error(`No TXT records found for name: ${recordName}`);
|
|
82
80
|
}
|
|
83
81
|
|
|
84
|
-
|
|
85
82
|
/**
|
|
86
83
|
* Verify ACME DNS challenge
|
|
87
84
|
*
|
|
@@ -121,7 +118,6 @@ async function verifyDnsChallenge(authz, challenge, keyAuthorization, prefix = '
|
|
|
121
118
|
return true;
|
|
122
119
|
}
|
|
123
120
|
|
|
124
|
-
|
|
125
121
|
/**
|
|
126
122
|
* Verify ACME TLS ALPN challenge
|
|
127
123
|
*
|
|
@@ -149,7 +145,6 @@ async function verifyTlsAlpnChallenge(authz, challenge, keyAuthorization) {
|
|
|
149
145
|
return true;
|
|
150
146
|
}
|
|
151
147
|
|
|
152
|
-
|
|
153
148
|
/**
|
|
154
149
|
* Export API
|
|
155
150
|
*/
|
|
@@ -157,5 +152,5 @@ async function verifyTlsAlpnChallenge(authz, challenge, keyAuthorization) {
|
|
|
157
152
|
module.exports = {
|
|
158
153
|
'http-01': verifyHttpChallenge,
|
|
159
154
|
'dns-01': verifyDnsChallenge,
|
|
160
|
-
'tls-alpn-01': verifyTlsAlpnChallenge
|
|
155
|
+
'tls-alpn-01': verifyTlsAlpnChallenge,
|
|
161
156
|
};
|
package/src/wait.js
ADDED
package/types/index.d.ts
CHANGED
|
@@ -15,7 +15,6 @@ export type PublicKeyString = string;
|
|
|
15
15
|
export type CertificateString = string;
|
|
16
16
|
export type CsrString = string;
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
/**
|
|
20
19
|
* Augmented ACME interfaces
|
|
21
20
|
*/
|
|
@@ -28,7 +27,6 @@ export interface Authorization extends rfc8555.Authorization {
|
|
|
28
27
|
url: string;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
|
|
32
30
|
/**
|
|
33
31
|
* Client
|
|
34
32
|
*/
|
|
@@ -80,7 +78,6 @@ export class Client {
|
|
|
80
78
|
auto(opts: ClientAutoOptions): Promise<string>;
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
|
|
84
81
|
/**
|
|
85
82
|
* Directory URLs
|
|
86
83
|
*/
|
|
@@ -99,7 +96,6 @@ export const directory: {
|
|
|
99
96
|
}
|
|
100
97
|
};
|
|
101
98
|
|
|
102
|
-
|
|
103
99
|
/**
|
|
104
100
|
* Crypto
|
|
105
101
|
*/
|
|
@@ -177,14 +173,12 @@ export interface CryptoLegacyInterface {
|
|
|
177
173
|
|
|
178
174
|
export const forge: CryptoLegacyInterface;
|
|
179
175
|
|
|
180
|
-
|
|
181
176
|
/**
|
|
182
177
|
* Axios
|
|
183
178
|
*/
|
|
184
179
|
|
|
185
180
|
export const axios: AxiosInstance;
|
|
186
181
|
|
|
187
|
-
|
|
188
182
|
/**
|
|
189
183
|
* Logger
|
|
190
184
|
*/
|
package/types/index.test-d.ts
CHANGED
package/types/rfc8555.d.ts
CHANGED
|
@@ -27,7 +27,6 @@ export interface AccountUpdateRequest {
|
|
|
27
27
|
termsOfServiceAgreed?: boolean;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
30
|
/**
|
|
32
31
|
* Order
|
|
33
32
|
*
|
|
@@ -53,7 +52,6 @@ export interface OrderCreateRequest {
|
|
|
53
52
|
notAfter?: string;
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
|
|
57
55
|
/**
|
|
58
56
|
* Authorization
|
|
59
57
|
*
|
|
@@ -73,7 +71,6 @@ export interface Identifier {
|
|
|
73
71
|
value: string;
|
|
74
72
|
}
|
|
75
73
|
|
|
76
|
-
|
|
77
74
|
/**
|
|
78
75
|
* Challenge
|
|
79
76
|
*
|
|
@@ -102,7 +99,6 @@ export interface DnsChallenge extends ChallengeAbstract {
|
|
|
102
99
|
|
|
103
100
|
export type Challenge = HttpChallenge | DnsChallenge;
|
|
104
101
|
|
|
105
|
-
|
|
106
102
|
/**
|
|
107
103
|
* Certificate
|
|
108
104
|
*
|