/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.hadoop.ozone.security;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.security.token.OzoneBlockTokenIdentifier;
import org.apache.hadoop.security.ssl.KeyStoreTestUtil;
import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.Time;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

/**
 * Test class for OzoneManagerDelegationToken.
 */
public class TestOzoneManagerBlockToken {

  private static final Logger LOG = LoggerFactory
      .getLogger(TestOzoneManagerBlockToken.class);
  private static final String BASEDIR = GenericTestUtils
      .getTempPath(TestOzoneManagerBlockToken.class.getSimpleName());
  private static final String KEYSTORES_DIR =
      new File(BASEDIR).getAbsolutePath();
  private static long expiryTime;
  private static KeyPair keyPair;
  private static X509Certificate cert;
  private static final long MAX_LEN = 1000;

  @BeforeClass
  public static void setUp() throws Exception {
    File base = new File(BASEDIR);
    FileUtil.fullyDelete(base);
    base.mkdirs();
    expiryTime = Time.monotonicNow() + 60 * 60 * 24;

    // Create Ozone Master key pair.
    keyPair = KeyStoreTestUtil.generateKeyPair("RSA");
    // Create Ozone Master certificate (SCM CA issued cert) and key store.
    cert = KeyStoreTestUtil
        .generateCertificate("CN=OzoneMaster", keyPair, 30, "SHA256withRSA");
  }

  @After
  public void cleanUp() {
  }

  @Test
  public void testSignToken() throws GeneralSecurityException, IOException {
    String keystore = new File(KEYSTORES_DIR, "keystore.jks")
        .getAbsolutePath();
    String truststore = new File(KEYSTORES_DIR, "truststore.jks")
        .getAbsolutePath();
    String trustPassword = "trustPass";
    String keyStorePassword = "keyStorePass";
    String keyPassword = "keyPass";


    KeyStoreTestUtil.createKeyStore(keystore, keyStorePassword, keyPassword,
        "OzoneMaster", keyPair.getPrivate(), cert);

    // Create trust store and put the certificate in the trust store
    Map<String, X509Certificate> certs = Collections.singletonMap("server",
        cert);
    KeyStoreTestUtil.createTrustStore(truststore, trustPassword, certs);

    // Sign the OzoneMaster Token with Ozone Master private key
    PrivateKey privateKey = keyPair.getPrivate();
    OzoneBlockTokenIdentifier tokenId = new OzoneBlockTokenIdentifier(
        "testUser", "84940",
        EnumSet.allOf(HddsProtos.BlockTokenSecretProto.AccessModeProto.class),
        expiryTime, cert.getSerialNumber().toString(), MAX_LEN);
    byte[] signedToken = signTokenAsymmetric(tokenId, privateKey);

    // Verify a valid signed OzoneMaster Token with Ozone Master
    // public key(certificate)
    boolean isValidToken = verifyTokenAsymmetric(tokenId, signedToken, cert);
    LOG.info("{} is {}", tokenId, isValidToken ? "valid." : "invalid.");

    // Verify an invalid signed OzoneMaster Token with Ozone Master
    // public key(certificate)
    tokenId = new OzoneBlockTokenIdentifier("", "",
        EnumSet.allOf(HddsProtos.BlockTokenSecretProto.AccessModeProto.class),
        expiryTime, cert.getSerialNumber().toString(), MAX_LEN);
    LOG.info("Unsigned token {} is {}", tokenId,
        verifyTokenAsymmetric(tokenId, RandomUtils.nextBytes(128), cert));

  }

  public byte[] signTokenAsymmetric(OzoneBlockTokenIdentifier tokenId,
      PrivateKey privateKey) throws NoSuchAlgorithmException,
      InvalidKeyException, SignatureException {
    Signature rsaSignature = Signature.getInstance("SHA256withRSA");
    rsaSignature.initSign(privateKey);
    rsaSignature.update(tokenId.getBytes());
    byte[] signature = rsaSignature.sign();
    return signature;
  }

  public boolean verifyTokenAsymmetric(OzoneBlockTokenIdentifier tokenId,
      byte[] signature, Certificate certificate) throws InvalidKeyException,
      NoSuchAlgorithmException, SignatureException {
    Signature rsaSignature = Signature.getInstance("SHA256withRSA");
    rsaSignature.initVerify(certificate);
    rsaSignature.update(tokenId.getBytes());
    boolean isValid = rsaSignature.verify(signature);
    return isValid;
  }

