// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

goog.module('tink.subtle.EciesHkdfKemRecipientTest');
goog.setTestOnly('tink.subtle.EciesHkdfKemRecipientTest');

const Bytes = goog.require('tink.subtle.Bytes');
const EciesHkdfKemRecipient = goog.require('tink.subtle.EciesHkdfKemRecipient');
const EciesHkdfKemSender = goog.require('tink.subtle.EciesHkdfKemSender');
const EllipticCurves = goog.require('tink.subtle.EllipticCurves');
const Random = goog.require('tink.subtle.Random');
const TestCase = goog.require('goog.testing.TestCase');
const testSuite = goog.require('goog.testing.testSuite');
const userAgent = goog.require('goog.userAgent');


testSuite({
  shouldRunTests() {
    // https://msdn.microsoft.com/en-us/library/mt801195(v=vs.85).aspx
    return !userAgent.EDGE;  // b/120286783
  },

  setUp() {
    // Use a generous promise timeout for running continuously.
    TestCase.getActiveTestCase().promiseTimeout = 1000 * 1000;  // 1000s
  },

  tearDown() {
    // Reset the promise timeout to default value.
    TestCase.getActiveTestCase().promiseTimeout = 1000;  // 1s
  },

  async testEncapDecap() {
    const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
    const publicKey = await EllipticCurves.exportCryptoKey(keyPair.publicKey);
    const privateKey = await EllipticCurves.exportCryptoKey(keyPair.privateKey);
    const sender = await EciesHkdfKemSender.newInstance(publicKey);
    const recipient = await EciesHkdfKemRecipient.newInstance(privateKey);
    for (let i = 1; i < 20; i++) {
      const keySizeInBytes = i;
      const pointFormat = EllipticCurves.PointFormatType.UNCOMPRESSED;
      const hkdfHash = 'SHA-256';
      const hkdfInfo = Random.randBytes(i);
      const hkdfSalt = Random.randBytes(i);

      const kemKeyToken = await sender.encapsulate(
          keySizeInBytes, pointFormat, hkdfHash, hkdfInfo, hkdfSalt);
      const key = await recipient.decapsulate(
          kemKeyToken['token'], keySizeInBytes, pointFormat, hkdfHash, hkdfInfo,
          hkdfSalt);

      assertEquals(keySizeInBytes, kemKeyToken['key'].length);
      assertEquals(Bytes.toHex(key), Bytes.toHex(kemKeyToken['key']));
    }
  },

  async testDecap_nonIntegerKeySize() {
    const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
    const publicKey = await EllipticCurves.exportCryptoKey(keyPair.publicKey);
    const privateKey = await EllipticCurves.exportCryptoKey(keyPair.privateKey);
    const sender = await EciesHkdfKemSender.newInstance(publicKey);
    const recipient = await EciesHkdfKemRecipient.newInstance(privateKey);
    const keySizeInBytes = 16;
    const pointFormat = EllipticCurves.PointFormatType.UNCOMPRESSED;
    const hkdfHash = 'SHA-256';
    const hkdfInfo = Random.randBytes(16);
    const hkdfSalt = Random.randBytes(16);
    const kemKeyToken = await sender.encapsulate(
        keySizeInBytes, pointFormat, hkdfHash, hkdfInfo, hkdfSalt);

    try {
      await recipient.decapsulate(
          kemKeyToken['token'], NaN, pointFormat, hkdfHash, hkdfInfo, hkdfSalt);
      fail('An exception should be thrown.');
    } catch (e) {
      assertEquals('CustomError: size must be an integer', e.toString());
    }

    try {
      await recipient.decapsulate(
          kemKeyToken['token'], undefined, pointFormat, hkdfHash, hkdfInfo,
          hkdfSalt);
      fail('An exception should be thrown.');
    } catch (e) {
      assertEquals('CustomError: size must be an integer', e.toString());
    }

    try {
      await recipient.decapsulate(
          kemKeyToken['token'], 1.8, pointFormat, hkdfHash, hkdfInfo, hkdfSalt);
      fail('An exception should be thrown.');
    } catch (e) {
      assertEquals('CustomError: size must be an integer', e.toString());
    }
  },


  async testNewInstance_invalidParameters() {
    // Test newInstance without key.
    try {
      await EciesHkdfKemRecipient.newInstance(null);
      fail('An exception should be thrown.');
    } catch (e) {
    }

    // Test newInstance with public key instead private key.
    const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
    const publicKey = await EllipticCurves.exportCryptoKey(keyPair.publicKey);
    try {
      await EciesHkdfKemRecipient.newInstance(publicKey);
      fail('An exception should be thrown.');
    } catch (e) {
    }

    // Test newInstance with CryptoKey instead of JSON key.
    try {
      await EciesHkdfKemRecipient.newInstance(keyPair.publicKey);
      fail('An exception should be thrown.');
    } catch (e) {
    }
  },

  async testNewInstance_invalidPrivateKey() {
    for (let testVector of TEST_VECTORS) {
      const ellipticCurveString = EllipticCurves.curveToString(testVector.crv);
      const privateJwk = EllipticCurves.pointDecode(
          ellipticCurveString, testVector.pointFormat,
          Bytes.fromHex(testVector.privateKeyPoint));
      privateJwk['d'] = Bytes.toBase64(
          Bytes.fromHex(testVector.privateKeyValue), /* opt_webSafe = */ true);

      // Change the x value such that the key si no more valid. Recipient should
      // either throw an exception or ignore the x value and compute the same
      // output value.
      const xLength = EllipticCurves.fieldSizeInBytes(testVector.crv);
      privateJwk['x'] =
          Bytes.toBase64(new Uint8Array(xLength), /* opt_webSafe = */ true);
      let output;
      try {
        const recipient = await EciesHkdfKemRecipient.newInstance(privateJwk);
        const hkdfInfo = Bytes.fromHex(testVector.hkdfInfo);
        const salt = Bytes.fromHex(testVector.salt);
        output = await recipient.decapsulate(
            Bytes.fromHex(testVector.token), testVector.outputLength,
            testVector.pointFormat, testVector.hashType, hkdfInfo, salt);
      } catch (e) {
        // Everything works properly if exception was thrown.
        return;
      }
      // If there was no exception, the output should be still correct (x value
      // should be ignored during the computation).
      assertEquals(testVector.expectedOutput, Bytes.toHex(output));
    }
  },

  async testConstructor_invalidParameters() {
    // Test constructor without key.
    try {
      new EciesHkdfKemRecipient(null);
      fail('An exception should be thrown.');
    } catch (e) {
      assertEquals(
          'CustomError: Private key has to be non-null.', e.toString());
    }

    // Test public key instead of private key.
    const keyPair = await EllipticCurves.generateKeyPair('ECDH', 'P-256');
    try {
      new EciesHkdfKemRecipient(keyPair.publicKey);
      fail('An exception should be thrown.');
    } catch (e) {
      assertEquals(
          'CustomError: Expected crypto key of type: private.', e.toString());
    }

    // Test that JSON key cannot be used instead of CryptoKey.
    const privateKey = await EllipticCurves.exportCryptoKey(keyPair.privateKey);
    try {
      new EciesHkdfKemRecipient(privateKey);
      fail('An exception should be thrown.');
    } catch (e) {
    }
  },

  async testEncapDecap_differentParams() {
    const curveTypes = Object.keys(EllipticCurves.CurveType);
    const hashTypes = ['SHA-1', 'SHA-256', 'SHA-512'];
    for (let curve of curveTypes) {
      const curveString =
          EllipticCurves.curveToString(EllipticCurves.CurveType[curve]);
      for (let hashType of hashTypes) {
        const keyPair =
            await EllipticCurves.generateKeyPair('ECDH', curveString);
        const keySizeInBytes = 32;
        const pointFormat = EllipticCurves.PointFormatType.UNCOMPRESSED;
        const hkdfInfo = Random.randBytes(8);
        const hkdfSalt = Random.randBytes(16);

        const publicKey =
            await EllipticCurves.exportCryptoKey(keyPair.publicKey);
        const sender = await EciesHkdfKemSender.newInstance(publicKey);
        const kemKeyToken = await sender.encapsulate(
            keySizeInBytes, pointFormat, hashType, hkdfInfo, hkdfSalt);

        const privateKey =
            await EllipticCurves.exportCryptoKey(keyPair.privateKey);
        const recipient = await EciesHkdfKemRecipient.newInstance(privateKey);
        const key = await recipient.decapsulate(
            kemKeyToken['token'], keySizeInBytes, pointFormat, hashType,
            hkdfInfo, hkdfSalt);

        assertEquals(keySizeInBytes, kemKeyToken['key'].length);
        assertEquals(Bytes.toHex(key), Bytes.toHex(kemKeyToken['key']));
      }
    }
  },

  async testEncapDecap_modifiedToken() {
    const curveTypes = Object.keys(EllipticCurves.CurveType);
    const hashTypes = ['SHA-1', 'SHA-256', 'SHA-512'];
    for (let crvId of curveTypes) {
      const curve = EllipticCurves.CurveType[crvId];
      const curveString = EllipticCurves.curveToString(curve);
      for (let hashType of hashTypes) {
        const keyPair =
            await EllipticCurves.generateKeyPair('ECDH', curveString);
        const privateKey =
            await EllipticCurves.exportCryptoKey(keyPair.privateKey);
        const recipient = await EciesHkdfKemRecipient.newInstance(privateKey);
        const keySizeInBytes = 32;
        const pointFormat = EllipticCurves.PointFormatType.UNCOMPRESSED;
        const hkdfInfo = Random.randBytes(8);
        const hkdfSalt = Random.randBytes(16);

        // Create invalid token (EC point), while preserving the 0x04 prefix
        // byte.
        const token = Random.randBytes(
            EllipticCurves.encodingSizeInBytes(curve, pointFormat));
        token[0] = 0x04;
        try {
          await recipient.decapsulate(
              token, keySizeInBytes, pointFormat, hashType, hkdfInfo, hkdfSalt);
          fail('Should throw an exception');
        } catch (e) {
        }
      }
    }
  },

  async testDecapsulate_testVectorsGeneratedByJava() {
    for (let testVector of TEST_VECTORS) {
      const ellipticCurveString = EllipticCurves.curveToString(testVector.crv);
      const privateJwk = EllipticCurves.pointDecode(
          ellipticCurveString, testVector.pointFormat,
          Bytes.fromHex(testVector.privateKeyPoint));
      privateJwk['d'] = Bytes.toBase64(
          Bytes.fromHex(testVector.privateKeyValue), /* opt_webSafe = */ true);
      const recipient = await EciesHkdfKemRecipient.newInstance(privateJwk);
      const hkdfInfo = Bytes.fromHex(testVector.hkdfInfo);
      const salt = Bytes.fromHex(testVector.salt);
      const output = await recipient.decapsulate(
          Bytes.fromHex(testVector.token), testVector.outputLength,
          testVector.pointFormat, testVector.hashType, hkdfInfo, salt);
      assertEquals(testVector.expectedOutput, Bytes.toHex(output));
    }
  },
});


