def decrypt(self, esp, key, icv_size=None):
        """
        Decrypt an ESP packet

        @param esp:        an encrypted ESP packet
        @param key:        the secret key used for encryption
        @param icv_size:   the length of the icv used for integrity check

        @return:    a valid ESP packet encrypted with this algorithm
        @raise IPSecIntegrityError: if the integrity check fails with an AEAD
                                    algorithm
        """
        if icv_size is None:
            icv_size = self.icv_size if self.is_aead else 0

        iv = esp.data[:self.iv_size]
        data = esp.data[self.iv_size:len(esp.data) - icv_size]
        icv = esp.data[len(esp.data) - icv_size:]

        if self.cipher:
            cipher = self.new_cipher(key, iv, icv)
            decryptor = cipher.decryptor()

            if self.is_aead:
                # Tag value check is done during the finalize method
                decryptor.authenticate_additional_data(
                    struct.pack('!LL', esp.spi, esp.seq)
                )

            try:
                data = decryptor.update(data) + decryptor.finalize()
            except InvalidTag as err:
                raise IPSecIntegrityError(err)

        # extract padlen and nh
        padlen = (data[-2])
        nh = data[-1]

        # then use padlen to determine data and padding
        data = data[:len(data) - padlen - 2]
        padding = data[len(data) - padlen - 2: len(data) - 2]

        return _ESPPlain(spi=esp.spi,
                        seq=esp.seq,
                        iv=iv,
                        data=data,
                        padding=padding,
                        padlen=padlen,
                        nh=nh,
                        icv=icv)
Decrypt an ESP packet

        @param esp:        an encrypted ESP packet
        @param key:        the secret key used for encryption
        @param icv_size:   the length of the icv used for integrity check

        @return:    a valid ESP packet encrypted with this algorithm
        @raise IPSecIntegrityError: if the integrity check fails with an AEAD
                                    algorithm