  private byte[] signTokenSymmetric(OzoneBlockTokenIdentifier identifier,
      Mac mac, SecretKey key) {
    try {
      mac.init(key);
    } catch (InvalidKeyException ike) {
      throw new IllegalArgumentException("Invalid key to HMAC computation",
          ike);
    }
    return mac.doFinal(identifier.getBytes());
  }

  OzoneBlockTokenIdentifier generateTestToken() {
    return new OzoneBlockTokenIdentifier(RandomStringUtils.randomAlphabetic(6),
        RandomStringUtils.randomAlphabetic(5),
        EnumSet.allOf(HddsProtos.BlockTokenSecretProto.AccessModeProto.class),
        expiryTime, cert.getSerialNumber().toString(), MAX_LEN);
  }

  @Test
  public void testAsymmetricTokenPerf() throws NoSuchAlgorithmException,
      CertificateEncodingException, NoSuchProviderException,
      InvalidKeyException, SignatureException {
    final int testTokenCount = 1000;
    List<OzoneBlockTokenIdentifier> tokenIds = new ArrayList<>();
    List<byte[]> tokenPasswordAsym = new ArrayList<>();
    for (int i = 0; i < testTokenCount; i++) {
      tokenIds.add(generateTestToken());
    }

    KeyPair kp = KeyStoreTestUtil.generateKeyPair("RSA");

    // Create Ozone Master certificate (SCM CA issued cert) and key store
    X509Certificate omCert;
    omCert = KeyStoreTestUtil.generateCertificate("CN=OzoneMaster",
        kp, 30, "SHA256withRSA");

    long startTime = Time.monotonicNowNanos();
    for (int i = 0; i < testTokenCount; i++) {
      tokenPasswordAsym.add(
          signTokenAsymmetric(tokenIds.get(i), kp.getPrivate()));
    }
    long duration = Time.monotonicNowNanos() - startTime;
    LOG.info("Average token sign time with HmacSha256(RSA/1024 key) is {} ns",
        duration / testTokenCount);

    startTime = Time.monotonicNowNanos();
    for (int i = 0; i < testTokenCount; i++) {
      verifyTokenAsymmetric(tokenIds.get(i), tokenPasswordAsym.get(i), omCert);
    }
    duration = Time.monotonicNowNanos() - startTime;
    LOG.info("Average token verify time with HmacSha256(RSA/1024 key) "
        + "is {} ns", duration / testTokenCount);
  }

  @Test
  public void testSymmetricTokenPerf() {
    String hmacSHA1 = "HmacSHA1";
    String hmacSHA256 = "HmacSHA256";

    testSymmetricTokenPerfHelper(hmacSHA1, 64);
    testSymmetricTokenPerfHelper(hmacSHA256, 1024);
  }

  public void testSymmetricTokenPerfHelper(String hmacAlgorithm, int keyLen) {
    final int testTokenCount = 1000;
    List<OzoneBlockTokenIdentifier> tokenIds = new ArrayList<>();
    List<byte[]> tokenPasswordSym = new ArrayList<>();
    for (int i = 0; i < testTokenCount; i++) {
      tokenIds.add(generateTestToken());
    }

    KeyGenerator keyGen;
    try {
      keyGen = KeyGenerator.getInstance(hmacAlgorithm);
      keyGen.init(keyLen);
    } catch (NoSuchAlgorithmException nsa) {
      throw new IllegalArgumentException("Can't find " + hmacAlgorithm +
          " algorithm.");
    }

    Mac mac;
    try {
      mac = Mac.getInstance(hmacAlgorithm);
    } catch (NoSuchAlgorithmException nsa) {
      throw new IllegalArgumentException("Can't find " + hmacAlgorithm +
          " algorithm.");
    }

    SecretKey secretKey = keyGen.generateKey();

    long startTime = Time.monotonicNowNanos();
    for (int i = 0; i < testTokenCount; i++) {
      tokenPasswordSym.add(
          signTokenSymmetric(tokenIds.get(i), mac, secretKey));
    }
    long duration = Time.monotonicNowNanos() - startTime;
    LOG.info("Average token sign time with {}({} symmetric key) is {} ns",
        hmacAlgorithm, keyLen, duration / testTokenCount);
  }
}