class AesEaxJce implements Aead {

  @SuppressWarnings("InsecureCryptoUsage")
  @Override
  public byte[] decrypt(final byte[] ciphertext, final byte[] associatedData)
      throws GeneralSecurityException {
    int plaintextLength = ciphertext.length - ivSizeInBytes - TAG_SIZE_IN_BYTES;
    if (plaintextLength < 0) {
      throw new GeneralSecurityException("ciphertext too short");
    }
    Cipher ecb = localEcbCipher.get();
    ecb.init(Cipher.ENCRYPT_MODE, keySpec);
    byte[] n = omac(ecb, 0, ciphertext, 0, ivSizeInBytes);
    byte[] aad = associatedData;
    if (aad == null) {
      aad = new byte[0];
    }
    byte[] h = omac(ecb, 1, aad, 0, aad.length);
    byte[] t = omac(ecb, 2, ciphertext, ivSizeInBytes, plaintextLength);
    byte res = 0;
    int offset = ciphertext.length - TAG_SIZE_IN_BYTES;
    for (int i = 0; i < TAG_SIZE_IN_BYTES; i++) {
      res = (byte) (res | (ciphertext[offset + i] ^ h[i] ^ n[i] ^ t[i]));
    }
    if (res != 0) {
      throw new AEADBadTagException("tag mismatch");
    }
    Cipher ctr = localCtrCipher.get();
    ctr.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(n));
    return ctr.doFinal(ciphertext, ivSizeInBytes, plaintextLength);
  }

  @SuppressWarnings("InsecureCryptoUsage") public  AesEaxJce(final byte[] key, int ivSizeInBytes);

}