@Test
public void testReencryptEncryptedKey() throws Exception {

  // Generate a new EEK
  final KeyProviderCryptoExtension.EncryptedKeyVersion ek1 =
      kpExt.generateEncryptedKey(encryptionKey.getName());
  // Decrypt EEK into an EK and check it
  final KeyVersion k1 = kpExt.decryptEncryptedKey(ek1);
  assertEquals(KeyProviderCryptoExtension.EK, k1.getVersionName());
  assertEquals(encryptionKey.getMaterial().length, k1.getMaterial().length);
  // Roll the EK
  kpExt.rollNewVersion(ek1.getEncryptionKeyName());
  // Reencrypt ek1
  final KeyProviderCryptoExtension.EncryptedKeyVersion ek2 =
      kpExt.reencryptEncryptedKey(ek1);
  assertEquals("Version name of EEK should be EEK",
      KeyProviderCryptoExtension.EEK,
      ek2.getEncryptedKeyVersion().getVersionName());
  assertEquals("Name of EEK should be encryption key name",
      ENCRYPTION_KEY_NAME, ek2.getEncryptionKeyName());
  assertNotNull("Expected encrypted key material",
      ek2.getEncryptedKeyVersion().getMaterial());
  assertEquals("Length of encryption key material and EEK material should "
          + "be the same", encryptionKey.getMaterial().length,
      ek2.getEncryptedKeyVersion().getMaterial().length);
  if (Arrays.equals(ek2.getEncryptedKeyVersion().getMaterial(),
      ek1.getEncryptedKeyVersion().getMaterial())) {
    fail("Re-encrypted EEK should have different material");
  }
  // Decrypt the new EEK into an EK and check it
  final KeyVersion k2 = kpExt.decryptEncryptedKey(ek2);
  assertEquals(KeyProviderCryptoExtension.EK, k2.getVersionName());
  assertEquals(encryptionKey.getMaterial().length, k2.getMaterial().length);
  // Re-encrypting the same EEK with the same EK should be deterministic
  final KeyProviderCryptoExtension.EncryptedKeyVersion ek2a =
      kpExt.reencryptEncryptedKey(ek1);
  assertEquals("Version name of EEK should be EEK",
      KeyProviderCryptoExtension.EEK,
      ek2a.getEncryptedKeyVersion().getVersionName());
  assertEquals("Name of EEK should be encryption key name",
      ENCRYPTION_KEY_NAME, ek2a.getEncryptionKeyName());
  assertNotNull("Expected encrypted key material",
      ek2a.getEncryptedKeyVersion().getMaterial());
  assertEquals("Length of encryption key material and EEK material should "
          + "be the same", encryptionKey.getMaterial().length,
      ek2a.getEncryptedKeyVersion().getMaterial().length);
  if (Arrays.equals(ek2a.getEncryptedKeyVersion().getMaterial(),
      ek1.getEncryptedKeyVersion().getMaterial())) {
    fail("Re-encrypted EEK should have different material");
  }
  assertArrayEquals(ek2.getEncryptedKeyVersion().getMaterial(),
      ek2a.getEncryptedKeyVersion().getMaterial());
  // Re-encrypting an EEK with the same version EK should be no-op
  final KeyProviderCryptoExtension.EncryptedKeyVersion ek3 =
      kpExt.reencryptEncryptedKey(ek2);
  assertEquals("Version name of EEK should be EEK",
      KeyProviderCryptoExtension.EEK,
      ek3.getEncryptedKeyVersion().getVersionName());
  assertEquals("Name of EEK should be encryption key name",
      ENCRYPTION_KEY_NAME, ek3.getEncryptionKeyName());
  assertNotNull("Expected encrypted key material",
      ek3.getEncryptedKeyVersion().getMaterial());
  assertEquals("Length of encryption key material and EEK material should "
          + "be the same", encryptionKey.getMaterial().length,
      ek3.getEncryptedKeyVersion().getMaterial().length);
  if (Arrays.equals(ek3.getEncryptedKeyVersion().getMaterial(),
      ek1.getEncryptedKeyVersion().getMaterial())) {
    fail("Re-encrypted EEK should have different material");
  }
  assertArrayEquals(ek2.getEncryptedKeyVersion().getMaterial(),
      ek3.getEncryptedKeyVersion().getMaterial());
}