@Test
  public void testComputeSharedSecretWithWycheproofTestVectors() throws Exception {
    if (TestUtil.isTsan()) {
      return;
    }

    // NOTE(bleichen): Instead of ecdh_test.json it might be easier to use the
    //   files ecdh_<curve>_ecpoint.json, which encode the public key point just as DER
    //   encoded bitsequence.
    JsonObject json =
        WycheproofTestUtil.readJson("../wycheproof/testvectors/ecdh_test.json");
    int errors = 0;
    JsonArray testGroups = json.get("testGroups").getAsJsonArray();
    for (int i = 0; i < testGroups.size(); i++) {
      JsonObject group = testGroups.get(i).getAsJsonObject();
      JsonArray tests = group.get("tests").getAsJsonArray();
      String curve = group.get("curve").getAsString();
      EllipticCurves.CurveType curveType;
      try {
        curveType = WycheproofTestUtil.getCurveType(curve);
      } catch (NoSuchAlgorithmException ex) {
        System.out.println("Unsupported curve:" + curve);
        continue;
      }
      for (int j = 0; j < tests.size(); j++) {
        JsonObject testcase = tests.get(j).getAsJsonObject();
        if (WycheproofTestUtil.checkFlags(testcase, "CVE_2017_10176")) {
          System.out.println("Skipping CVE-2017-10176 test, see b/73760761");
          continue;
        }

        String tcId =
            String.format(
                "testcase %d (%s)",
                testcase.get("tcId").getAsInt(), testcase.get("comment").getAsString());
        String result = testcase.get("result").getAsString();
        String hexPubKey = testcase.get("public").getAsString();
        String expectedSharedSecret = testcase.get("shared").getAsString();
        String hexPrivKey = testcase.get("private").getAsString();
        if (hexPrivKey.length() % 2 == 1) {
          hexPrivKey = "0" + hexPrivKey;
        }
        KeyFactory kf = EngineFactory.KEY_FACTORY.getInstance("EC");
        try {
          ECPrivateKey privKey = EllipticCurves.getEcPrivateKey(curveType, Hex.decode(hexPrivKey));
          ECPublicKey pubKey;
          try {
            X509EncodedKeySpec x509keySpec = new X509EncodedKeySpec(Hex.decode(hexPubKey));
            pubKey = (ECPublicKey) kf.generatePublic(x509keySpec);
            // Sometimes providers do not encode keys the same way.
            // E.g. BouncyCastle may use long form encoding, where jdk uses a short encoding
            // with named curves. This checks the encodings and logs them if they differ.
            String hexReencodedKey = Hex.encode(pubKey.getEncoded());
            if (!hexPubKey.equals(hexReencodedKey)) {
              System.out.println("Wycheproof encoded public key spec: " + hexPubKey);
              System.out.println("Reencoded public key spec: " + hexReencodedKey);
            }
          } catch (java.lang.RuntimeException ex) {
            // Some of the test vectors contain incorrectly encoded public keys.
            // Some java providers do not properly check the encoding, which often results in
            // RuntimeExceptions. Since the decoding is not part of tink, we can simply ignore
            // these test vectors here.
            System.out.println("Got runtime exception: " + ex);
            continue;
          }
          String sharedSecret = Hex.encode(EllipticCurves.computeSharedSecret(privKey, pubKey));
          if (result.equals("invalid")) {
            if (expectedSharedSecret.equals(sharedSecret)
                && WycheproofTestUtil.checkFlags(
                    testcase, "WrongOrder", "WeakPublicKey", "UnnamedCurve")) {
              System.out.println(
                  tcId + " accepted invalid parameters but shared secret is correct.");
            } else {
              System.out.println(
                  "FAIL " + tcId + " accepted invalid parameters, shared secret: " + sharedSecret);
              errors++;
            }
          } else if (!expectedSharedSecret.equals(sharedSecret)) {
            System.out.println(
                "FAIL "
                    + tcId
                    + " incorrect shared secret, computed: "
                    + sharedSecret
                    + " expected: "
                    + expectedSharedSecret);
            errors++;
          }
        } catch (GeneralSecurityException ex) {
          System.out.println(tcId + " threw exception: " + ex.toString());
          if (result.equals("valid")) {
            System.out.println("FAIL " + tcId + " exception: " + ex.toString());
            ex.printStackTrace();
            errors++;
          }
        } catch (Exception ex) {
          // Other exceptions typically indicate that something is wrong with the implementation.
          System.out.println("FAIL " + tcId + " exception: " + ex.toString());
          ex.printStackTrace();
          errors++;
        }
      }
    }
    assertEquals(0, errors);
  }
A class to store a pair of valid Ecdsa signature in IEEE_P1363 and DER format.
java_src/src/test/java/com/google/crypto/tink/subtle/EllipticCurvesTest.java