@Override
  public ByteBuf decrypt(ByteBuf toDecrypt, SecretKeySpec key) throws GeneralSecurityException {
    ByteBuf decryptedContent = null;
    ByteBuf temp = null;
    try {
      Cipher decrypter = Cipher.getInstance(GCM_CRYPTO_INSTANCE, "BC");
      byte[] iv = deserializeIV(new ByteBufInputStream(toDecrypt));
      decrypter.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
      int outputSize = decrypter.getOutputSize(toDecrypt.readableBytes());
      decryptedContent = PooledByteBufAllocator.DEFAULT.ioBuffer(outputSize);

      ByteBuffer toDecryptBuffer;
      if (toDecrypt.nioBufferCount() != 1) {
        temp = PooledByteBufAllocator.DEFAULT.ioBuffer(toDecrypt.readableBytes());
        temp.writeBytes(toDecrypt);
        toDecryptBuffer = temp.nioBuffer();
      } else {
        toDecryptBuffer = toDecrypt.nioBuffer();
      }

      ByteBuffer decryptedContentBuffer = decryptedContent.nioBuffer(0, outputSize);
      int n = decrypter.doFinal(toDecryptBuffer, decryptedContentBuffer);
      decryptedContent.writerIndex(decryptedContent.writerIndex() + n);
      toDecrypt.skipBytes(toDecrypt.readableBytes());
      return decryptedContent;
    } catch (Exception e) {
      if (toDecrypt != null) {
        toDecrypt.release();
      }
      throw new GeneralSecurityException("Exception thrown while decrypting data", e);
    } finally {
      if (temp != null) {
        temp.release();
      }
    }
  }
Helper function to encrypt ByteBuf 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 ByteBuf} 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 ByteBuf} 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