Skip to content

Commit

Permalink
server: fix bug with constantly reissuing certs
Browse files Browse the repository at this point in the history
  • Loading branch information
koush committed Dec 25, 2023
1 parent 441cce2 commit f6d2dc4
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 27 deletions.
2 changes: 1 addition & 1 deletion server/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"env": {
// force usage of system python because brew python is 3.11
// which has no wheels for coreml tools or tflite-runtime
"SCRYPTED_PYTHON_PATH": "/usr/bin/python3",
// "SCRYPTED_PYTHON_PATH": "/usr/bin/python3",
// "SCRYPTED_SHARED_WORKER": "true",
// "SCRYPTED_DISABLE_AUTHENTICATION": "true",
// "DEBUG": "*",
Expand Down
4 changes: 2 additions & 2 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 37 additions & 18 deletions server/src/cert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,56 @@ const { pki } = forge;


export const CURRENT_SELF_SIGNED_CERTIFICATE_VERSION = 'v2';
const SIXTY_DAYS_MS = 60 * 24 * 60 * 60 * 1000;

export function createSelfSignedCertificate(serviceKey?: string) {
let privateKey: ReturnType<typeof pki.privateKeyFromPem>;
const cert = pki.createCertificate();
export interface SelfSignedCertificate {
serviceKey: string;
certificate: string;
version: string,
};

if (serviceKey) {
privateKey = pki.privateKeyFromPem(serviceKey);
cert.publicKey = pki.rsa.setPublicKey(privateKey.n, privateKey.e);
export function createSelfSignedCertificate(existing?: SelfSignedCertificate): SelfSignedCertificate {
let serviceKey: ReturnType<typeof pki.privateKeyFromPem>;
// check if existing key is usable
if (existing?.certificate && existing?.serviceKey && existing?.version === CURRENT_SELF_SIGNED_CERTIFICATE_VERSION) {
try {
const certificate = pki.certificateFromPem(existing.certificate);
if (certificate.validity.notAfter.getTime() > Date.now() + SIXTY_DAYS_MS)
return existing;
serviceKey = pki.privateKeyFromPem(existing.serviceKey);
}
catch (e) {
}
}

const certificate = pki.createCertificate();

if (existing?.serviceKey) {
certificate.publicKey = pki.rsa.setPublicKey(serviceKey.n, serviceKey.e);
}
else {
// generate a keypair and create an X.509v3 certificate
const keys = pki.rsa.generateKeyPair(2048);
privateKey = keys.privateKey;
cert.publicKey = keys.publicKey;
serviceKey = keys.privateKey;
certificate.publicKey = keys.publicKey;
}


// NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
// Conforming CAs should ensure serialNumber is:
// - no more than 20 octets
// - non-negative (prefix a '00' if your value starts with a '1' bit)
cert.serialNumber = '01' + crypto.randomBytes(19).toString("hex"); // 1 octet = 8 bits = 1 byte = 2 hex chars
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); // adding 1 year of validity from now
certificate.serialNumber = '01' + crypto.randomBytes(19).toString("hex"); // 1 octet = 8 bits = 1 byte = 2 hex chars
certificate.validity.notBefore = new Date();
certificate.validity.notAfter = new Date();
certificate.validity.notAfter.setFullYear(certificate.validity.notBefore.getFullYear() + 5); // adding 5 years of validity from now
const attrs = [{
name: 'commonName',
value: 'localhost'
}];
cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.setExtensions([{
certificate.setSubject(attrs);
certificate.setIssuer(attrs);
certificate.setExtensions([{
name: 'basicConstraints',
cA: true
}, {
Expand Down Expand Up @@ -73,10 +92,10 @@ export function createSelfSignedCertificate(serviceKey?: string) {
}]);

// self-sign certificate
cert.sign(privateKey);
certificate.sign(serviceKey);
return {
serviceKey: pki.privateKeyToPem(privateKey),
certificate: pki.certificateToPem(cert),
serviceKey: pki.privateKeyToPem(serviceKey),
certificate: pki.certificateToPem(certificate),
version: CURRENT_SELF_SIGNED_CERTIFICATE_VERSION,
};
}
11 changes: 5 additions & 6 deletions server/src/scrypted-server-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,14 @@ async function start(mainFilename: string, options?: {

if (certSetting?.value?.version !== CURRENT_SELF_SIGNED_CERTIFICATE_VERSION) {
keyPair = createSelfSignedCertificate();

certSetting = new Settings();
certSetting._id = 'certificate';
certSetting.value = keyPair;
certSetting = await db.upsert(certSetting);
}
else {
keyPair = createSelfSignedCertificate(keyPair.serviceKey);
keyPair = createSelfSignedCertificate(keyPair);
}
certSetting = new Settings();
certSetting._id = 'certificate';
certSetting.value = keyPair;
certSetting = await db.upsert(certSetting);

const basicAuth = httpAuth.basic({
realm: 'Scrypted',
Expand Down

0 comments on commit f6d2dc4

Please sign in to comment.