class TestVector {
  /**
   * @param {!EllipticCurves.CurveType} crv
   * @param {string} hashType
   * @param {!EllipticCurves.PointFormatType} pointFormat
   * @param {string} token
   * @param {string} privateKeyPoint
   * @param {string} privateKeyValue
   * @param {string} salt
   * @param {string} hkdfInfo
   * @param {number} outputLength
   * @param {string} expectedOutput
   */
  constructor(
      crv, hashType, pointFormat, token, privateKeyPoint, privateKeyValue, salt,
      hkdfInfo, outputLength, expectedOutput) {
    /** @const {!EllipticCurves.CurveType} */
    this.crv = crv;
    /** @const {string} */
    this.hashType = hashType;
    /** @const {!EllipticCurves.PointFormatType} */
    this.pointFormat = pointFormat;
    /** @const {string} */
    this.token = token;
    /** @const {string} */
    this.privateKeyPoint = privateKeyPoint;
    /** @const {string} */
    this.privateKeyValue = privateKeyValue;
    /** @const {string} */
    this.salt = salt;
    /** @const {string} */
    this.hkdfInfo = hkdfInfo;
    /** @const {number} */
    this.outputLength = outputLength;
    /** @const {string} */
    this.expectedOutput = expectedOutput;
  }
}

