Skip to content
Snippets Groups Projects
viamapi-iframe.js 89.3 KiB
Newer Older
import {createDeviceHash} from '../utilities/appUtility';

const libmime = require('libmime');
const QRCode = require('qrcode');
const pkijs = require('pkijs');
const asn1js = require('asn1js');
const pvutils = require('pvutils');
const Penpal = require('penpal').default;
const penpalMethods = require('../../temp/penpal-methods').default;
const WopiAPI = require('./wopiapi-iframe');
const ViamAPI = require('../../temp/viamapi');
//*********************************************************************************

const CERTIFIATE_Version_1 = 0;
const CERTIFIATE_Version_3 = 2;

//these bit fields are reversed, WTF!
const KEY_USAGE_DigitalSignature	= 0x80;//01;
const KEY_USAGE_NonRepudiation		= 0x40;//02;
const KEY_USAGE_KeyEncipherment		= 0x20;//04;
const KEY_USAGE_DataEncipherment	= 0x10;//08;
const KEY_USAGE_KeyAgreement		= 0x08;//10;
const KEY_USAGE_KeyCertSign			= 0x04;//20;
const KEY_USAGE_CRLSign				= 0x02;//40;
//const KEY_USAGE_EncipherOnly		= 0x01;//80; // Not used for now. Must be used together with KEY_USAGE_KeyAgreement (maybe should be ORed as a constant directly?)
//const KEY_USAGE_DecipherOnly		= 0x80;//0100; // If used, modify "KeyUsage" extension array buffer size and appropriate bit operators to accomodate for extra byte

const KEY_USAGE_LeafCertificate		= KEY_USAGE_DigitalSignature | KEY_USAGE_NonRepudiation | KEY_USAGE_KeyEncipherment | KEY_USAGE_DataEncipherment;
const KEY_USAGE_CertificateAuthority= KEY_USAGE_DigitalSignature | KEY_USAGE_KeyCertSign | KEY_USAGE_CRLSign;


const OID_EXT_KEY_USAGE_Any     	= "2.5.29.37.0";
const OID_ID_PKIX_ServerAuth		= "1.3.6.1.5.5.7.3.1";
const OID_ID_PKIX_ClientAuth		= "1.3.6.1.5.5.7.3.2";
const OID_ID_PKIX_CodeSigning		= "1.3.6.1.5.5.7.3.3";
const OID_ID_PKIX_EmailProtection	= "1.3.6.1.5.5.7.3.4";
const OID_ID_PKIX_TimeStamping	    = "1.3.6.1.5.5.7.3.8";
const OID_ID_PKIX_OCSPSigning		= "1.3.6.1.5.5.7.3.9";
// const OID_EXT_KEY_USAGE_MS...	= "1.3.6.1.4.1.311.10.3.1"; // Microsoft Certificate Trust List signing
// const OID_EXT_KEY_USAGE_MS...	= "1.3.6.1.4.1.311.10.3.4";  // Microsoft Encrypted File System
const OID_PKCS7_Data                = "1.2.840.113549.1.7.1";
const OID_PKCS7_SignedData          = "1.2.840.113549.1.7.2";
const OID_PKCS7_EnvelopedData       = "1.2.840.113549.1.7.3";
const OID_PKCS9_EmailAddress        = "1.2.840.113549.1.9.1";
const OID_PKCS9_ContentType         = "1.2.840.113549.1.9.3";
const OID_PKCS9_MessageDigest       = "1.2.840.113549.1.9.4";
Markin Igor's avatar
Markin Igor committed
const OID_PKCS9_SigningTime         = "1.2.840.113549.1.9.5";

const defaultAlgorithms = {
  hashAlg: "SHA-256",
  signAlg: "RSASSA-PKCS1-v1_5",
  keyLength: 2048
Markin Igor's avatar
Markin Igor committed
};

const AES_encryptionVariant_Password  = 2;
const encryptionAlgorithm = {
  name: "AES-CBC",
  length: 128
};

