U
    g'                     @   sp   d Z dgZddlmZ ddlmZmZmZmZm	Z	m
Z
mZmZ ddlmZ eddZG dd deZd	d
 ZdS )z
Output Feedback (CFB) mode.
OfbMode    )_copy_bytes)load_pycryptodome_raw_libVoidPointercreate_string_bufferget_raw_bufferSmartPointerc_size_tc_uint8_ptris_writeable_buffer)get_random_byteszCryptodome.Cipher._raw_ofba  
                        int OFB_start_operation(void *cipher,
                                                const uint8_t iv[],
                                                size_t iv_len,
                                                void **pResult);
                        int OFB_encrypt(void *ofbState,
                                        const uint8_t *in,
                                        uint8_t *out,
                                        size_t data_len);
                        int OFB_decrypt(void *ofbState,
                                        const uint8_t *in,
                                        uint8_t *out,
                                        size_t data_len);
                        int OFB_stop_operation(void *state);
                        c                   @   s,   e Zd ZdZdd Zd	ddZd
ddZdS )r   a  *Output FeedBack (OFB)*.

    This mode is very similar to CBC, but it
    transforms the underlying block cipher into a stream cipher.

    The keystream is the iterated block encryption of the
    previous ciphertext block.

    An Initialization Vector (*IV*) is required.

    See `NIST SP800-38A`_ , Section 6.4.

    .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf

    :undocumented: __init__
    c                 C   s   t  | _t| t|tt|| j }|r>t	d| t
| j tj| _|  t|| _tdd|| _| j| _ddg| _dS )aS  Create a new block cipher, configured in OFB mode.

        :Parameters:
          block_cipher : C pointer
            A smart pointer to the low-level block cipher instance.

          iv : bytes/bytearray/memoryview
            The initialization vector to use for encryption or decryption.
            It is as long as the cipher block.

            **The IV must be a nonce, to to be reused for any other
            message**. It shall be a nonce or a random value.

            Reusing the *IV* for encryptions performed with the same key
            compromises confidentiality.
        z)Error %d while instantiating the OFB modeNencryptdecrypt)r   _stateraw_ofb_libZOFB_start_operationgetr
   r	   lenZ
address_of
ValueErrorr   ZOFB_stop_operationrelease
block_sizer   ivIV_next)selfZblock_cipherr   result r   ?/tmp/pip-unpacked-wheel-_q8s9isk/Cryptodome/Cipher/_mode_ofb.py__init__I   s$    



zOfbMode.__init__Nc                 C   s   d| j krtddg| _ |dkr0tt|}n4|}t|sDtdt|t|krdtdt| t| j	 t
|t
|tt|}|rtd| |dkrt|S dS dS )a  Encrypt data with the key and the parameters set at initialization.

        A cipher object is stateful: once you have encrypted a message
        you cannot encrypt (or decrypt) another message using the same
        object.

        The data to encrypt can be broken up in two or
        more pieces and `encrypt` can be called multiple times.

        That is, the statement:

            >>> c.encrypt(a) + c.encrypt(b)

        is equivalent to:

             >>> c.encrypt(a+b)

        This function does not add any padding to the plaintext.

        :Parameters:
          plaintext : bytes/bytearray/memoryview
            The piece of data to encrypt.
            It can be of any length.
        :Keywords:
          output : bytearray/memoryview
            The location where the ciphertext must be written to.
            If ``None``, the ciphertext is returned.
        :Return:
          If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
          Otherwise, ``None``.
        r   z*encrypt() cannot be called after decrypt()N4output must be a bytearray or a writeable memoryview9output must have the same length as the input  (%d bytes)z%Error %d while encrypting in OFB mode)r   	TypeErrorr   r   r   r   r   ZOFB_encryptr   r   r
   r	   r   )r   	plaintextoutput
ciphertextr   r   r   r   r   y   s,    !

zOfbMode.encryptc                 C   s   d| j krtddg| _ |dkr0tt|}n4|}t|sDtdt|t|krdtdt| t| j	 t
|t
|tt|}|rtd| |dkrt|S dS dS )a  Decrypt data with the key and the parameters set at initialization.

        A cipher object is stateful: once you have decrypted a message
        you cannot decrypt (or encrypt) another message with the same
        object.

        The data to decrypt can be broken up in two or
        more pieces and `decrypt` can be called multiple times.

        That is, the statement:

            >>> c.decrypt(a) + c.decrypt(b)

        is equivalent to:

             >>> c.decrypt(a+b)

        This function does not remove any padding from the plaintext.

        :Parameters:
          ciphertext : bytes/bytearray/memoryview
            The piece of data to decrypt.
            It can be of any length.
        :Keywords:
          output : bytearray/memoryview
            The location where the plaintext is written to.
            If ``None``, the plaintext is returned.
        :Return:
          If ``output`` is ``None``, the plaintext is returned as ``bytes``.
          Otherwise, ``None``.
        r   z*decrypt() cannot be called after encrypt()Nr   r   z%Error %d while decrypting in OFB mode)r   r    r   r   r   r   r   ZOFB_decryptr   r   r
   r	   r   )r   r#   r"   r!   r   r   r   r   r      s,    !

zOfbMode.decrypt)N)N)__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   7   s   0
=c                 K   s   |  |}|dd}|dd}d||fkr8t| j}|dk	rR|dk	rVtdn|}t|| jkrrtd| j |rtdt| t||S )a  Instantiate a cipher object that performs OFB encryption/decryption.

    :Parameters:
      factory : module
        The underlying block cipher, a module from ``Cryptodome.Cipher``.

    :Keywords:
      iv : bytes/bytearray/memoryview
        The IV to use for OFB.

      IV : bytes/bytearray/memoryview
        Alias for ``iv``.

    Any other keyword will be passed to the underlying block cipher.
    See the relevant documentation for details (at least ``key`` will need
    to be present).
    r   Nr   )NNz*You must either use 'iv' or 'IV', not bothz.Incorrect IV length (it must be %d bytes long)zUnknown parameters for OFB: %s)	Z_create_base_cipherpopr   r   r    r   r   strr   )factorykwargsZcipher_stater   r   r   r   r   _create_ofb_cipher   s     


r,   N)r'   __all__ZCryptodome.Util.py3compatr   ZCryptodome.Util._raw_apir   r   r   r   r   r	   r
   r   ZCryptodome.Randomr   r   objectr   r,   r   r   r   r   <module>   s   (
 >