@Test
public void testModifyCiphertext() throws Exception {

  KeyPair uaKeyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE);
  ECPrivateKey uaPrivateKey = (ECPrivateKey) uaKeyPair.getPrivate();
  ECPublicKey uaPublicKey = (ECPublicKey) uaKeyPair.getPublic();
  byte[] authSecret = Random.randBytes(16);
  HybridEncrypt hybridEncrypt =
      new WebPushHybridEncrypt.Builder()
          .withAuthSecret(authSecret)
          .withRecipientPublicKey(uaPublicKey)
          .build();
  HybridDecrypt hybridDecrypt =
      new WebPushHybridDecrypt.Builder()
          .withAuthSecret(authSecret)
          .withRecipientPublicKey(uaPublicKey)
          .withRecipientPrivateKey(uaPrivateKey)
          .build();
  byte[] plaintext = Random.randBytes(20);
  byte[] ciphertext = hybridEncrypt.encrypt(plaintext, null /* contextInfo */);
  // Flipping bits.
  for (int b = 0; b < ciphertext.length; b++) {
    for (int bit = 0; bit < 8; bit++) {
      byte[] modified = Arrays.copyOf(ciphertext, ciphertext.length);
      modified[b] ^= (byte) (1 << bit);
      try {
        byte[] unused = hybridDecrypt.decrypt(modified, null /* contextInfo */);
        fail("Decrypting modified ciphertext should fail");
      } catch (GeneralSecurityException ex) {
        // This is expected.
      }
    }
  }
  // Truncate the message.
  for (int length = 0; length < ciphertext.length; length++) {
    byte[] modified = Arrays.copyOf(ciphertext, length);
    try {
      byte[] unused = hybridDecrypt.decrypt(modified, null /* contextInfo */);
      fail("Decrypting modified ciphertext should fail");
    } catch (GeneralSecurityException ex) {
      // This is expected.
    }
  }
}