"use strict";
/*
 * Copyright 2020 NEM
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ForgeCertificateService = void 0;
const forge = require("node-forge");
const node_forge_1 = require("node-forge");
const path_1 = require("path");
const BootstrapUtils_1 = require("./BootstrapUtils");
/**
 * TODO remove if not used!
 */
class ForgeCertificateService {
    constructor(params) {
        this.params = params;
    }
    async run(name) {
        // Currently the SSL certifcates are created via a docker image. Migrate this to a native forge!
        // https://www.npmjs.com/package/node-forge
        const target = `${this.params.target}/config/${name}/resources/cert`;
        await BootstrapUtils_1.BootstrapUtils.mkdir(target);
        const caKeyPair = await this.createCaCertificate(target, 'ca', `${name}-account`);
        await this.createNodeCertificate(target, 'node', name, caKeyPair);
        return { privateKey: 'a', publicKey: 'b' };
    }
    async createCaCertificate(target, prefix, name) {
        const keyPair = node_forge_1.pki.rsa.generateKeyPair();
        const publicKeyPem = node_forge_1.pki.publicKeyToPem(keyPair.publicKey);
        await BootstrapUtils_1.BootstrapUtils.writeTextFile(path_1.join(target, `${prefix}.pubkey.pem`), publicKeyPem);
        // console.log(publicKeyPem);
        const privateKeyToPem = node_forge_1.pki.privateKeyToPem(keyPair.privateKey);
        await BootstrapUtils_1.BootstrapUtils.writeTextFile(path_1.join(target, `${prefix}.key.pem`), privateKeyToPem);
        const cert = node_forge_1.pki.createCertificate();
        cert.publicKey = keyPair.publicKey;
        cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(20));
        cert.validity.notBefore = new Date();
        cert.validity.notAfter = new Date();
        cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 20);
        const attrs = [
            {
                shortName: 'CN',
                value: name,
            },
        ];
        cert.setSubject(attrs);
        cert.sign(keyPair.privateKey);
        // convert a Forge certificate to PEM
        const pemCertificate = node_forge_1.pki.certificateToPem(cert);
        await BootstrapUtils_1.BootstrapUtils.writeTextFile(path_1.join(target, `${prefix}.cert.pem`), pemCertificate);
        return keyPair;
    }
    async createNodeCertificate(target, prefix, name, caKeyPair) {
        const keypair = node_forge_1.pki.rsa.generateKeyPair();
        const publicKeyPem = node_forge_1.pki.publicKeyToPem(keypair.publicKey);
        await BootstrapUtils_1.BootstrapUtils.writeTextFile(path_1.join(target, `${prefix}.pubkey.pem`), publicKeyPem);
        // console.log(publicKeyPem);
        const privateKeyToPem = node_forge_1.pki.privateKeyToPem(keypair.privateKey);
        await BootstrapUtils_1.BootstrapUtils.writeTextFile(path_1.join(target, `${prefix}.key.pem`), privateKeyToPem);
        const cert = node_forge_1.pki.createCertificationRequest();
        cert.publicKey = keypair.publicKey;
        cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(20));
        const attrs = [
            {
                shortName: 'CN',
                value: name,
            },
        ];
        cert.setSubject(attrs);
        cert.sign(caKeyPair.privateKey);
        // convert a Forge certificate to PEM
        const pemCertificate = node_forge_1.pki.certificationRequestToPem(cert);
        await BootstrapUtils_1.BootstrapUtils.writeTextFile(path_1.join(target, `${prefix}.csr.pem`), pemCertificate);
        return { privateKey: privateKeyToPem, publicKey: publicKeyPem };
    }
    createCertCommands(target) {
        return `
cd ${target}
set -e
mkdir new_certs && chmod 700 new_certs
touch index.txt

# create CA key
openssl genpkey -out ca.key.pem -outform PEM -algorithm ed25519
openssl pkey -inform pem -in ca.key.pem -text -noout
openssl pkey -in ca.key.pem -pubout -out ca.pubkey.pem

# create CA cert and self-sign it
openssl req -config ca.cnf -keyform PEM -key ca.key.pem -new -x509 -days 7300 -out ca.cert.pem
openssl x509 -in ca.cert.pem  -text -noout

# create node key
openssl genpkey -out node.key.pem -outform PEM -algorithm ed25519
openssl pkey -inform pem -in node.key.pem -text -noout

# create request
openssl req -config node.cnf -key node.key.pem -new -out node.csr.pem
openssl req  -text -noout -verify -in node.csr.pem

### below is done after files are written
# CA side
# create serial
openssl rand -hex 19 > ./serial.dat

# sign cert for 375 days
openssl ca -batch -config ca.cnf -days 375 -notext -in node.csr.pem -out node.crt.pem
openssl verify -CAfile ca.cert.pem node.crt.pem

# finally create full crt
cat node.crt.pem ca.cert.pem > node.full.crt.pem
`;
    }
}
exports.ForgeCertificateService = ForgeCertificateService;
