var generatePem = function (keyPair) {
    var cert = forge.pki.createCertificate();

    cert.serialNumber = toPositiveHex(forge.util.bytesToHex(forge.random.getBytesSync(9))); // the serial number can be decimal or hex (if preceded by 0x)

    cert.validity.notBefore = new Date();
    cert.validity.notAfter = new Date();
    cert.validity.notAfter.setDate(cert.validity.notBefore.getDate() + (options.days || 365));

    attrs = attrs || [{
      name: 'commonName',
      value: 'example.org'
    }, {
      name: 'countryName',
      value: 'US'
    }, {
      shortName: 'ST',
      value: 'Virginia'
    }, {
      name: 'localityName',
      value: 'Blacksburg'
    }, {
      name: 'organizationName',
      value: 'Test'
    }, {
      shortName: 'OU',
      value: 'Test'
    }];

    cert.setSubject(attrs);
    cert.setIssuer(attrs);

    cert.publicKey = keyPair.publicKey;

    cert.setExtensions(options.extensions || [{
      name: 'basicConstraints',
      cA: true
    }, {
      name: 'keyUsage',
      keyCertSign: true,
      digitalSignature: true,
      nonRepudiation: true,
      keyEncipherment: true,
      dataEncipherment: true
    }, {
      name: 'subjectAltName',
      altNames: [{
        type: 6, // URI
        value: 'http://example.org/webid#me'
      }]
    }]);

    cert.sign(keyPair.privateKey, getAlgorithm(options && options.algorithm));

    var pem = {
      private: forge.pki.privateKeyToPem(keyPair.privateKey),
      public: forge.pki.publicKeyToPem(keyPair.publicKey),
      cert: forge.pki.certificateToPem(cert)
    };

    if (options && options.pkcs7) {
      var p7 = forge.pkcs7.createSignedData();
      p7.addCertificate(cert);
      pem.pkcs7 = forge.pkcs7.messageToPem(p7);
    }

    if (options && options.clientCertificate) {
      var clientkeys = forge.pki.rsa.generateKeyPair(1024);
      var clientcert = forge.pki.createCertificate();
      clientcert.serialNumber = toPositiveHex(forge.util.bytesToHex(forge.random.getBytesSync(9)));
      clientcert.validity.notBefore = new Date();
      clientcert.validity.notAfter = new Date();
      clientcert.validity.notAfter.setFullYear(clientcert.validity.notBefore.getFullYear() + 1);

      var clientAttrs = JSON.parse(JSON.stringify(attrs));

      for(var i = 0; i < clientAttrs.length; i++) {
        if(clientAttrs[i].name === 'commonName') {
          if( options.clientCertificateCN )
            clientAttrs[i] = { name: 'commonName', value: options.clientCertificateCN };
          else
            clientAttrs[i] = { name: 'commonName', value: 'John Doe jdoe123' };
        }
      }

      clientcert.setSubject(clientAttrs);

      // Set the issuer to the parent key
      clientcert.setIssuer(attrs);

      clientcert.publicKey = clientkeys.publicKey;

      // Sign client cert with root cert
      clientcert.sign(keyPair.privateKey);

      pem.clientprivate = forge.pki.privateKeyToPem(clientkeys.privateKey);
      pem.clientpublic = forge.pki.publicKeyToPem(clientkeys.publicKey);
      pem.clientcert = forge.pki.certificateToPem(clientcert);

      if (options.pkcs7) {
        var clientp7 = forge.pkcs7.createSignedData();
        clientp7.addCertificate(clientcert);
        pem.clientpkcs7 = forge.pkcs7.messageToPem(clientp7);
      }
    }

    var caStore = forge.pki.createCaStore();
    caStore.addCertificate(cert);

    try {
      forge.pki.verifyCertificateChain(caStore, [cert],
        function (vfd, depth, chain) {
          if (vfd !== true) {
            throw new Error('Certificate could not be verified.');
          }
          return true;
        });
    }
    catch(ex) {
      throw new Error(ex);
    }

    return pem;
  };
