Return an iterator that encrypts `data` using the Cipher-Block Chaining
    with Ciphertext Stealing (CBC-CTS) mode of operation.
    
    CBC-CTS mode can only operate on `data` that is greater than 8 bytes in
    length.
    
    Each iteration, except the last, always returns a block-sized :obj:`bytes`
    object (i.e. 8 bytes). The last iteration may return a :obj:`bytes` object
    with a length less than the block-size, if `data` is not a multiple of the
    block-size in length.
    
    `data` should be a :obj:`bytes`-like object that is greater than 8 bytes in
    length.
    If it is not, a :exc:`ValueError` exception is raised.
    
    `init_vector` is the initialization vector and should be a
    :obj:`bytes`-like object with exactly 8 bytes.
    If it is not, a :exc:`ValueError` exception is raised.

def encrypt_cbc_cts(self, data, init_vector):
    """
    Return an iterator that encrypts `data` using the Cipher-Block Chaining
    with Ciphertext Stealing (CBC-CTS) mode of operation.
    
    CBC-CTS mode can only operate on `data` that is greater than 8 bytes in
    length.
    
    Each iteration, except the last, always returns a block-sized :obj:`bytes`
    object (i.e. 8 bytes). The last iteration may return a :obj:`bytes` object
    with a length less than the block-size, if `data` is not a multiple of the
    block-size in length.
    
    `data` should be a :obj:`bytes`-like object that is greater than 8 bytes in
    length.
    If it is not, a :exc:`ValueError` exception is raised.
    
    `init_vector` is the initialization vector and should be a
    :obj:`bytes`-like object with exactly 8 bytes.
    If it is not, a :exc:`ValueError` exception is raised.
    """
    data_len = len(data)
    if data_len <= 8:
      raise ValueError("data is not greater than 8 bytes in length")
    
    S1, S2, S3, S4 = self.S
    P = self.P
    
    u4_1_pack = self._u4_1_pack
    u1_4_unpack = self._u1_4_unpack
    u4_2_pack = self._u4_2_pack
    u4_2_unpack = self._u4_2_unpack
    encrypt = self._encrypt
    
    try:
      prev_cipher_L, prev_cipher_R = u4_2_unpack(init_vector)
    except struct_error:
      raise ValueError("initialization vector is not 8 bytes in length")
      
    extra_bytes = data_len % 8
    last_block_stop_i = data_len - extra_bytes
    
    plain_L, plain_R = u4_2_unpack(data[0:8])
    prev_cipher_L, prev_cipher_R = encrypt(
      plain_L ^ prev_cipher_L,
      plain_R ^ prev_cipher_R,
      P, S1, S2, S3, S4,
      u4_1_pack, u1_4_unpack
    )
    cipher_block = u4_2_pack(prev_cipher_L, prev_cipher_R)
    
    for plain_L, plain_R in self._u4_2_iter_unpack(data[8:last_block_stop_i]):
      yield cipher_block
      prev_cipher_L, prev_cipher_R = encrypt(
        plain_L ^ prev_cipher_L,
        plain_R ^ prev_cipher_R,
        P, S1, S2, S3, S4,
        u4_1_pack, u1_4_unpack
      )
      cipher_block = u4_2_pack(prev_cipher_L, prev_cipher_R)
    
    P_L, P_R = u4_2_unpack(data[last_block_stop_i:] + bytes(8 - extra_bytes))
    
    yield u4_2_pack(
      *encrypt(
        prev_cipher_L ^ P_L,
        prev_cipher_R ^ P_R,
        P, S1, S2, S3, S4,
        u4_1_pack, u1_4_unpack
      )
    )
    
    yield cipher_block[:extra_bytes]