@Test
public void testWycheproofVectors() throws Exception {

  JSONObject json =
      WycheproofTestUtil.readJson("../wycheproof/testvectors/aes_gcm_siv_test.json");
  int errors = 0;
  int cntSkippedTests = 0;
  JSONArray testGroups = json.getJSONArray("testGroups");
  for (int i = 0; i < testGroups.length(); i++) {
    JSONObject group = testGroups.getJSONObject(i);
    int keySize = group.getInt("keySize");
    JSONArray tests = group.getJSONArray("tests");
    if (!Arrays.asList(keySizeInBytes).contains(keySize / 8)) {
      cntSkippedTests += tests.length();
      continue;
    }
    for (int j = 0; j < tests.length(); j++) {
      JSONObject testcase = tests.getJSONObject(j);
      String tcId =
          String.format(
              "testcase %d (%s)", testcase.getInt("tcId"), testcase.getString("comment"));
      byte[] iv = Hex.decode(testcase.getString("iv"));
      byte[] key = Hex.decode(testcase.getString("key"));
      byte[] msg = Hex.decode(testcase.getString("msg"));
      byte[] aad = Hex.decode(testcase.getString("aad"));
      byte[] ct = Hex.decode(testcase.getString("ct"));
      byte[] tag = Hex.decode(testcase.getString("tag"));
      byte[] ciphertext = Bytes.concat(iv, ct, tag);
      // Result is one of "valid", "invalid", "acceptable".
      // "valid" are test vectors with matching plaintext, ciphertext and tag.
      // "invalid" are test vectors with invalid parameters or invalid ciphertext and tag.
      // "acceptable" are test vectors with weak parameters or legacy formats.
      String result = testcase.getString("result");
      // Tink only supports 12-byte iv.
      if (iv.length != 12) {
        result = "invalid";
      }
      try {
        AesGcmSiv gcm = new AesGcmSiv(key);
        byte[] decrypted = gcm.decrypt(ciphertext, aad);
        boolean eq = TestUtil.arrayEquals(decrypted, msg);
        if (result.equals("invalid")) {
          System.out.printf(
              "FAIL %s: accepting invalid ciphertext, cleartext: %s, decrypted: %s%n",
              tcId, Hex.encode(msg), Hex.encode(decrypted));
          errors++;
        } else {
          if (!eq) {
            System.out.printf(
                "FAIL %s: incorrect decryption, result: %s, expected: %s%n",
                tcId, Hex.encode(decrypted), Hex.encode(msg));
            errors++;
          }
        }
      } catch (GeneralSecurityException ex) {
        if (result.equals("valid")) {
          System.out.printf("FAIL %s: cannot decrypt, exception %s%n", tcId, ex);
          errors++;
        }
      }
    }
  }
  System.out.printf("Number of tests skipped: %d", cntSkippedTests);
  assertEquals(0, errors);
}