docs: def encrypt(self, sa, esp, key):
          """
          Encrypt an ESP packet
  
          @param sa:   the SecurityAssociation associated with the ESP packet.
          @param esp:  an unencrypted _ESPPlain packet with valid padding
          @param key:  the secret key used for encryption
  
          @return:    a valid ESP packet encrypted with this algorithm
          """
          data = esp.data_for_encryption()
  
          if self.cipher:
              mode_iv = self._format_mode_iv(algo=self, sa=sa, iv=esp.iv)
              cipher = self.new_cipher(key, mode_iv)
              encryptor = cipher.encryptor()
  
              if self.is_aead:
                  aad = struct.pack('!LL', esp.spi, esp.seq)
                  encryptor.authenticate_additional_data(aad)
                  data = encryptor.update(data) + encryptor.finalize()
                  data += encryptor.tag[:self.icv_size]
              else:
                  data = encryptor.update(data) + encryptor.finalize()
  
          return ESP(spi=esp.spi, seq=esp.seq, data=esp.iv + data)