public EncryptedKeyVersion reencryptEncryptedKey(EncryptedKeyVersion ekv)
      throws IOException, GeneralSecurityException {
    return getExtension().reencryptEncryptedKey(ekv);
  }
@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());
  }