/* * 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); }