// Test vectors generated by Java version of Tink.
//
// Token (i.e. sender public key) and privateKeyPoint values are in UNCOMPRESSED
// EcPoint encoding (i.e. it has prefix '04' followed by x and y values).
/** {!Array<!TestVector>} */
const TEST_VECTORS = [
  new TestVector(
      EllipticCurves.CurveType.P256, 'SHA-256',
      EllipticCurves.PointFormatType.UNCOMPRESSED,
      /* token = */ '04' +
          '5cdd8e426d11970a610f0e5f9b27f247a421c477b379f2ff3fd3bac50dfff9ff' +
          '7cada79ab1de9ce4aeaff45fcd2628d1b6d7ecac99d4c26409d4ab8a362c8e7a',
      /* privateKeyPoint = */ '04' +
          '4adf0fff84b995bb97af250128a3d779c86ba3cd7e5c0fa2c10895d0b995aaee' +
          'cdced57616ebb04c808f191c2bf3848c495dcfddcdd1bb73d8ea7a15c642af05',
      /* privateKeyValue = */
      'da73e10f7d81483daa63438b982c879706bcf8fef8c7c4d3071c3ef2367714f3',
      /* salt = */ 'abcdef',
      /* hkdfInfo = */ 'aaaaaaaaaaaaaaaa',
      /* outputLength = */ 32,
      /* expectedOutput = */
      'aeeee35a14967310798f037e2f126e2e326369115eb9e2d1a34d9c6761f60511'),
  new TestVector(
      EllipticCurves.CurveType.P384, 'SHA-1',
      EllipticCurves.PointFormatType.UNCOMPRESSED,
      /* token = */ '04' +
          '75bc8a2e6cf80ce2e0a1cd60ab3d68e4d357b58ff69f0de14b7ec13c58a79750496e07db3f933167148d80730b96f000' +
          '9389967de410535ca3e103e7ce73dae9525f934589a6cd1fca37e61411985788dcedc71b35ef63b7365e391f6e2a945f',
      /* privateKeyPoint = */ '04' +
          '5f81886c4202897355b1da79348d53abd9e9119a7de6f5f10dfe751f7ca9c807035c029bac59499337c4af185fe61728' +
          'f132bfb234365a9c61e1e56c11acca3bee6621961c7c38eb9dcbd39b332fd35006876dccdb206a7b2d43cf70589c3356',
      /* privateKeyValue = */
      '544b5f32731d6277fa71e756f0b2d6840f62e6b744a8b8cdf91f8cf29e6d8562f6237369721f756ab044711e0d42c53c',
      /* salt = */ 'ababcdcd',
      /* hkdfInfo = */ '100000000000000001',
      /* outputLength = */ 32,
      /* expectedOutput = */
      '7a25c525eabaa0d994c27f7661a208b5ea25c2a778198237de6e4f235cd64a33'),
  new TestVector(
      EllipticCurves.CurveType.P521, 'SHA-512',
      EllipticCurves.PointFormatType.UNCOMPRESSED,
      /* token = */ '04' +
          '0075192f8decddf7a0371b2c859aad738cc5424fa70e74b560070ed8309ae8a6064b06f9aaad8020ac8620e62a6c1196efa44180d325a36a54945743b9382bd49bc1' +
          '000dfa1e30b228e975998b7afeaaf30235ec505960e58bf3269b69fffcbce9f15fc1441fab2ed97f554ae4bde8b956efb2372c5b330cb1aa0ab81b99e792acd7f5a8',
      /* privateKeyPoint = */ '04' +
          '00e57037a96bcbca532ef2f75646d825304ea716bbc9c4bf953455074347158f4818122c76e26a4cf94b39f451b7f5960b9cda43d49999ddc401c1be7f082052b387' +
          '0147197ba83ec55c8b02e6cbe7b49ce6d6c238edb89561bde6b4574a585c684379d8040888117866823258216344a7268dc696c3a2d192824a1e693609b44661fc2c',
      /* privateKeyValue = */
      '001e5410117d22e95c5768b82a786dd66fa8c326b938a3a81fdd6113499437ae9f74e9f876adf085c187c6a147abc13460b8ed3050a6b228005426b61f2b616a79c6',
      /* salt = */ '00001111',
      /* hkdfInfo = */ '1234123412341234',
      /* outputLength = */ 32,
      /* expectedOutput = */
      '3f7f64c7aba2cb012c9b5a952385290604b3b5843ec6e6714647a9c9d6ac87be')
];
