@Test
public void testEncryptDecrypt() throws Exception {

  KeyPair uaKeyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE);
  ECPrivateKey uaPrivateKey = (ECPrivateKey) uaKeyPair.getPrivate();
  ECPublicKey uaPublicKey = (ECPublicKey) uaKeyPair.getPublic();
  byte[] uaPublicKeyBytes =
      EllipticCurves.pointEncode(
          WebPushConstants.NIST_P256_CURVE_TYPE,
          WebPushConstants.UNCOMPRESSED_POINT_FORMAT,
          uaPublicKey.getW());
  byte[] authSecret = Random.randBytes(16);
  HybridEncrypt hybridEncrypt =
      new WebPushHybridEncrypt.Builder()
          .withAuthSecret(authSecret)
          .withRecipientPublicKey(uaPublicKeyBytes)
          .build();
  HybridDecrypt hybridDecrypt =
      new WebPushHybridDecrypt.Builder()
          .withAuthSecret(authSecret)
          .withRecipientPublicKey(uaPublicKeyBytes)
          .withRecipientPrivateKey(uaPrivateKey)
          .build();
  Set<String> salts = new TreeSet<>();
  Set<String> ephemeralPublicKeys = new TreeSet<>();
  Set<String> payloads = new TreeSet<>();
  int numTests = 100;
  if (TestUtil.isTsan()) {
    numTests = 5;
  }
  for (int j = 0; j < numTests; j++) {
    byte[] plaintext = Random.randBytes(j);
    byte[] ciphertext = hybridEncrypt.encrypt(plaintext, null /* contextInfo */);
    assertEquals(ciphertext.length, plaintext.length + WebPushConstants.CIPHERTEXT_OVERHEAD);
    assertArrayEquals(plaintext, hybridDecrypt.decrypt(ciphertext, null /* contextInfo */));
    // Checks that the encryption is randomized.
    ByteBuffer record = ByteBuffer.wrap(ciphertext);
    byte[] salt = new byte[WebPushConstants.SALT_SIZE];
    record.get(salt);
    salts.add(Hex.encode(salt));
    int unused1 = record.getInt();
    int unused2 = (int) record.get();
    byte[] ephemeralPublicKey = new byte[WebPushConstants.PUBLIC_KEY_SIZE];
    record.get(ephemeralPublicKey);
    ephemeralPublicKeys.add(Hex.encode(ephemeralPublicKey));
    byte[] payload = new byte[ciphertext.length - WebPushConstants.CONTENT_CODING_HEADER_SIZE];
    record.get(payload);
    payloads.add(Hex.encode(payload));
  }
  assertEquals(numTests, salts.size());
  assertEquals(numTests, ephemeralPublicKeys.size());
  assertEquals(numTests, payloads.size());
}