test_class.file: apps/webpush/src/test/java/com/google/crypto/tink/apps/webpush/WebPushHybridEncryptTest.java
test_class.identifier: WebPushHybridEncryptTest
test_case.body: @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());
    }
test_case.class_method_signature: WebPushHybridEncryptTest.testEncryptDecrypt()
test_case.full_signature: @Test public void testEncryptDecrypt()
test_case.identifier: testEncryptDecrypt
test_case.invocations: generateKeyPair getPrivate getPublic pointEncode getW randBytes build withRecipientPublicKey withAuthSecret build withRecipientPrivateKey withRecipientPublicKey withAuthSecret isTsan randBytes encrypt assertEquals assertArrayEquals decrypt wrap get add encode getInt get get add encode get add encode assertEquals size assertEquals size assertEquals size
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void testEncryptDecrypt()
focal_class.declarator: recipientPublicKey
focal_class.modifier: private final
focal_class.original_string: private final byte[] recipientPublicKey;
focal_class.type: byte[]
focal_class.var_name: recipientPublicKey
focal_class.declarator: authSecret
focal_class.modifier: private final
focal_class.original_string: private final byte[] authSecret;
focal_class.type: byte[]
focal_class.var_name: authSecret
focal_class.declarator: recipientPublicPoint
focal_class.modifier: private final
focal_class.original_string: private final ECPoint recipientPublicPoint;
focal_class.type: ECPoint
focal_class.var_name: recipientPublicPoint
focal_class.declarator: recordSize
focal_class.modifier: private final
focal_class.original_string: private final int recordSize;
focal_class.type: int
focal_class.var_name: recordSize
focal_class.file: apps/webpush/src/main/java/com/google/crypto/tink/apps/webpush/WebPushHybridEncrypt.java
focal_class.identifier: WebPushHybridEncrypt
focal_class.interfaces: implements HybridEncrypt
focal_class.class_method_signature: WebPushHybridEncrypt.WebPushHybridEncrypt(Builder builder)
focal_class.full_signature: private  WebPushHybridEncrypt(Builder builder)
focal_class.identifier: WebPushHybridEncrypt
focal_class.modifiers: private
focal_class.parameters: (Builder builder)
focal_class.signature:  WebPushHybridEncrypt(Builder builder)
focal_class.class_method_signature: WebPushHybridEncrypt.encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */)
focal_class.full_signature: @Override public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */)
focal_class.identifier: encrypt
focal_class.modifiers: @Override public
focal_class.parameters: (final byte[] plaintext, final byte[] contextInfo /* unused */)
focal_class.return: byte[]
focal_class.signature: byte[] encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */)
focal_class.class_method_signature: WebPushHybridEncrypt.encrypt(final byte[] key, final byte[] nonce, final byte[] plaintext)
focal_class.full_signature: private byte[] encrypt(final byte[] key, final byte[] nonce, final byte[] plaintext)
focal_class.identifier: encrypt
focal_class.modifiers: private
focal_class.parameters: (final byte[] key, final byte[] nonce, final byte[] plaintext)
focal_class.return: byte[]
focal_class.signature: byte[] encrypt(final byte[] key, final byte[] nonce, final byte[] plaintext)
focal_method.body: @Override
    public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */)
        throws GeneralSecurityException {
      if (contextInfo != null) {
        throw new GeneralSecurityException("contextInfo must be null because it is unused");
      }
  
      if (plaintext.length > recordSize - WebPushConstants.CIPHERTEXT_OVERHEAD) {
        throw new GeneralSecurityException("plaintext too long");
      }
  
      // See https://tools.ietf.org/html/rfc8291#section-3.4.
      KeyPair keyPair = EllipticCurves.generateKeyPair(WebPushConstants.NIST_P256_CURVE_TYPE);
      ECPrivateKey ephemeralPrivateKey = (ECPrivateKey) keyPair.getPrivate();
      ECPublicKey ephemeralPublicKey = (ECPublicKey) keyPair.getPublic();
      byte[] ecdhSecret =
          EllipticCurves.computeSharedSecret(ephemeralPrivateKey, recipientPublicPoint);
      byte[] ephemeralPublicKeyBytes =
          EllipticCurves.pointEncode(
              WebPushConstants.NIST_P256_CURVE_TYPE,
              WebPushConstants.UNCOMPRESSED_POINT_FORMAT,
              ephemeralPublicKey.getW());
      byte[] ikm =
          WebPushUtil.computeIkm(ecdhSecret, authSecret, recipientPublicKey, ephemeralPublicKeyBytes);
      byte[] salt = Random.randBytes(WebPushConstants.SALT_SIZE);
      byte[] cek = WebPushUtil.computeCek(ikm, salt);
      byte[] nonce = WebPushUtil.computeNonce(ikm, salt);
      return ByteBuffer.allocate(WebPushConstants.CIPHERTEXT_OVERHEAD + plaintext.length)
          .put(salt)
          .putInt(recordSize)
          .put((byte) WebPushConstants.PUBLIC_KEY_SIZE)
          .put(ephemeralPublicKeyBytes)
          .put(encrypt(cek, nonce, plaintext))
          .array();
    }
focal_method.class_method_signature: WebPushHybridEncrypt.encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */)
focal_method.full_signature: @Override public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */)
focal_method.identifier: encrypt
focal_method.invocations: generateKeyPair getPrivate getPublic computeSharedSecret pointEncode getW computeIkm randBytes computeCek computeNonce array put put put putInt put allocate encrypt
focal_method.modifiers: @Override public
focal_method.parameters: (final byte[] plaintext, final byte[] contextInfo /* unused */)
focal_method.return: byte[]
focal_method.signature: byte[] encrypt(final byte[] plaintext, final byte[] contextInfo /* unused */)