/*
 * 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
 */

package com.scytl.slogger.validator.hmac.encrypted;

import com.scytl.slogger.crypto.SecureLoggerCryptographyProvider;
import com.scytl.slogger.event.SecureLoggingEvent;
import com.scytl.slogger.event.SecureMessageProperties;
import com.scytl.slogger.validator.EventValidatorException;
import com.scytl.slogger.validator.hmac.HMacEventValidator;

import org.apache.log4j.Layout;

import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.util.Base64;
import java.util.Map;

import javax.crypto.SecretKey;

/**
 * Implementation of event validator to verify hmac chained logs with encrypted secret key.
 */
public class EncryptedHMacEventValidator extends HMacEventValidator {

  private final PrivateKey privateKey;

  /**
   * Constructor
   *
   * @param privateKey the private key
   * @param cryptographyProvider the cryptography provider.
   */
  public EncryptedHMacEventValidator(final PrivateKey privateKey,
      final SecureLoggerCryptographyProvider cryptographyProvider) {
    super(cryptographyProvider);
    this.privateKey = privateKey;
  }

  @Override
  protected void initializeHMac(final SecureLoggingEvent event, final Layout layout)
      throws EventValidatorException {
    Map<String, String> properties = event.getSecureMessage().properties();
    if (properties.containsKey(SecureMessageProperties.ENCRYPTED_SESSION_KEY)) {
      try {
        byte[] encryptedSecretKey = Base64.getDecoder().decode(
            properties.get(SecureMessageProperties.ENCRYPTED_SESSION_KEY));

        byte[] envelope =
            getCryptographyProvider().asymmetricDecrypt(encryptedSecretKey, privateKey);

        SecretKey secretKey =
            getCryptographyProvider().generateSymmetricKey(Base64.getDecoder().decode(envelope));

        loadHMacSecretKey(secretKey);
      } catch (GeneralSecurityException e) {
        throw new EventValidatorException(e);
      }
    }
  }
}