Example #2
0
exports.isValid = function (parameters, enableDebug) {
  const debug = () => {
    if (enableDebug) {
      console.error(...arguments);
    }
  };

  if (!parameters.crt) {
    debug('No certificate.');
    return false;
  }

  let certificate;
  try {
    certificate = forge.pki.certificateFromPem(parameters.crt);
  } catch (error) {
    debug('Invalid certificate.');
    return false;
  }

  // Consider that certificates expire 24h before they actually do.
  const padding = 24 * 3600 * 1000;
  const now = new Date();
  if (now.getTime() + padding >= certificate.validity.notAfter.getTime()) {
    debug('Certificate expired.');
    return false;
  }
  if (now < certificate.validity.notBefore) {
    debug('Certificate not valid yet. Or your system\'s clock is off.');
    return false;
  }

  if ('ca' in parameters) {
    try {
      const caStore = forge.pki.createCaStore(parameters.ca);
      if (!forge.pki.verifyCertificateChain(caStore, [ certificate ])) {
        debug('Certificate is not verified by the provided CA chain.');
        return false;
      }
    } catch (error) {
      debug('Problem during CA chain verification:', error);
      return false;
    }
  }

  if ('key' in parameters) {
    try {
      const privateKey = forge.pki.privateKeyFromPem(parameters.key);
      const md = forge.md.sha256.create();
      md.update('verify me', 'utf8');
      const signature = privateKey.sign(md);
      if (!certificate.publicKey.verify(md.digest().bytes(), signature)) {
        debug('Certificate doesn\'t match the provided RSA private key.');
        return false;
      }
    } catch (error) {
      debug('Problem during RSA private key verification:', error);
      return false;
    }
  }

  if ('hostname' in parameters) {
    const hostname = parameters.hostname;
    const commonName = certificate.subject.getField('CN').value;
    let altNames = [ commonName ];
    const subjectAltName = certificate.getExtension('subjectAltName');
    if (subjectAltName) {
      altNames = subjectAltName.altNames
        .filter(altName => altName.type === 2) // DNS
        .map(altName => altName.value);
    }
    if (altNames.indexOf(hostname) < 0) {
      debug('Certificate is not valid for hostname "' + hostname + '" ' +
        '(should be one of: "' + altNames.join('", "') + '").');
      return false;
    }
  }

  return true;
};
Example #3
0
exports.createCertificate = function (attrs, serial) {

// console.log('Generating 2048-bit key-pair...');
var keys = forge.pki.rsa.generateKeyPair(2048);
// console.log('Key-pair created.');

// console.log('Creating self-signed certificate...');
var cert = forge.pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = serial; // cert.serialNumber = serial + forge.util.bytesToHex(forge.random.getBytesSync(19));
// console.log("serial: " + serial);
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 20);

// needs attrs from external source

cert.setSubject(attrs);
cert.setIssuer(attrs);
cert.setExtensions([{
  name: 'subjectKeyIdentifier'
}, {
  name: 'basicConstraints',
  cA: true
}]);

// self-sign certificate
cert.sign(keys.privateKey, forge.md.sha256.create());
// console.log('Certificate created.');

// PEM-format keys and cert
var pem = {
  privateKey: forge.pki.privateKeyToPem(keys.privateKey),
  publicKey: forge.pki.publicKeyToPem(keys.publicKey),
  certificate: forge.pki.certificateToPem(cert)
};

// console.log('\nKey-Pair:');
// console.log(pem.privateKey);
// console.log(pem.publicKey);

// console.log('\nCertificate:');
// console.log(pem.certificate);

// verify certificate
var caStore = forge.pki.createCaStore();
caStore.addCertificate(cert);
try {
  forge.pki.verifyCertificateChain(caStore, [cert],
    function(vfd, depth, chain) {
      if(vfd === true) {
// console.log('SubjectKeyIdentifier verified: ' +
          cert.verifySubjectKeyIdentifier();
// console.log('Certificate verified.');
      }
      return true;
  });
} catch(ex) {
// console.log('Certificate verification failure: ' + JSON.stringify(ex, null, 2));
}
// console.log(pem);
var certClean =
[
          {"privateKey": JSON.parse(JSON.stringify(pem.privateKey).replace(/\\r\\nMI/gm, " MI").replace(/\\r\\n-----END/gm, " -----END").replace(/\\r\\n/gm, ""))},
          {"publicKey": JSON.parse(JSON.stringify(pem.publicKey).replace(/\\r\\nMI/gm, " MI").replace(/\\r\\n-----END/gm, " -----END").replace(/\\r\\n/gm, ""))},
          {"certificate": JSON.parse(JSON.stringify(pem.certificate).replace(/\\r\\nMI/gm, " MI").replace(/\\r\\n-----END/gm, " -----END").replace(/\\r\\n/gm, ""))}
          ];

var certRaw = [{"serial": cert.serialNumber}, {"privateKey": pem.privateKey}, {"publicKey": pem.publicKey}, {"certificate": pem.certificate}];

var certCooked = {};
certCooked.privateKey = pem.privateKey;
certCooked.publicKey = pem.publicKey;
certCooked.certificate = pem.certificate;

stringOut = {};
stringOut.userId = parseInt(serial, 16);
stringOut.certs = certCooked;
console.log("serial: " + serial + " Int: " + stringOut.userId);

return (stringOut);
};