//*********************************************************************************
// Returns promise, resolved to keyPair object {publicKey, privateKey}
//*********************************************************************************
function generateKeys(algorithms) {
  //region Get a "crypto" extension
  const crypto = pkijs.getCrypto();
  if (typeof crypto === "undefined") {
    return Promise.reject("No WebCrypto extension found");
  }
  //endregion Get a "crypto" extension

  if (!algorithms) {
    algorithms = defaultAlgorithms;
  } else {
    if (!algorithms.hashAlg) {
      algorithms.hashAlg = defaultAlgorithms.hashAlg;
    }
    if (!algorithms.signAlg) {
      algorithms.signAlg = defaultAlgorithms.signAlg;
    }
    if (!algorithms.keyLength) {
      algorithms.keyLength = defaultAlgorithms.keyLength;
    }
  }

  //region Get default algorithm parameters for key generation
  const algorithm = pkijs.getAlgorithmParameters(algorithms.signAlg, "generatekey");
  if("hash" in algorithm.algorithm) {
    algorithm.algorithm.hash.name = algorithms.hashAlg;
  }
  algorithm.algorithm.modulusLength = algorithms.keyLength;
  //endregion

  return crypto.generateKey(algorithm.algorithm, true, algorithm.usages);
}

//*********************************************************************************
function createCertificate(certData, issuerData = null)
{

  if (typeof certData === "undefined") {
    return Promise.reject("No Certificate data provided");
  }

  if (typeof certData.subject === "undefined") {
    return Promise.reject("No Certificate subject data provided");
  }


  //region Get a "crypto" extension
  const crypto = pkijs.getCrypto();

  if (typeof crypto === "undefined") {
    return Promise.reject("No WebCrypto extension found");
  }
  //endregion Get a "crypto" extension

  //region Initial variables
  let sequence = Promise.resolve();

  const certificate = new pkijs.Certificate();
  let publicKey;
  let privateKey;

  let certificateBuffer;// = new ArrayBuffer(0); // ArrayBuffer with loaded or created CERT
  let privateKeyBuffer;// = new ArrayBuffer(0);
  let publicKeyBuffer;// = new ArrayBuffer(0);

  //endregion Initial variables

  if (certData.keyPair) {
    //region Create a new key pair
    sequence = sequence.then(() =>
    {
      return certData.keyPair;
    });
    //endregion Create a new key pair

  } else {
    //region Create a new key pair
    sequence = sequence.then(() =>
    {
      return generateKeys(certData.algorithms);
    });
    //endregion Create a new key pair
  }

  //region Store new key in an interim variables
  sequence = sequence.then(keyPair =>
  {
    publicKey = keyPair.publicKey;
    privateKey = keyPair.privateKey;
  }, error => Promise.reject(`Error during key generation: ${error}`));
  //endregion Store new key in an interim variables

  //region Exporting public key into "subjectPublicKeyInfo" value of certificate
  sequence = sequence.then(() =>
    certificate.subjectPublicKeyInfo.importKey(publicKey)
  );
  //endregion Exporting public key into "subjectPublicKeyInfo" value of certificate

  sequence = sequence.then(
    () => crypto.digest({ name: "SHA-1" }, certificate.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex),
    error => Promise.reject(`Error during importing public key: ${error}`)
  );

  //region Fill in cert data
  sequence = sequence.then(subjKeyIdBuffer =>
  {

    //region Put a static values
    certificate.version = CERTIFIATE_Version_3;

    const serialNumberBuffer = new ArrayBuffer(20);
    const serialNumberView = new Uint8Array(serialNumberBuffer);
Markin Igor's avatar
Markin Igor committed
    pkijs.getRandomValues(serialNumberView);
    // noinspection JSUnresolvedFunction
    certificate.serialNumber = new asn1js.Integer({ valueHex: serialNumberView });
    //endregion Put a static values

    //region Subject
    // For reference http://oidref.com/2.5.4.3
    if (certData.subject.commonName) {
      // noinspection JSUnresolvedFunction
      certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
        type: "2.5.4.3", // Common name
        value: new asn1js.PrintableString({ value: certData.subject.commonName })
      }));
    }

    if (certData.subject.country) {
      // noinspection JSUnresolvedFunction
      certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
        type: "2.5.4.6", // Country name
        value: new asn1js.PrintableString({ value: certData.subject.country })
      }));
    }

    if (certData.subject.locality) {
      // noinspection JSUnresolvedFunction
      certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
        type: "2.5.4.7", // Locality Name
        value: new asn1js.PrintableString({ value: certData.subject.locality })
      }));
    }

    if (certData.subject.state) {
      // noinspection JSUnresolvedFunction
      certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
        type: "2.5.4.8", // State or Province name
        value: new asn1js.PrintableString({ value: certData.subject.state })
      }));
    }

    if (certData.subject.organization) {
      // noinspection JSUnresolvedFunction
      certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
        type: "2.5.4.10", // Organization name
        value: new asn1js.PrintableString({ value: certData.subject.organization })
      }));
    }

    if (certData.subject.organizationUnit) {
      // noinspection JSUnresolvedFunction
      certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
        type: "2.5.4.11", // Organization unit name
        value: new asn1js.PrintableString({ value: certData.subject.organizationUnit })
      }));
    }

    if (certData.subject.email) {
      // noinspection JSUnresolvedFunction
      certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
        type: OID_PKCS9_EmailAddress, // Email, deprecated but still widely used
        value: new asn1js.IA5String({ value: certData.subject.email })
      }));
    }
    //endregion Subject


    //region Issuer
    if (issuerData && issuerData.certificate) {
      certificate.issuer = issuerData.certificate.subject;
    } else {
      certificate.issuer = certificate.subject;
    }
    //endregion Issuer

    //region Validity
    if (!certData.validity) {
      certData.validity = {}
    }

    if (certData.validity.notBefore) {
      certificate.notBefore.value = certData.validity.notBefore; //date
    } else {
      const tmp = new Date();
      certificate.notBefore.value = new Date(tmp.getFullYear(), tmp.getMonth(), tmp.getDate(), 0, 0, 0);
    }

    if (certData.validity.notAfter) {
      certificate.notAfter.value = certData.validity.notAfter; //date
    } else {
      const tmp = certificate.notBefore.value;
      const validYears = certData.validity.validYears || 1;
      certificate.notAfter.value = new Date(tmp.getFullYear() + validYears, tmp.getMonth(), tmp.getDate(), 23, 59, 59);
    }
    //endregion Validity

    //region Extensions
    certificate.extensions = []; // Extensions are not a part of certificate by default, it's an optional array

    //region "BasicConstraints" extension
    const basicConstr = new pkijs.BasicConstraints({
      cA: !!certData.isCA,
      //pathLenConstraint: 0 //TODO add logic for leaf CA
    });

    certificate.extensions.push(new pkijs.Extension({
      extnID: "2.5.29.19",
      critical: true,
      extnValue: basicConstr.toSchema().toBER(false),
      parsedValue: basicConstr // Parsed value for well-known extensions
    }));
    //endregion "BasicConstraints" extension

    //region "KeyUsage" extension
    const keyUsageBuffer = new ArrayBuffer(1);
    const keyUsageBitView = new Uint8Array(keyUsageBuffer);

    keyUsageBitView[0] = !!certData.isCA ? KEY_USAGE_CertificateAuthority : KEY_USAGE_LeafCertificate;

    // noinspection JSUnresolvedFunction
    const keyUsage = new asn1js.BitString({ valueHex: keyUsageBuffer });

    certificate.extensions.push(new pkijs.Extension({
      extnID: "2.5.29.15",
      critical: true,
      extnValue: keyUsage.toBER(false),
      parsedValue: keyUsage // Parsed value for well-known extensions
    }));
    //endregion "KeyUsage" extension

    //region "ExtKeyUsage" extension
    if (!certData.isCA && certData.subject.email) {
      const extKeyUsage = new pkijs.ExtKeyUsage({
        keyPurposes: [
          OID_ID_PKIX_EmailProtection
        ]
      });

      certificate.extensions.push(new pkijs.Extension({
        extnID: "2.5.29.37",
        critical: false,
        extnValue: extKeyUsage.toSchema().toBER(false),
        parsedValue: extKeyUsage // Parsed value for well-known extensions
      }));
    }
    //endregion "ExtKeyUsage" extension

    //region "SubjAltName" extension
    if (certData.subject.email || certData.subject.url) {

      const names = [];

      if (certData.subject.email) {
        names.push(new pkijs.GeneralName({
          type: 1, // rfc822Name
          value: certData.subject.email
        }));
      }

      if (certData.subject.url) {
        names.push(new pkijs.GeneralName({
          type: 2, // dNSName
          value: certData.subject.url
        }));
      }

      const subjAltNames = new pkijs.GeneralNames({
        names: names
      });

      certificate.extensions.push(new pkijs.Extension({
        extnID: "2.5.29.17",
        critical: false,
        extnValue: subjAltNames.toSchema().toBER(false),
        parsedValue: subjAltNames // Parsed value for well-known extensions
      }));
    }
    //endregion "SubjAltName" extension


    //region "SubjectKeyIdentifier" extension
    const subjKeyId = new asn1js.OctetString({ valueHex: subjKeyIdBuffer });

    certificate.extensions.push(new pkijs.Extension({
      extnID: "2.5.29.14",
      critical: false,
      extnValue: subjKeyId.toBER(false),
      parsedValue: subjKeyId // Parsed value for well-known extensions
    }));
    //endregion "SubjectKeyIdentifier" extension

    /* COULD NOT GET IT WORKING
        //region "AuthorityKeyIdentifier" extension
        if (issuerData && issuerData.certificate) {

          let issuerSubjKeyExt = null;

          let extLength = issuerData.certificate.extensions.length;
          for (var i = 0; i < extLength; i++) {
            let ext = issuerData.certificate.extensions[i];
            if (ext.extnID == "2.5.29.14") {
              issuerSubjKeyExt = ext;
              break;
            }
          }

          if (issuerSubjKeyExt) {

            const asn1 = asn1js.fromBER(issuerSubjKeyExt.extnValue);

            const authKeyIdentifier = new AuthorityKeyIdentifier({
              keyIdentifier: new asn1js.OctetString({
                //isHexOnly: true,
                //valueHex: issuerSubjKeyExt.parsedValue.valueBlock.valueHex
                value: new asn1js.OctetString({ valueHex: subjKeyIdBuffer })
              })
            });
            // const authKeyIdentifier = new AuthorityKeyIdentifier({
            // 	//keyIdentifier: new asn1js.OctetString({ valueHex: subjKeyIdBuffer })

            // });

            certificate.extensions.push(new Extension({
              extnID: "2.5.29.35",
              critical: false,
              extnValue: authKeyIdentifier.toSchema().toBER(false),
              parsedValue: authKeyIdentifier // Parsed value for well-known extensions
            }));
          }
        }
        //endregion "AuthorityKeyIdentifier" extension
    */
    //endregion Extensions
  });
  //region Fill in cert data


  //region Signing final certificate
  sequence = sequence.then(() => {
      let signerKey = (issuerData && issuerData.privateKey) ? issuerData.privateKey : privateKey;
      //console.log(signerKey)
      return certificate.sign(signerKey, (certData.algorithms && certData.algorithms.hashAlg) ? certData.algorithms.hashAlg : defaultAlgorithms.hashAlg)
    },
    error => Promise.reject(`Error during exporting public key: ${error}`));
  //endregion

  //region Encode and store certificate
  sequence = sequence.then(() =>
  {
    //console.log(certificate)
    certificateBuffer = certificate.toSchema(true).toBER(false);
  }, error => Promise.reject(`Error during signing: ${error}`));
  //endregion

  //region Exporting public key
  sequence = sequence.then(() =>
    crypto.exportKey("spki", publicKey)
  );
  //endregion

  //region Store exported public key on Web page
  sequence = sequence.then(result =>
  {
    publicKeyBuffer = result;
  }, error => Promise.reject(`Error during exporting of public key: ${error}`));
  //endregion

  //region Exporting private key
  sequence = sequence.then(() =>
    crypto.exportKey("pkcs8", privateKey)
  );
  //endregion

  //region Store exported key on Web page
  sequence = sequence.then(result =>
  {
    privateKeyBuffer = result;
  }, error => Promise.reject(`Error during exporting of private key: ${error}`));
  //endregion

  return sequence.then(() => {

    const result = {
      certificate: certificate,
      certificatePEM: encodePEM(certificateBuffer, "CERTIFICATE"),
      publicKey: publicKey,
      publicKeyPEM: encodePEM(publicKeyBuffer, "PUBLIC KEY"),
      privateKey: privateKey,
      privateKeyPEM: encodePEM(privateKeyBuffer, "PRIVATE KEY")
Markin Igor's avatar
Markin Igor committed
    };
    return result;
  });
}

