ByteBuffer encrypt(ByteBuffer toEncrypt, SecretKeySpec key, byte[] iv) throws GeneralSecurityException {
    try {
      Cipher encrypter = Cipher.getInstance(GCM_CRYPTO_INSTANCE, "BC");
      if (iv == null) {
        iv = new byte[ivValSize];
        random.nextBytes(iv);
      }
      encrypter.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
      int outputSize = encrypter.getOutputSize(toEncrypt.remaining());
      ByteBuffer encryptedContent = ByteBuffer.allocate(IVRecord_Format_V1.getIVRecordSize(iv) + outputSize);
      IVRecord_Format_V1.serializeIVRecord(encryptedContent, iv);
      encrypter.doFinal(toEncrypt, encryptedContent);
      encryptedContent.flip();
      return encryptedContent;
    } catch (Exception e) {
      throw new GeneralSecurityException("Exception thrown while encrypting data", e);
    }
  }
Helper function to encrypt ByteBuffer with the given key. When useFixedIv is true, don't use a random iv byte
array, using a all zero byte array instead. Only set it to be true in test.
@param toEncrypt {@link ByteBuffer} that needs to be encrypted
@param key the secret key (of type T) to use to encrypt
@param iv If null, will create a random byte array serve as iv bytes.
@return the {@link ByteBuffer} containing the encrypted content. Ensure the result has all
the information like the IV along with the encrypted content, in order to decrypt the content with a given key
@throws {@link GeneralSecurityException} on any exception with encryption
ambry-router/src/main/java/com/github/ambry/router/GCMCryptoService.java