/**
   * Test public key encryption.
   *
   * @throws Exception When test fails.
   */
  @Test
  public void testActivationGenerate() throws Exception {
    String activationOTP = "CKZ2O-OE544";
    String activationIdShort = "IFA6F-3NPAZ";
    byte[] activationNonce = BaseEncoding.base64().decode("grDwkvXrgfUdKBsqg0xYYw==");
    byte[] publicKeyBytes =
        BaseEncoding.base64()
            .decode(
                "BJXfJMCANX+T9FzsG6Hi0KTYPN64i7HxMiWoMYPd17DYfBR+IwzOesTh/jj/B3trL9m3O1oODYil+8ssJzDt/QA=");
    byte[] ephemeralPrivateKeyBytes =
        BaseEncoding.base64().decode("AKeMTtivK/XRiQPhfJYxAw1L62ah4lGTQ4JKqRrr0fnC");
    byte[] masterPublicKey =
        BaseEncoding.base64()
            .decode(
                "BFOqvpLNi15eHDt8fkFxFe034Buw/i8gR3ax4fKiIQynt5K858oBBYhqLVH8FhNmMnlysnRd2UsPJSQxzoPhEn8=");

    CryptoProviderUtil keyConvertor = PowerAuthConfiguration.INSTANCE.getKeyConvertor();
    PrivateKey eph = keyConvertor.convertBytesToPrivateKey(ephemeralPrivateKeyBytes);
    PublicKey mpk = keyConvertor.convertBytesToPublicKey(masterPublicKey);

    PublicKey publicKey =
        PowerAuthConfiguration.INSTANCE.getKeyConvertor().convertBytesToPublicKey(publicKeyBytes);
    PowerAuthClientActivation activation = new PowerAuthClientActivation();

    byte[] cDevicePublicKey =
        activation.encryptDevicePublicKey(
            publicKey, eph, mpk, activationOTP, activationIdShort, activationNonce);
    assertArrayEquals(
        cDevicePublicKey,
        BaseEncoding.base64()
            .decode(
                "tnAyB0C5I9xblLlFCPONUT4GtABvutPkRvvx2oTeGIuUMAmUYTqJluKn/Zge+vbq+VArIVNYVTd+0yuBZGVtkkd1mTcc2eTDhqZSQJS6mMgmKeCqv64c6E4dm4INOkxh"));
  }
  /**
   * Test of the complete activation process, orchestration between client and server.
   *
   * @throws Exception In case test fails
   */
  @Test
  public void testActivationProcess() throws Exception {

    System.out.println("TEST: Activation Process");

    // Prepare test data
    KeyGenerator keyGenerator = new KeyGenerator();
    PowerAuthClientActivation clientActivation = new PowerAuthClientActivation();
    PowerAuthServerActivation serverActivation = new PowerAuthServerActivation();
    KeyPair masterKeyPair = keyGenerator.generateKeyPair();

    // Generate master keypair
    PrivateKey masterPrivateKey = masterKeyPair.getPrivate();
    PublicKey masterPublicKey = masterKeyPair.getPublic();

    for (int i = 0; i < 20; i++) {

      // SERVER: Generate data for activation
      String activationId = serverActivation.generateActivationId();
      String activationIdShort = serverActivation.generateActivationIdShort();
      String activationOTP = serverActivation.generateActivationOTP();
      byte[] activationSignature =
          serverActivation.generateActivationSignature(
              activationIdShort, activationOTP, masterPrivateKey);
      KeyPair serverKeyPair = serverActivation.generateServerKeyPair();
      PrivateKey serverPrivateKey = serverKeyPair.getPrivate();
      PublicKey serverPublicKey = serverKeyPair.getPublic();

      // CLIENT: Verify activation signature
      boolean activationSignatureOK =
          clientActivation.verifyActivationDataSignature(
              activationIdShort, activationOTP, activationSignature, masterPublicKey);
      assertTrue(activationSignatureOK);

      // CLIENT: Generate and send public key
      KeyPair deviceKeyPair = clientActivation.generateDeviceKeyPair();
      KeyPair clientEphemeralKeyPair = keyGenerator.generateKeyPair();
      PrivateKey devicePrivateKey = deviceKeyPair.getPrivate();
      PublicKey devicePublicKey = deviceKeyPair.getPublic();
      byte[] clientNonce = clientActivation.generateActivationNonce();
      byte[] c_devicePublicKey =
          clientActivation.encryptDevicePublicKey(
              devicePublicKey,
              clientEphemeralKeyPair.getPrivate(),
              masterPublicKey,
              activationOTP,
              activationIdShort,
              clientNonce);

      // SERVER: Decrypt device public key
      PublicKey decryptedDevicePublicKey =
          serverActivation.decryptDevicePublicKey(
              c_devicePublicKey,
              activationIdShort,
              masterPrivateKey,
              clientEphemeralKeyPair.getPublic(),
              activationOTP,
              clientNonce);
      assertEquals(devicePublicKey, decryptedDevicePublicKey);

      // SERVER: Encrypt and send encrypted server public and it's signature
      KeyPair ephemeralKeyPair = keyGenerator.generateKeyPair();
      PrivateKey ephemeralPrivateKey = ephemeralKeyPair.getPrivate();
      PublicKey ephemeralPublicKey = ephemeralKeyPair.getPublic();
      byte[] serverNonce = serverActivation.generateActivationNonce();
      byte[] c_serverPublicKey =
          serverActivation.encryptServerPublicKey(
              serverPublicKey,
              devicePublicKey,
              ephemeralPrivateKey,
              activationOTP,
              activationIdShort,
              serverNonce);
      byte[] c_serverPublicKeySignature =
          serverActivation.computeServerDataSignature(
              activationId, c_serverPublicKey, masterPrivateKey);

      // CLIENT: Validate server public key signature and decrypt server public key
      boolean serverPublicKeySignatureOK =
          clientActivation.verifyServerDataSignature(
              activationId, c_serverPublicKey, c_serverPublicKeySignature, masterPublicKey);
      assertTrue(serverPublicKeySignatureOK);

      PublicKey decryptedServerPublicKey =
          clientActivation.decryptServerPublicKey(
              c_serverPublicKey,
              devicePrivateKey,
              ephemeralPublicKey,
              activationOTP,
              activationIdShort,
              serverNonce);
      assertEquals(serverPublicKey, decryptedServerPublicKey);

      // CLIENT and SERVER: Compute device public key fingerprint
      int devicePublicKeyFingerprintClient =
          clientActivation.computeDevicePublicKeyFingerprint(devicePublicKey);
      int devicePublicKeyFingerprintServer =
          serverActivation.computeDevicePublicKeyFingerprint(decryptedDevicePublicKey);
      assertEquals(devicePublicKeyFingerprintClient, devicePublicKeyFingerprintServer);

      // CLIENT and SERVER: Compute shared master secret
      SecretKey sharedMasterSecretDevice =
          keyGenerator.computeSharedKey(devicePrivateKey, serverPublicKey);
      SecretKey sharedMasterSecretServer =
          keyGenerator.computeSharedKey(serverPrivateKey, devicePublicKey);
      assertEquals(sharedMasterSecretDevice, sharedMasterSecretServer);
    }
  }