function formatPEM(pemString) {
  const lineWidth = 64;
  let resultString = "";
  let start = 0;
  let piece;
  while ((piece = pemString.substring(start, start + lineWidth)).length > 0) {
    start += lineWidth;
    resultString += piece + '\r\n';
  }
  return resultString;
}

function encodePEM(buffer, label) {
  const bufferString = String.fromCharCode.apply(null, new Uint8Array(buffer));

  const header = `-----BEGIN ${label}-----\r\n`;
  const base64formatted = formatPEM(window.btoa(bufferString));
  const footer = `-----END ${label}-----\r\n`;
  const resultString = header + base64formatted + footer;

  return resultString;
}

function decodePEM(pemString) {
  const pemStripped = pemString.replace(/(-----(BEGIN|END) [a-zA-Z ]*-----|\r|\n)/g, '');
  const pemDecoded = window.atob(pemStripped);
  const buffer = pvutils.stringToArrayBuffer(pemDecoded);
  return buffer;
}

//*********************************************************************************
function parseCertificate(certificatePEM) {
  const certificateBuffer = decodePEM(certificatePEM);
  const asn1 = asn1js.fromBER(certificateBuffer);
  const certificate = new pkijs.Certificate({ schema: asn1.result });
  return certificate;
}

//*********************************************************************************
function parsePublicKey(publicKeyPEM) {
  const publicKeyBuffer = decodePEM(publicKeyPEM);
  const crypto = pkijs.getCrypto();
  const publicKeyPromise = crypto.importKey(
    "spki",
    publicKeyBuffer,
    {   //these are the algorithm options
      name: "RSASSA-PKCS1-v1_5",
      hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
    },
    true,
    ["verify"]
  );
  return publicKeyPromise;
}

