/*
* Copyright 2018 Scytl Secure Electronic Voting SA
*
* All rights reserved
*
* See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
*/
/* jshint node:true */
'use strict';
var BasicConstraints = require('./basic-constraints');
var KeyUsageExtension = require('./key-usage-extension');
var validator = require('./input-validator');
var constants = require('./constants');
var forge = require('node-forge');
module.exports = X509Certificate;
/**
* @class X509Certificate
* @classdesc Encapsulates an X.509 certificate. To instantiate this object, use
* the method {@link CertificateService.newX509Certificate}.
* @property {string} publicKey The public key of the certificate, in PEM
* format.
* @property {Date} notBefore The starting time of the certificate's validity.
* @property {Date} notAfter The ending time of the certificate's validity.
* @property {string} serialNumber The serial number of the certificate.
* @property {string} subjectCommonName The subject common name of the
* certificate.
* @property {string} subjectOrganizationalUnit The subject organizational unit
* of the certificate.
* @property {string} subjectOrganization The subject organization of the
* certificate.
* @property {string} subjectLocality The subject locality of the certificate.
* @property {string} subjectCountry The subject country of the certificate.
* @property {string} issuerCommonName The issuer common name of the
* certificate.
* @property {string} issuerOrganizationalUnit The issuer organizational unit of
* the certificate.
* @property {string} issuerOrganization The issuer organization of the
* certificate.
* @property {string} issuerLocality The issuer locality of the certificate.
* @property {string} issuerCountry The issuer country of the certificate.
* @property {BasicConstraints} basicConstraints The basic constraints of the
* certificate.
* @property {KeyUsageExtension} keyUsageExtension The key usage extension of
* the certificate.
*/
function X509Certificate(certificate) {
var forgeCertificate_ = forge.pki.certificateFromPem(certificate, true);
validator.checkIsDefinedAndNotNull(
forgeCertificate_.publicKey, 'Public key of certificate');
this.publicKey = forge.pki.publicKeyToPem(forgeCertificate_.publicKey, 64);
validator.checkIsDefinedAndNotNull(
forgeCertificate_.validity.notBefore,
'Starting time of validity of certificate');
this.notBefore = forgeCertificate_.validity.notBefore;
validator.checkIsDefinedAndNotNull(
forgeCertificate_.validity.notAfter,
'Ending time of validity of certificate');
this.notAfter = forgeCertificate_.validity.notAfter;
this.serialNumber = forgeCertificate_.serialNumber;
if (!this.serialNumber) {
this.serialNumber = '';
}
var field = forgeCertificate_.subject.getField({name: 'commonName'});
this.subjectCommonName = (field) ? field.value : '';
field = forgeCertificate_.subject.getField({shortName: 'OU'});
this.subjectOrganizationalUnit = (field) ? field.value : '';
field = forgeCertificate_.subject.getField({name: 'organizationName'});
this.subjectOrganization = (field) ? field.value : '';
field = forgeCertificate_.subject.getField({name: 'localityName'});
this.subjectLocality = (field) ? field.value : '';
field = forgeCertificate_.subject.getField({name: 'countryName'});
this.subjectCountry = (field) ? field.value : '';
field = forgeCertificate_.issuer.getField({name: 'commonName'});
this.issuerCommonName = (field) ? field.value : '';
field = forgeCertificate_.issuer.getField({shortName: 'OU'});
this.issuerOrganizationalUnit = (field) ? field.value : '';
field = forgeCertificate_.issuer.getField({name: 'organizationName'});
this.issuerOrganization = (field) ? field.value : '';
field = forgeCertificate_.issuer.getField({name: 'localityName'});
this.issuerLocality = (field) ? field.value : '';
field = forgeCertificate_.issuer.getField({name: 'countryName'});
this.issuerCountry = (field) ? field.value : '';
var constraints = forgeCertificate_.getExtension({name: 'basicConstraints'});
this.basicConstraints =
(constraints) ? new BasicConstraints(constraints) : null;
var extension = forgeCertificate_.getExtension({name: 'keyUsage'});
this.keyUsageExtension =
(extension) ? new KeyUsageExtension(extension) : null;
/**
* Verifies that the certificate provided as input was signed by this
* certificate.
*
* @function verify
* @memberof X509Certificate
* @param {string}
* certificate The certificate whose signature is to be verified,
* in PEM format.
* @returns {boolean} true
if the certificate provided as
* input was signed by this certificate, false
* otherwise.
* @throws {Error}
* If the input data validation fails.
*/
this.verify = function(certificate) {
validator.checkIsNonEmptyString(
certificate,
'Certificate, in PEM format, containing signature to be verified');
return forgeCertificate_.verify(forge.pki.certificateFromPem(certificate));
};
/**
* Serializes this certificate into its PEM string representation.
*
* @function toPem
* @memberof X509Certificate
* @returns {string} The PEM string representation of this certificate.
*/
this.toPem = function() {
return forge.pki.certificateToPem(
forgeCertificate_, constants.PEM_LINE_LENGTH);
};
return Object.freeze(this);
}