// 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.signature.EcdsaPublicKeyManager');

const EcdsaUtil = goog.require('tink.signature.EcdsaUtil');
const ecdsaVerify = goog.require('google3.third_party.tink.javascript.subtle.ecdsa_verify');
const KeyManager = goog.require('google3.third_party.tink.javascript.internal.key_manager');
const {PublicKeyVerify} = goog.require('google3.third_party.tink.javascript.signature.internal.public_key_verify');
const {SecurityException} = goog.require('google3.third_party.tink.javascript.exception.security_exception');
const Util = goog.require('google3.third_party.tink.javascript.internal.util');
const {PbEcdsaParams, PbEcdsaPublicKey, PbKeyData, PbMessage} = goog.require('google3.third_party.tink.javascript.internal.proto');

/**
 * @implements {KeyManager.KeyFactory}
 * @final
 */
class EcdsaPublicKeyFactory {
  /** @override */
  newKey(keyFormat) {
    throw new SecurityException(
        'This operation is not supported for public keys. ' +
        'Use EcdsaPrivateKeyManager to generate new keys.');
  }

  /** @override */
  newKeyData(serializedKeyFormat) {
    throw new SecurityException(
        'This operation is not supported for public keys. ' +
        'Use EcdsaPrivateKeyManager to generate new keys.');
  }
}


/**
 * @implements {KeyManager.KeyManager<PublicKeyVerify>}
 * @final
 */
class EcdsaPublicKeyManager {
  constructor() {
    this.keyFactory = new EcdsaPublicKeyFactory();
  }

  /** @override */
  async getPrimitive(primitiveType, key) {
    if (primitiveType !== this.getPrimitiveType()) {
      throw new SecurityException(
          'Requested primitive type which is not ' +
          'supported by this key manager.');
    }

    const keyProto = EcdsaPublicKeyManager.getKeyProto_(key);
    EcdsaUtil.validatePublicKey(keyProto, this.getVersion());

    const jwk = EcdsaUtil.getJsonWebKeyFromProto(keyProto);
    const params = /** @type{!PbEcdsaParams} */ (keyProto.getParams());
    const hash = Util.hashTypeProtoToString(params.getHashType());
    const encoding = EcdsaUtil.encodingTypeProtoToEnum(params.getEncoding());
    return await ecdsaVerify.fromJsonWebKey(jwk, hash, encoding);
  }

  /** @override */
  doesSupport(keyType) {
    return keyType === this.getKeyType();
  }

  /** @override */
  getKeyType() {
    return EcdsaPublicKeyManager.KEY_TYPE;
  }

  /** @override */
  getPrimitiveType() {
    return EcdsaPublicKeyManager.SUPPORTED_PRIMITIVE_;
  }

  /** @override */
  getVersion() {
    return EcdsaPublicKeyManager.VERSION;
  }

  /** @override */
  getKeyFactory() {
    return this.keyFactory;
  }

  /**
   * @private
   * @param {!PbKeyData|!PbMessage} keyMaterial
   * @return {!PbEcdsaPublicKey}
   */
  static getKeyProto_(keyMaterial) {
    if (keyMaterial instanceof PbKeyData) {
      return EcdsaPublicKeyManager.getKeyProtoFromKeyData_(keyMaterial);
    }
    if (keyMaterial instanceof PbEcdsaPublicKey) {
      return keyMaterial;
    }
    throw new SecurityException(
        'Key type is not supported. This key manager supports ' +
        EcdsaPublicKeyManager.KEY_TYPE + '.');
  }

  /**
   * @private
   * @param {!PbKeyData} keyData
   * @return {!PbEcdsaPublicKey}
   */
  static getKeyProtoFromKeyData_(keyData) {
    if (keyData.getTypeUrl() !== EcdsaPublicKeyManager.KEY_TYPE) {
      throw new SecurityException(
          'Key type ' + keyData.getTypeUrl() + ' is not supported. This key ' +
          'manager supports ' + EcdsaPublicKeyManager.KEY_TYPE + '.');
    }

    let /** !PbEcdsaPublicKey */ key;
    try {
      key = PbEcdsaPublicKey.deserializeBinary(keyData.getValue());
    } catch (e) {
      throw new SecurityException(
          'Input cannot be parsed as ' + EcdsaPublicKeyManager.KEY_TYPE +
          ' key-proto.');
    }
    if (!key.getParams() || !key.getX() || !key.getY()) {
      throw new SecurityException(
          'Input cannot be parsed as ' + EcdsaPublicKeyManager.KEY_TYPE +
          ' key-proto.');
    }
    return key;
  }
}

/** @const @public {string} */
EcdsaPublicKeyManager.KEY_TYPE =
    'type.googleapis.com/google.crypto.tink.EcdsaPublicKey';
/** @const @private {!Object} */
EcdsaPublicKeyManager.SUPPORTED_PRIMITIVE_ = PublicKeyVerify;
/** @const @package {number} */
EcdsaPublicKeyManager.VERSION = 0;

exports = EcdsaPublicKeyManager;