//*********************************************************************************
function encryptMessage(message, password, label) {
  const buffer = pvutils.stringToArrayBuffer(message);
  const secret = pvutils.stringToArrayBuffer(password);

  const enveloped = new pkijs.EnvelopedData();
  enveloped.addRecipientByPreDefinedData(secret, {}, AES_encryptionVariant_Password);
  return enveloped.encrypt(encryptionAlgorithm, buffer).
  then(
    () => {
      const content = new pkijs.ContentInfo();
      content.contentType = OID_PKCS7_EnvelopedData;
      content.content = enveloped.toSchema();
      const ber = content.toSchema().toBER(false);
      return encodePEM(ber, label)
    },
    error => Promise.reject(`encryption error: ${error}`)
  )
}

//*********************************************************************************
function decryptMessage(message, password) {
  if (canTryPincode()) {
    const secret = pvutils.stringToArrayBuffer(password);
    const buffer = decodePEM(message);

    const asn1 = asn1js.fromBER(buffer);
    const content = new pkijs.ContentInfo({schema: asn1.result});
    const enveloped = new pkijs.EnvelopedData({schema: content.content});
    return enveloped.decrypt(0, {preDefinedData: secret}).then(result => {
      return pvutils.arrayBufferToString(result);
    }).catch(() => {
      return Promise.reject(failPincodeAttempt(password));
Olgun Cengiz's avatar
Olgun Cengiz committed
    return Promise.reject(getTimeLeftInLocalStorage());
  }
}

//*********************************************************************************
function getBlockFinishTimeInLocalStorage() {
Olgun Cengiz's avatar
Olgun Cengiz committed
  return localStorage.getItem("blockFinishTime") || getCurrentTime();
}

function getCurrentTime() {
  return Math.floor(new Date().getTime() / 1000);
}

function getTimeLeftInLocalStorage() {
  const blockFinishTime = getBlockFinishTimeInLocalStorage();
  const timeNow = getCurrentTime();
  const seconds = (blockFinishTime - timeNow) % 60;
  let minutes = Math.floor((blockFinishTime - timeNow) / 60);
  minutes %= 60;

  const left = "Your identity has been blocked. Try again in " + minutes + " minutes and " + seconds + " seconds.";
  return left;
}

function failPincodeAttempt(password) {
  let message = "Wrong pincode";
  if (password !== '00000000') {
    let attempt = localStorage.getItem("attempt") || 1;
    attempt = parseInt(attempt);
    if (attempt === 9) {
Olgun Cengiz's avatar
Olgun Cengiz committed
      const identitiesTemp = listIdentitiesFromLocalStorage();
      for(let i in identitiesTemp) {
        destroyIdentityFromLocalStorage(i);
      }
      message = "9 failed attempts. Identity is revoked!";
      localStorage.removeItem("attempt");
    } else if (attempt % 3 === 0) {
      const timeNow = getCurrentTime();
Olgun Cengiz's avatar
Olgun Cengiz committed
      const blockFinishTime = timeNow + 300;
      localStorage.setItem("blockFinishTime", blockFinishTime);
      localStorage.setItem("attempt", attempt + 1);
      message = "3 failed attempts. Identity is blocked!";
    } else {
      localStorage.setItem("attempt", attempt + 1);
    }
  }
Olgun Cengiz's avatar
Olgun Cengiz committed
  return message;
}

function canTryPincode() {
  const timeNow = getCurrentTime();
Olgun Cengiz's avatar
Olgun Cengiz committed
  const blockFinishTime = getBlockFinishTimeInLocalStorage();
  if (blockFinishTime <= timeNow) {
    localStorage.removeItem("blockFinishTime");
    return true;
  } else {
    return false;
  }
}

//*********************************************************************************
function parsePrivateKey(privateKeyPEM) {
  const privateKeyBuffer = decodePEM(privateKeyPEM);
  const crypto = pkijs.getCrypto();
  const privateKeyPromise = crypto.importKey(
    "pkcs8",
    privateKeyBuffer,
    {   //these are the algorithm options
      name: "RSASSA-PKCS1-v1_5",
      hash: {name: "SHA-256"}, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
    },
    true,
    ["sign"]
  );
  return privateKeyPromise;
}


function createPassportCertificate(commonNameArg) {
  const certData = {
    algorithms: {
      hashAlg: "SHA-256",
      signAlg: "RSASSA-PKCS1-v1_5",
      keyLength: 2048
    },
    //keyPair: generateKeys(), //optional , if provided must be object or promise that resolves to object {publicKey, prvateKey}. If it is not provided, new ones are generated automatically
    subject: {
      commonName: commonNameArg + "-userdevice", //optional for leaf, recommended for CA
      country: "CH", //optional for leaf, recommended for CA
      locality: "Zug", //optional for leaf, recommended for CA
      state: "Zug", //optional for leaf, recommended for CA
      organization: "Vereign AG", //optional for leaf, recommended for CA
      organizationUnit:"Business Dep", //optional for leaf, recommended for CA
      //email: "damyan.mitev@vereign.com", // added to DN and Subject Alternative Name extension. Optional for CA. Mandatory for leaf certificate, used for email protection
      //url: "www.vereign.com" // optional url, recommended for CA, added to Subject Alternative Name extension
    },
    validity: {
      //notBefore: new Date() // optional, defaults to today at 00:00:00
      //notAfter: new Date()  // optional, defaults to notBefore + validYears at 23:59:59
      validYears: 5 //optional, defaults to 1
    },
    isCA: true // optional flag denoting if this is CA certificate or leaf certificate, defaults to false
Markin Igor's avatar
Markin Igor committed
  };

  return createCertificate(certData, null)
}

function createOneTimePassportCertificate(commonNameArg, emailArg, privateKeyIssuerArg, certicateIssuerArg) {
Markin Igor's avatar
Markin Igor committed
  var certData = null;
Markin Igor's avatar
Markin Igor committed
  if(emailArg != null && emailArg !== "") {
    certData = {
      algorithms: {
        hashAlg: "SHA-256",
        signAlg: "RSASSA-PKCS1-v1_5",
        keyLength: 2048
      },
      //keyPair: generateKeys(), //optional , if provided must be object or promise that resolves to object {publicKey, prvateKey}. If it is not provided, new ones are generated automatically
      subject: {
        commonName: commonNameArg + "-onetime", //optional for leaf, recommended for CA
        country: "CH", //optional for leaf, recommended for CA
        locality: "Zug", //optional for leaf, recommended for CA
        state: "Zug", //optional for leaf, recommended for CA
        organization: "Vereign AG", //optional for leaf, recommended for CA
        organizationUnit:"Business Dep", //optional for leaf, recommended for CA
        email: emailArg, // added to DN and Subject Alternative Name extension. Optional for CA. Mandatory for leaf certificate, used for email protection
        //url: "www.vereign.com" // optional url, recommended for CA, added to Subject Alternative Name extension
      },
      validity: {
        //notBefore: new Date() // optional, defaults to today at 00:00:00
        //notAfter: new Date()  // optional, defaults to notBefore + validYears at 23:59:59
        validYears: 5 //optional, defaults to 1
      },
      isCA: false // optional flag denoting if this is CA certificate or leaf certificate, defaults to false
    }
  } else {
    certData = {
      algorithms: {
        hashAlg: "SHA-256",
        signAlg: "RSASSA-PKCS1-v1_5",
        keyLength: 2048
      },
      //keyPair: generateKeys(), //optional , if provided must be object or promise that resolves to object {publicKey, prvateKey}. If it is not provided, new ones are generated automatically
      subject: {
        commonName: commonNameArg + "-onetime", //optional for leaf, recommended for CA
        country: "CH", //optional for leaf, recommended for CA
        locality: "Zug", //optional for leaf, recommended for CA
        state: "Zug", //optional for leaf, recommended for CA
        organization: "Vereign AG", //optional for leaf, recommended for CA
        organizationUnit:"Business Dep", //optional for leaf, recommended for CA
        //email: emailArg, // added to DN and Subject Alternative Name extension. Optional for CA. Mandatory for leaf certificate, used for email protection
        //url: "www.vereign.com" // optional url, recommended for CA, added to Subject Alternative Name extension
      },
      validity: {
        //notBefore: new Date() // optional, defaults to today at 00:00:00
        //notAfter: new Date()  // optional, defaults to notBefore + validYears at 23:59:59
        validYears: 5 //optional, defaults to 1
      },
      isCA: false // optional flag denoting if this is CA certificate or leaf certificate, defaults to false
    }
  }

  return parsePrivateKey(privateKeyIssuerArg).then(privateKeyDecoded => {
    const issuerData = {
      certificate: parseCertificate(certicateIssuerArg),// vereignCACertPEM),
      privateKey: privateKeyDecoded
Markin Igor's avatar
Markin Igor committed
    };
    return createCertificate(certData, issuerData);
    //console.log(vereignIntermediateKey)
  });
}

function download(filename, contentType, text) {
  var element = document.createElement('a');
  element.setAttribute('href', 'data:' + contentType + ';charset=utf-8,' + encodeURIComponent(text));
  element.setAttribute('download', filename);

  element.style.display = 'none';
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

function arrayBufferToBase64Formatted(buffer) {
  const bufferString = String.fromCharCode.apply(null, new Uint8Array(buffer));
  const base64formatted = formatPEM(window.btoa(bufferString));
  return base64formatted;
}

function arrayBufferToBase64(buffer) {
  const bufferString = String.fromCharCode.apply(null, new Uint8Array(buffer));
  const base64 = window.btoa(bufferString);
  return base64;
}

const newline = /\r\n|\r|\n/g;

function capitalizeFirstLetter(string) {
Markin Igor's avatar
Markin Igor committed
  if(string === "id") {
Loading
Loading full blame...