mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
101 lines
2.8 KiB
JavaScript
101 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
require('reflect-metadata');
|
|
|
|
const { randomBytes, webcrypto } = require('node:crypto');
|
|
const {
|
|
BasicConstraintsExtension,
|
|
ExtendedKeyUsage,
|
|
ExtendedKeyUsageExtension,
|
|
KeyUsageFlags,
|
|
KeyUsagesExtension,
|
|
Pkcs10CertificateRequest,
|
|
SubjectKeyIdentifierExtension,
|
|
X509CertificateGenerator,
|
|
} = require('@peculiar/x509');
|
|
|
|
const algorithm = Object.freeze({
|
|
name: 'ECDSA',
|
|
namedCurve: 'P-256',
|
|
hash: 'SHA-256',
|
|
});
|
|
|
|
async function createCertificateAuthority(options = {}) {
|
|
const now = options.now ?? Date.now();
|
|
const keys = await webcrypto.subtle.generateKey(algorithm, true, [
|
|
'sign',
|
|
'verify',
|
|
]);
|
|
const name = 'CN=QingLong Worker Test CA';
|
|
const certificate = await X509CertificateGenerator.createSelfSigned(
|
|
{
|
|
serialNumber: randomBytes(16).toString('hex'),
|
|
name,
|
|
notBefore: new Date(now - 60_000),
|
|
notAfter: new Date(now + 365 * 24 * 60 * 60_000),
|
|
signingAlgorithm: algorithm,
|
|
keys,
|
|
extensions: [
|
|
new BasicConstraintsExtension(true, 1, true),
|
|
new KeyUsagesExtension(
|
|
KeyUsageFlags.keyCertSign | KeyUsageFlags.cRLSign,
|
|
true,
|
|
),
|
|
await SubjectKeyIdentifierExtension.create(
|
|
keys.publicKey,
|
|
false,
|
|
webcrypto,
|
|
),
|
|
],
|
|
},
|
|
webcrypto,
|
|
);
|
|
|
|
return Object.freeze({
|
|
certificatePem: certificate.toString('pem'),
|
|
async issue(certificateSigningRequestPem, issueOptions = {}) {
|
|
const request = new Pkcs10CertificateRequest(
|
|
certificateSigningRequestPem,
|
|
);
|
|
if (!(await request.verify(webcrypto))) {
|
|
throw new Error('test CSR signature is invalid');
|
|
}
|
|
const notBeforeMs = issueOptions.notBeforeMs ?? now - 60_000;
|
|
const notAfterMs = issueOptions.notAfterMs ?? now + 30 * 24 * 60 * 60_000;
|
|
const extensions = [
|
|
new BasicConstraintsExtension(false, undefined, true),
|
|
new KeyUsagesExtension(KeyUsageFlags.digitalSignature, true),
|
|
await SubjectKeyIdentifierExtension.create(
|
|
request.publicKey,
|
|
false,
|
|
webcrypto,
|
|
),
|
|
];
|
|
if (issueOptions.clientAuth !== false) {
|
|
extensions.splice(
|
|
1,
|
|
0,
|
|
new ExtendedKeyUsageExtension([ExtendedKeyUsage.clientAuth], true),
|
|
);
|
|
}
|
|
const leaf = await X509CertificateGenerator.create(
|
|
{
|
|
serialNumber: randomBytes(16).toString('hex'),
|
|
subject: request.subject,
|
|
issuer: name,
|
|
notBefore: new Date(notBeforeMs),
|
|
notAfter: new Date(notAfterMs),
|
|
signingAlgorithm: algorithm,
|
|
publicKey: request.publicKey,
|
|
signingKey: keys.privateKey,
|
|
extensions,
|
|
},
|
|
webcrypto,
|
|
);
|
|
return leaf.toString('pem');
|
|
},
|
|
});
|
|
}
|
|
|
|
module.exports = { createCertificateAuthority };
|