/*
 * 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
 */
var scytlKeyStoreTest = {

  /**
   * Opens a Scytl key store that was generated using Java and checks that its
   * contents can be retrieved.
   *
   * @param {String}
   *            scytlKeyStoreJson the Scytl key store, in JSON format.
   * @param {String}
   *            secretKeyEntryPasswordB64 the password to access a secret key
   *            entry in the Scytl key store, in Base64 encoded format.
   * @param {String}
   *            secretKeyForEncryptionAlias the storage alias of the secret
   *            key for encryption.
   * @param {String}
   *            secretKeyForEncryptionB64 the secret key for encryption, in
   *            Base64 encoded format.
   * @param {String}
   *            secretKeyForHmacAlias the storage alias of the secret key for
   *            HMAC generation.
   * @param {String}
   *            secretKeyForHmacB64 the secret key for HMAC generation, in
   *            Base64 encoded format.
   * @param {String}
   *            privateKeyEntryPasswordB64 the password to access a private
   *            key entry in the Scytl key store, in Base64 encoded format.
   * @param {String}
   *            rootPrivateKeyAlias the storage alias of the root private key.
   * @param {String}
   *            rootPrivateKeyPem the expected root private key, in PEM
   *            format.
   * @param {String}
   *            rootCertificatePem the expected root certificate, in PEM
   *            format.
   * @param {String}
   *            intermediatePrivateKeyAlias the storage alias of the
   *            intermediate private key.
   * @param {String}
   *            intermediatePrivateKeyPem the expected intermediate private
   *            key, in PEM format.
   * @param {String}
   *            intermediateCertificatePem the expected intermediate
   *            certificate, in PEM format.
   * @param {String}
   *            leafPrivateKeyAlias the storage alias of the leaf private key.
   * @param {String}
   *            leafPrivateKeyPem the expected leaf private key, in PEM
   *            format.
   * @param {String}
   *            leafCertificatePem the expected leaf certificate, in PEM
   *            format.
   * @param {String}
   *            elGamalPrivateKeyEntryPasswordB64 the password to access an
   *            ElGamal private key entry in the Scytl key store, in Base64
   *            encoded format.
   * @param {String}
   *            elGamalPrivateKeyAlias the storage alias of the ElGamal
   *            private key.
   * @param {String}
   *            elGamalPrivateKeyJson the expected ElGamal private key, in
   *            JSON format.
   * @throws {Error}
   *             if the Scytl key store opening operation fails or the Scytl
   *             key store's content cannot be retrieved.
   */
  open: function(
      scytlKeyStoreJson, secretKeyEntryPasswordB64, secretKeyForEncryptionAlias,
      secretKeyForEncryptionB64, secretKeyForHmacAlias, secretKeyForHmacB64,
      privateKeyEntryPasswordB64, rootPrivateKeyAlias, rootPrivateKeyPem,
      rootCertificatePem, intermediatePrivateKeyAlias,
      intermediatePrivateKeyPem, intermediateCertificatePem,
      leafPrivateKeyAlias, leafPrivateKeyPem, leafCertificatePem,
      elGamalPrivateKeyEntryPasswordB64, elGamalPrivateKeyAlias,
      elGamalPrivateKeyJson) {

    'use strict';

    var errorData = {};
    errorData['Scytl key store (JSON format) [Java]'] = scytlKeyStoreJson;
    errorData['Secret key entry password (Base64 encoded) [Java]'] =
        secretKeyEntryPasswordB64;
    errorData['Secret key for encryption alias [Java]'] =
        secretKeyForEncryptionAlias;
    errorData['Secret key for encryption (Base64 encoded) [Java]'] =
        secretKeyForEncryptionB64;
    errorData['Secret key for HMAC generation alias [Java]'] =
        secretKeyForHmacAlias;
    errorData['Secret key for HMAC generation (Base64 encoded) [Java]'] =
        secretKeyForHmacB64;
    errorData['Private key entry password (Base64 encoded) [Java]'] =
        privateKeyEntryPasswordB64;
    errorData['Root private key alias [Java]'] = rootPrivateKeyAlias;
    errorData['Root private key (PEM format) [Java]'] = rootPrivateKeyPem;
    errorData['Root certificate (PEM format) [Java]'] = rootCertificatePem;
    errorData['Intermediate private key alias [Java]'] =
        intermediatePrivateKeyAlias;
    errorData['Intermediate private key (PEM format) [Java]'] =
        intermediatePrivateKeyPem;
    errorData['Intermediate certificate (PEM format) [Java]'] =
        intermediateCertificatePem;
    errorData['Leaf private key alias [Java]'] = leafPrivateKeyAlias;
    errorData['Leaf Private key (PEM format) [Java]'] = leafPrivateKeyPem;
    errorData['Leaf certificate (PEM format) [Java]'] = leafCertificatePem;
    errorData['ElGamal private key entry password (Base64 encoded) [Java]'] =
        elGamalPrivateKeyEntryPasswordB64;
    errorData['ElGamal private key alias [Java]'] = elGamalPrivateKeyAlias;
    errorData['ElGamal private key (JSON format) [Java]'] =
        elGamalPrivateKeyJson;

    try {
      cryptolib(
          'stores.service', 'certificates.service', 'homomorphic.service',
          function(box) {
            var sksReader = new box.stores.service.loadStore(scytlKeyStoreJson);

            // Retrieve secret keys from Scytl key store.
            var secretKeyForEncryptionB64Found = sksReader.getSecretKey(
                secretKeyForEncryptionAlias, secretKeyEntryPasswordB64);
            errorData
                ['Secret key for encryption, from Scytl key store (Base64 encoded) [JS]'] =
                    secretKeyForEncryptionB64Found;
            var secretKeyForHmacB64Found = sksReader.getSecretKey(
                secretKeyForHmacAlias, secretKeyEntryPasswordB64);
            errorData
                ['Secret key for HMAC generation, from Scytl key store (Base64 encoded) [JS]'] =
                    secretKeyForHmacB64Found;

            // Retrieve private keys from Scytl key store.
            var privateKeys =
                sksReader.getPrivateKeys(privateKeyEntryPasswordB64);
            var rootPrivateKeyPemFound = privateKeys[rootPrivateKeyAlias];
            errorData
                ['Root private key from Scytl key store (PEM format) [JS]'] =
                    rootPrivateKeyPemFound;
            var intermediatePrivateKeyPemFound =
                privateKeys[intermediatePrivateKeyAlias];
            errorData
                ['Intermediate private key from Scytl key store (PEM format) [JS]'] =
                    intermediatePrivateKeyPemFound;
            var leafPrivateKeyPemFound = privateKeys[leafPrivateKeyAlias];
            errorData
                ['Leaf Private key from Scytl key store (PEM format) [JS]'] =
                    leafPrivateKeyPemFound;

            // Retrieve certificate chains from Scytl key store.
            var rootCertificateChain = sksReader.getCertificateChainByAlias(
                privateKeyEntryPasswordB64, rootPrivateKeyAlias);
            errorData['Root certificate chain from PKCS12 [JS]'] =
                rootCertificateChain;
            var intermediateCertificateChain =
                sksReader.getCertificateChainByAlias(
                    privateKeyEntryPasswordB64, intermediatePrivateKeyAlias);
            errorData['Intermediate certificate chain from PKCS12 [JS]'] =
                intermediateCertificateChain;
            var leafCertificateChain = sksReader.getCertificateChainByAlias(
                privateKeyEntryPasswordB64, leafPrivateKeyAlias);
            errorData['Leaf certificate chain from PKCS12 [JS]'] =
                leafCertificateChain;

            // Check if secret keys were successfully retrieved from Scytl key
            // store.
            if (secretKeyForEncryptionB64Found !== secretKeyForEncryptionB64) {
              throw 'Expected secret key (Base64 encoded): ' +
                  secretKeyForEncryptionB64 +
                  ' ; Found: ' + secretKeyForEncryptionB64Found;
            }
            if (secretKeyForHmacB64Found !== secretKeyForHmacB64) {
              throw 'Expected secret key (Base64 encoded): ' +
                  secretKeyForHmacB64 + ' ; Found: ' + secretKeyForHmacB64Found;
            }

            // Check if private keys were successfully retrieved from Scytl key
            // store.
            testUtils.checkPrivateKey(
                rootPrivateKeyPemFound, rootPrivateKeyPem);
            testUtils.checkPrivateKey(
                intermediatePrivateKeyPemFound, intermediatePrivateKeyPem);
            testUtils.checkPrivateKey(
                leafPrivateKeyPemFound, leafPrivateKeyPem);

            // Check if certificate chains were successfully retrieved from
            // Scytl key store.
            testUtils.checkCertificate(
                rootCertificateChain[0], rootCertificatePem);
            testUtils.checkCertificate(
                intermediateCertificateChain[0], intermediateCertificatePem);
            testUtils.checkCertificate(
                intermediateCertificateChain[1], rootCertificatePem);
            testUtils.checkCertificate(
                leafCertificateChain[0], leafCertificatePem);
            testUtils.checkCertificate(
                leafCertificateChain[1], intermediateCertificatePem);
            testUtils.checkCertificate(
                leafCertificateChain[2], rootCertificatePem);

            // Check if certificates retrieved from Scytl key store can be
            // verified.
            var rootCertificatePemFound = leafCertificateChain[2];
            var intermediateCertificatePemFound = leafCertificateChain[1];
            var leafCertificatePemFound = leafCertificateChain[0];
            var rootCertificateFound =
                new box.certificates.service.load(rootCertificatePemFound);
            var intermediateCertificateFound =
                new box.certificates.service.load(
                    intermediateCertificatePemFound);
            if (!rootCertificateFound.verify(rootCertificatePemFound)) {
              throw 'Root certificate signature could not be verified.';
            }
            if (!rootCertificateFound.verify(intermediateCertificatePemFound)) {
              throw 'Intermediate certificate signature could not be verified.';
            }
            if (!intermediateCertificateFound.verify(leafCertificatePemFound)) {
              throw 'Leaf certificate signature could not be verified.';
            }

            // Retrieve ElGamal private key from Scytl key store.
            var elGamalPrivateKeyFound = sksReader.getElGamalPrivateKey(
                elGamalPrivateKeyAlias, elGamalPrivateKeyEntryPasswordB64);

            // Check if ElGamal private key was successfully retrieved from
            // Scytl key store.
            var elGamalPrivateKeyExpected =
                new box.homomorphic.service.createElGamalPrivateKey(
                    _converters.base64Encode(elGamalPrivateKeyJson));
            testUtils.checkElGamalPrivateKey(
                elGamalPrivateKeyFound, elGamalPrivateKeyExpected);
          });
    } catch (error) {
      throw testUtils.serializeError(error, errorData);
    }
  }
};