Exemplo n.º 1
0
class ARC4Cipher:
    """ARC4 cipher object"""

    def __init__(self, key, *args, **kwargs):
        """Initialize an ARC4 cipher object

        See also `new()` at the module level."""

        if len(args) > 0:
            ndrop = args[0]
            args = args[1:]
        else:
            ndrop = kwargs.pop("drop", 0)

        expect_byte_string(key)

        self._state = VoidPointer()
        result = _raw_arc4_lib.ARC4_stream_init(key, c_size_t(len(key)), self._state.address_of())
        if result != 0:
            raise ValueError("Error %d while creating the ARC4 cipher" % result)
        self._state = SmartPointer(self._state.get(), _raw_arc4_lib.ARC4_stream_destroy)

        if ndrop > 0:
            # This is OK even if the cipher is used for decryption, since encrypt
            # and decrypt are actually the same thing with ARC4.
            self.encrypt(b("\x00") * ndrop)

        self.block_size = 1
        self.key_size = len(key)

    def encrypt(self, plaintext):
        """Encrypt a piece of data.

        :Parameters:
          plaintext : byte string
            The piece of data to encrypt. It can be of any size.
        :Return: the encrypted data (byte string, as long as the
          plaintext).
        """

        expect_byte_string(plaintext)
        ciphertext = create_string_buffer(len(plaintext))
        result = _raw_arc4_lib.ARC4_stream_encrypt(self._state.get(), plaintext, ciphertext, c_size_t(len(plaintext)))
        if result:
            raise ValueError("Error %d while encrypting with RC4" % result)
        return get_raw_buffer(ciphertext)

    def decrypt(self, ciphertext):
        """Decrypt a piece of data.

        :Parameters:
          ciphertext : byte string
            The piece of data to decrypt. It can be of any size.
        :Return: the decrypted data (byte string, as long as the
          ciphertext).
        """
        try:
            return self.encrypt(ciphertext)
        except ValueError, e:
            raise ValueError(str(e).replace("enc", "dec"))
Exemplo n.º 2
0
    def __init__(self, key, nonce):
        """Initialize a Salsa20 cipher object

        See also `new()` at the module level."""

        if len(key) not in key_size:
            raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key))

        if len(nonce) != 8:
            raise ValueError("Incorrect nonce length for Salsa20 (%d bytes)" %
                             len(nonce))

        self.nonce = nonce

        expect_byte_string(key)
        expect_byte_string(nonce)

        self._state = VoidPointer()
        result = _raw_salsa20_lib.Salsa20_stream_init(
                        key,
                        c_size_t(len(key)),
                        nonce,
                        c_size_t(len(nonce)),
                        self._state.address_of())
        if result:
            raise ValueError("Error %d instantiating a Salsa20 cipher")
        self._state = SmartPointer(self._state.get(),
                                   _raw_salsa20_lib.Salsa20_stream_destroy)

        self.block_size = 1
        self.key_size = len(key)
Exemplo n.º 3
0
Arquivo: ARC4.py Projeto: cloudera/hue
    def __init__(self, key, *args, **kwargs):
        """Initialize an ARC4 cipher object

        See also `new()` at the module level."""

        if len(args) > 0:
            ndrop = args[0]
            args = args[1:]
        else:
            ndrop = kwargs.pop('drop', 0)

        if len(key) not in key_size:
            raise ValueError("Incorrect ARC4 key length (%d bytes)" %
                             len(key))

        expect_byte_string(key)

        self._state = VoidPointer()
        result = _raw_arc4_lib.ARC4_stream_init(key,
                                                c_size_t(len(key)),
                                                self._state.address_of())
        if result != 0:
            raise ValueError("Error %d while creating the ARC4 cipher"
                             % result)
        self._state = SmartPointer(self._state.get(),
                                   _raw_arc4_lib.ARC4_stream_destroy)

        if ndrop > 0:
            # This is OK even if the cipher is used for decryption,
            # since encrypt and decrypt are actually the same thing
            # with ARC4.
            self.encrypt(b('\x00') * ndrop)

        self.block_size = 1
        self.key_size = len(key)
Exemplo n.º 4
0
    def __init__(self, x, y, curve="p256"):

        try:
            self._curve = _curves[curve]
        except KeyError:
            raise ValueError("Unknown curve name %s" % str(curve))
        self._curve_name = curve

        modulus_bytes = self.size_in_bytes()
        context = self._curve.context

        xb = long_to_bytes(x, modulus_bytes)
        yb = long_to_bytes(y, modulus_bytes)
        if len(xb) != modulus_bytes or len(yb) != modulus_bytes:
            raise ValueError("Incorrect coordinate length")

        self._point = VoidPointer()
        result = _ec_lib.ec_ws_new_point(self._point.address_of(),
                                         c_uint8_ptr(xb),
                                         c_uint8_ptr(yb),
                                         c_size_t(modulus_bytes),
                                         context.get())
        if result:
            if result == 15:
                raise ValueError("The EC point does not belong to the curve")
            raise ValueError("Error %d while instantiating an EC point" % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the EC point
        self._point = SmartPointer(self._point.get(),
                                   _ec_lib.ec_free_point)
Exemplo n.º 5
0
    def __init__(self, factory, nonce, mac_len, cipher_params):

        if factory.block_size != 16:
            raise ValueError("OCB mode is only available for ciphers" " that operate on 128 bits blocks")

        self.block_size = 16
        """The block size of the underlying cipher, in bytes."""

        self.nonce = nonce
        """Nonce used for this session."""
        if len(nonce) not in range(1, 16):
            raise ValueError("Nonce must be at most 15 bytes long")

        self._mac_len = mac_len
        if not 8 <= mac_len <= 16:
            raise ValueError("MAC tag must be between 8 and 16 bytes long")

        # Cache for MAC tag
        self._mac_tag = None

        # Cache for unaligned associated data
        self._cache_A = b("")

        # Cache for unaligned ciphertext/plaintext
        self._cache_P = b("")

        # Allowed transitions after initialization
        self._next = [self.update, self.encrypt, self.decrypt, self.digest, self.verify]

        # Compute Offset_0
        params_without_key = dict(cipher_params)
        key = params_without_key.pop("key")
        nonce = bchr(self._mac_len << 4 & 0xFF) + bchr(0) * (14 - len(self.nonce)) + bchr(1) + self.nonce
        bottom = bord(nonce[15]) & 0x3F  # 6 bits, 0..63
        ktop = factory.new(key, factory.MODE_ECB, **params_without_key).encrypt(
            nonce[:15] + bchr(bord(nonce[15]) & 0xC0)
        )
        stretch = ktop + strxor(ktop[:8], ktop[1:9])  # 192 bits
        offset_0 = long_to_bytes(bytes_to_long(stretch) >> (64 - bottom), 24)[8:]

        # Create low-level cipher instance
        raw_cipher = factory._create_base_cipher(cipher_params)
        if cipher_params:
            raise TypeError("Unknown keywords: " + str(cipher_params))

        self._state = VoidPointer()
        result = _raw_ocb_lib.OCB_start_operation(
            raw_cipher.get(), offset_0, c_size_t(len(offset_0)), self._state.address_of()
        )
        if result:
            raise ValueError("Error %d while instantiating the OCB mode" % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(), _raw_ocb_lib.OCB_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        raw_cipher.release()
Exemplo n.º 6
0
    def __init__(self, block_cipher, initial_counter_block,
                 prefix_len, counter_len, little_endian):
        """Create a new block cipher, configured in CTR mode.

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

          initial_counter_block : byte string
            The initial plaintext to use to generate the key stream.

            It is as large as the cipher block, and it embeds
            the initial value of the counter.

            This value must not be reused.
            It shall contain a nonce or a random component.
            Reusing the *initial counter block* for encryptions
            performed with the same key compromises confidentiality.

          prefix_len : integer
            The amount of bytes at the beginning of the counter block
            that never change.

          counter_len : integer
            The length in bytes of the counter embedded in the counter
            block.

          little_endian : boolean
            True if the counter in the counter block is an integer encoded
            in little endian mode. If False, it is big endian.
        """

        expect_byte_string(initial_counter_block)
        self._state = VoidPointer()
        result = raw_ctr_lib.CTR_start_operation(block_cipher.get(),
                                                 initial_counter_block,
                                                 c_size_t(len(initial_counter_block)),
                                                 c_size_t(prefix_len),
                                                 counter_len,
                                                 little_endian,
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %X while instatiating the CTR mode"
                             % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   raw_ctr_lib.CTR_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        block_cipher.release()

        #: The block size of the underlying cipher, in bytes.
        self.block_size = len(initial_counter_block)

        self._next = [ self.encrypt, self.decrypt ]
Exemplo n.º 7
0
    def set(self, point):
        self._point = VoidPointer()
        result = _ec_lib.ec_ws_clone(self._point.address_of(),
                                     point._point.get())
        if result:
            raise ValueError("Error %d while cloning an EC point" % result)

        self._point = SmartPointer(self._point.get(),
                                   _ec_lib.ec_free_point)
        return self
Exemplo n.º 8
0
    def __init__(self, subkey):
        assert len(subkey) == 16

        self._exp_key = VoidPointer()
        result = _raw_galois_lib.ghash_expand(c_uint8_ptr(subkey),
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)

        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        # create_string_buffer always returns a string of zeroes
        self._last_y = create_string_buffer(16)
Exemplo n.º 9
0
    def __init__(self, block_cipher, iv, segment_size):
        """Create a new block cipher, configured in CFB mode.

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

          iv : byte string
            The initialization vector to use for encryption or decryption.
            It is as long as the cipher block.

            **The IV must be unpredictable**. Ideally it is picked randomly.

            Reusing the *IV* for encryptions performed with the same key
            compromises confidentiality.

          segment_size : integer
            The number of bytes the plaintext and ciphertext are segmented in.
        """

        expect_byte_string(iv)
        self._state = VoidPointer()
        result = raw_cfb_lib.CFB_start_operation(block_cipher.get(),
                                                 iv,
                                                 c_size_t(len(iv)),
                                                 c_size_t(segment_size),
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %d while instatiating the CFB mode" % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   raw_cfb_lib.CFB_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        block_cipher.release()

        self.block_size = len(iv)
        """The block size of the underlying cipher, in bytes."""

        self.iv = iv
        """The Initialization Vector originally used to create the object.
        The value does not change."""

        self.IV = iv
        """Alias for `iv`"""

        self._next = [ self.encrypt, self.decrypt ]
Exemplo n.º 10
0
    def __init__(self, hash_subkey, block_size):
        _SmoothMAC.__init__(self, block_size, None, 0)

        self._key = hash_subkey
        self._exp_key = VoidPointer()
        expect_byte_string(self._key)
        result = _raw_galois_lib.ghash_expand(self._key, self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)
        self._exp_key = SmartPointer(self._exp_key.get(), _raw_galois_lib.ghash_destroy)

        self._last_y = create_string_buffer(16)
        for i in xrange(16):
            self._last_y[i] = bchr(0)
        self._mac = _raw_galois_lib.ghash
Exemplo n.º 11
0
class _GHASH(_SmoothMAC):
    """GHASH function defined in NIST SP 800-38D, Algorithm 2.

    If X_1, X_2, .. X_m are the blocks of input data, the function
    computes:

       X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H

    in the Galois field GF(2^256) using the reducing polynomial
    (x^128 + x^7 + x^2 + x + 1).
    """

    def __init__(self, hash_subkey, block_size):
        _SmoothMAC.__init__(self, block_size, None, 0)

        self._key = hash_subkey
        self._exp_key = VoidPointer()
        expect_byte_string(self._key)
        result = _raw_galois_lib.ghash_expand(self._key,
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)
        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        self._last_y = create_string_buffer(16)
        for i in xrange(16):
            self._last_y[i] = bchr(0)
        self._mac = _raw_galois_lib.ghash

    def copy(self):
        clone = _GHASH(self._key, self._bs)
        _SmoothMAC._deep_copy(self, clone)
        clone._last_y = self._last_y
        return clone

    def _update(self, block_data):
        expect_byte_string(block_data)
        result = _raw_galois_lib.ghash(self._last_y,
                                       block_data,
                                       c_size_t(len(block_data)),
                                       self._last_y,
                                       self._exp_key.get())
        if result:
            raise ValueError("Error %d while updating GMAC" % result)

    def _digest(self, left_data):
        return get_raw_buffer(self._last_y)
Exemplo n.º 12
0
def init_p256():
    p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
    b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
    order = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
    Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
    Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5

    p256_modulus = long_to_bytes(p, 32)
    p256_b = long_to_bytes(b, 32)
    p256_order = long_to_bytes(order, 32)

    ec_p256_context = VoidPointer()
    result = _ec_lib.ec_ws_new_context(ec_p256_context.address_of(),
                                       c_uint8_ptr(p256_modulus),
                                       c_uint8_ptr(p256_b),
                                       c_uint8_ptr(p256_order),
                                       c_size_t(len(p256_modulus)),
                                       c_ulonglong(getrandbits(64)))
    if result:
        raise ImportError("Error %d initializing P-256 context" % result)

    context = SmartPointer(ec_p256_context.get(), _ec_lib.ec_free_context)
    p256 = _Curve(
        Integer(p),
        Integer(b),
        Integer(order),
        Integer(Gx),
        Integer(Gy),
        None,
        "1.2.840.10045.3.1.7",  # ANSI X9.62
        context,
        "NIST P-256",
        "ecdsa-sha2-nistp256")
    _curves.update(dict.fromkeys(p256_names, p256))
Exemplo n.º 13
0
def init_p521():
    p = 0x000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    b = 0x00000051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00
    order = 0x000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409
    Gx = 0x000000c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66
    Gy = 0x0000011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650

    p521_modulus = long_to_bytes(p, 66)
    p521_b = long_to_bytes(b, 66)
    p521_order = long_to_bytes(order, 66)

    ec_p521_context = VoidPointer()
    result = _ec_lib.ec_ws_new_context(ec_p521_context.address_of(),
                                       c_uint8_ptr(p521_modulus),
                                       c_uint8_ptr(p521_b),
                                       c_uint8_ptr(p521_order),
                                       c_size_t(len(p521_modulus)),
                                       c_ulonglong(getrandbits(64)))
    if result:
        raise ImportError("Error %d initializing P-521 context" % result)

    context = SmartPointer(ec_p521_context.get(), _ec_lib.ec_free_context)
    p521 = _Curve(
        Integer(p),
        Integer(b),
        Integer(order),
        Integer(Gx),
        Integer(Gy),
        None,
        "1.3.132.0.35",  # SEC 2
        context,
        "NIST P-521",
        "ecdsa-sha2-nistp521")
    _curves.update(dict.fromkeys(p521_names, p521))
Exemplo n.º 14
0
    def __init__(self, subkey):
        assert len(subkey) == 16

        expect_byte_string(subkey)
        self._exp_key = VoidPointer()
        result = _raw_galois_lib.ghash_expand(subkey,
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)

        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        self._last_y = create_string_buffer(16)
        for i in range(16):
            self._last_y[i] = bchr(0)
Exemplo n.º 15
0
def _create_base_cipher(dict_parameters):
    """This method instantiates and returns a handle to a low-level
    base cipher. It will absorb named parameters in the process."""

    use_aesni = dict_parameters.pop("use_aesni", True)

    try:
        key = dict_parameters.pop("key")
    except KeyError:
        raise TypeError("Missing 'key' parameter")

    if len(key) not in key_size:
        raise ValueError("Incorrect AES key length (%d bytes)" % len(key))

    if use_aesni and _raw_aesni_lib:
        start_operation = _raw_aesni_lib.AESNI_start_operation
        stop_operation = _raw_aesni_lib.AESNI_stop_operation
    else:
        start_operation = _raw_aes_lib.AES_start_operation
        stop_operation = _raw_aes_lib.AES_stop_operation

    cipher = VoidPointer()
    result = start_operation(c_uint8_ptr(key),
                             c_size_t(len(key)),
                             cipher.address_of())
    if result:
        raise ValueError("Error %X while instantiating the AES cipher"
                         % result)
    return SmartPointer(cipher.get(), stop_operation)
Exemplo n.º 16
0
def _create_base_cipher(dict_parameters):
    """This method instantiates and returns a handle to a low-level
    base cipher. It will absorb named parameters in the process."""

    try:
        key = dict_parameters.pop("key")
    except KeyError:
        raise TypeError("Missing 'key' parameter")

    effective_keylen = dict_parameters.pop("effective_keylen", 1024)

    if len(key) not in key_size:
        raise ValueError("Incorrect ARC2 key length (%d bytes)" % len(key))

    if not (40 <= effective_keylen <= 1024):
        raise ValueError(
            "'effective_key_len' must be at least 40 and no larger than 1024 "
            "(not %d)" % effective_keylen)

    start_operation = _raw_arc2_lib.ARC2_start_operation
    stop_operation = _raw_arc2_lib.ARC2_stop_operation

    cipher = VoidPointer()
    result = start_operation(c_uint8_ptr(key), c_size_t(len(key)),
                             c_size_t(effective_keylen), cipher.address_of())
    if result:
        raise ValueError("Error %X while instantiating the ARC2 cipher" %
                         result)

    return SmartPointer(cipher.get(), stop_operation)
    def __init__(self, subkey, ghash_c):
        assert len(subkey) == 16

        self.ghash_c = ghash_c

        self._exp_key = VoidPointer()
        result = ghash_c.ghash_expand(c_uint8_ptr(subkey),
                                      self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GHASH key" % result)

        self._exp_key = SmartPointer(self._exp_key.get(),
                                     ghash_c.ghash_destroy)

        # create_string_buffer always returns a string of zeroes
        self._last_y = create_string_buffer(16)
Exemplo n.º 18
0
    def __init__(self, data, digest_bytes, update_after_digest):
        # The size of the resulting hash in bytes.
        self.digest_size = digest_bytes

        self._update_after_digest = update_after_digest
        self._digest_done = False

        state = VoidPointer()
        result = _raw_keccak_lib.keccak_init(state.address_of(),
                                             c_size_t(self.digest_size * 2),
                                             0x01)
        if result:
            raise ValueError("Error %d while instantiating keccak" % result)
        self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy)
        if data:
            self.update(data)
Exemplo n.º 19
0
def _create_base_cipher(dict_parameters):
    """This method instantiates and returns a smart pointer to
    a low-level base cipher. It will absorb named parameters in
    the process."""

    try:
        key = dict_parameters.pop("key")
        salt = dict_parameters.pop("salt")
        cost = dict_parameters.pop("cost")
    except KeyError as e:
        raise TypeError("Missing EKSBlowfish parameter: " + str(e))
    invert = dict_parameters.pop("invert", True)

    if len(key) not in key_size:
        raise ValueError("Incorrect EKSBlowfish key length (%d bytes)" % len(key))

    start_operation = _raw_blowfish_lib.EKSBlowfish_start_operation
    stop_operation = _raw_blowfish_lib.EKSBlowfish_stop_operation

    void_p = VoidPointer()
    result = start_operation(c_uint8_ptr(key),
                             c_size_t(len(key)),
                             c_uint8_ptr(salt),
                             c_size_t(len(salt)),
                             c_uint(cost),
                             c_uint(int(invert)),
                             void_p.address_of())
    if result:
        raise ValueError("Error %X while instantiating the EKSBlowfish cipher"
                         % result)
    return SmartPointer(void_p.get(), stop_operation)
Exemplo n.º 20
0
def _create_base_cipher(dict_parameters):
    """This method instantiates and returns a handle to a low-level
    base cipher. It will absorb named parameters in the process."""

    try:
        key = dict_parameters.pop("key")
    except KeyError:
        raise TypeError("Missing 'key' parameter")

    expect_byte_string(key)

    if len(key) not in key_size:
        raise ValueError("Incorrect CAST key length (%d bytes)" % len(key))

    start_operation = _raw_cast_lib.CAST_start_operation
    stop_operation = _raw_cast_lib.CAST_stop_operation

    cipher = VoidPointer()
    result = start_operation(key,
                             c_size_t(len(key)),
                             cipher.address_of())
    if result:
        raise ValueError("Error %X while instantiating the CAST cipher"
                         % result)

    return SmartPointer(cipher.get(), stop_operation)
Exemplo n.º 21
0
    def __init__(self, data, update_after_digest):
        self._update_after_digest = update_after_digest
        self._digest_done = False
        self._padding = 0x06

        state = VoidPointer()
        result = _raw_keccak_lib.keccak_init(state.address_of(),
                                             c_size_t(self.digest_size * 2),
                                             c_ubyte(24))
        if result:
            raise ValueError("Error %d while instantiating SHA-3/512"
                             % result)
        self._state = SmartPointer(state.get(),
                                   _raw_keccak_lib.keccak_destroy)
        if data:
            self.update(data)
Exemplo n.º 22
0
    def __init__(self, data, key, digest_bytes):
        """
        Initialize a BLAKE2s hash object.
        """

        #: The size of the resulting hash in bytes.
        self.digest_size = digest_bytes

        # See https://tools.ietf.org/html/draft-saarinen-blake2-02
        if digest_bytes in (16, 20, 28, 32) and not key:
            self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes)

        expect_byte_string(key)

        state = VoidPointer()
        result = _raw_blake2s_lib.blake2s_init(state.address_of(),
                                               key,
                                               c_size_t(len(key)),
                                               c_size_t(digest_bytes)
                                               )
        if result:
            raise ValueError("Error %d while instantiating BLAKE2s" % result)
        self._state = SmartPointer(state.get(),
                                   _raw_blake2s_lib.blake2s_destroy)
        if data:
            self.update(data)
Exemplo n.º 23
0
def init_p384():
    p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff
    b = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef
    order = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973
    Gx = 0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7
    Gy = 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F

    p384_modulus = long_to_bytes(p, 48)
    p384_b = long_to_bytes(b, 48)
    p384_order = long_to_bytes(order, 48)

    ec_p384_context = VoidPointer()
    result = _ec_lib.ec_ws_new_context(ec_p384_context.address_of(),
                                       c_uint8_ptr(p384_modulus),
                                       c_uint8_ptr(p384_b),
                                       c_uint8_ptr(p384_order),
                                       c_size_t(len(p384_modulus)),
                                       c_ulonglong(getrandbits(64)))
    if result:
        raise ImportError("Error %d initializing P-384 context" % result)

    context = SmartPointer(ec_p384_context.get(), _ec_lib.ec_free_context)
    p384 = _Curve(
        Integer(p),
        Integer(b),
        Integer(order),
        Integer(Gx),
        Integer(Gy),
        None,
        "1.3.132.0.34",  # SEC 2
        context,
        "NIST P-384",
        "ecdsa-sha2-nistp384")
    _curves.update(dict.fromkeys(p384_names, p384))
Exemplo n.º 24
0
    def __init__(self, data, key, digest_bytes, update_after_digest):

        # The size of the resulting hash in bytes.
        self.digest_size = digest_bytes

        self._update_after_digest = update_after_digest
        self._digest_done = False

        # See https://tools.ietf.org/html/rfc7693
        if digest_bytes in (20, 32, 48, 64) and not key:
            self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes)

        expect_byte_string(key)

        state = VoidPointer()
        result = _raw_blake2b_lib.blake2b_init(state.address_of(),
                                               key,
                                               c_size_t(len(key)),
                                               c_size_t(digest_bytes)
                                               )
        if result:
            raise ValueError("Error %d while instantiating BLAKE2b" % result)
        self._state = SmartPointer(state.get(),
                                   _raw_blake2b_lib.blake2b_destroy)
        if data:
            self.update(data)
Exemplo n.º 25
0
    def __init__(self, data, truncate):
        self._truncate = truncate

        if truncate is None:
            self.oid = "2.16.840.1.101.3.4.2.3"
            self.digest_size = 64
        elif truncate == "224":
            self.oid = "2.16.840.1.101.3.4.2.5"
            self.digest_size = 28
        elif truncate == "256":
            self.oid = "2.16.840.1.101.3.4.2.6"
            self.digest_size = 32
        else:
            raise ValueError("Incorrect truncation length. It must be '224' or '256'.")

        state = VoidPointer()
        result = _raw_sha512_lib.SHA512_init(state.address_of(),
                                             c_size_t(self.digest_size))
        if result:
            raise ValueError("Error %d while instantiating SHA-512"
                             % result)
        self._state = SmartPointer(state.get(),
                                   _raw_sha512_lib.SHA512_destroy)
        if data:
            self.update(data)
Exemplo n.º 26
0
    def __init__(self, subkey):
        assert len(subkey) == 16

        expect_byte_string(subkey)
        self._exp_key = VoidPointer()
        result = _raw_galois_lib.ghash_expand(subkey,
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)

        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        self._last_y = create_string_buffer(16)
        for i in range(16):
            self._last_y[i] = bchr(0)
Exemplo n.º 27
0
    def __init__(self, block_cipher, iv):
        """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.
        """

        self._state = VoidPointer()
        result = raw_ofb_lib.OFB_start_operation(block_cipher.get(),
                                                 c_uint8_ptr(iv),
                                                 c_size_t(len(iv)),
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %d while instatiating the OFB mode"
                             % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   raw_ofb_lib.OFB_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        block_cipher.release()

        self.block_size = len(iv)
        """The block size of the underlying cipher, in bytes."""

        self.iv = _copy_bytes(None, None, iv)
        """The Initialization Vector originally used to create the object.
        The value does not change."""

        self.IV = self.iv
        """Alias for `iv`"""

        self._next = [ self.encrypt, self.decrypt ]
Exemplo n.º 28
0
    def __init__(self, block_cipher, iv):
        """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.
        """

        self._state = VoidPointer()
        result = raw_ofb_lib.OFB_start_operation(block_cipher.get(),
                                                 c_uint8_ptr(iv),
                                                 c_size_t(len(iv)),
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %d while instatiating the OFB mode" %
                             result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   raw_ofb_lib.OFB_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        block_cipher.release()

        self.block_size = len(iv)
        """The block size of the underlying cipher, in bytes."""

        self.iv = _copy_bytes(None, None, iv)
        """The Initialization Vector originally used to create the object.
        The value does not change."""

        self.IV = self.iv
        """Alias for `iv`"""

        self._next = [self.encrypt, self.decrypt]
Exemplo n.º 29
0
    def __init__(self, hash_subkey, block_size):
        _SmoothMAC.__init__(self, block_size, None, 0)

        self._key = hash_subkey
        self._exp_key = VoidPointer()
        expect_byte_string(self._key)
        result = _raw_galois_lib.ghash_expand(self._key,
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)
        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        self._last_y = create_string_buffer(16)
        for i in xrange(16):
            self._last_y[i] = bchr(0)
        self._mac = _raw_galois_lib.ghash
Exemplo n.º 30
0
    def __init__(self, block_cipher, iv):
        """Create a new block cipher, configured in CBC mode.

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

          iv : byte string
            The initialization vector to use for encryption or decryption.
            It is as long as the cipher block.

            **The IV must be unpredictable**. Ideally it is picked randomly.

            Reusing the *IV* for encryptions performed with the same key
            compromises confidentiality.
        """

        expect_byte_string(iv)
        self._state = VoidPointer()
        result = raw_cbc_lib.CBC_start_operation(block_cipher.get(), iv,
                                                 c_size_t(len(iv)),
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %d while instatiating the CBC mode" %
                             result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   raw_cbc_lib.CBC_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        block_cipher.release()

        self.block_size = len(iv)
        """The block size of the underlying cipher, in bytes."""

        self.iv = iv
        """The Initialization Vector originally used to create the object.
        The value does not change."""

        self.IV = iv
        """Alias for `iv`"""

        self._next = [self.encrypt, self.decrypt]
Exemplo n.º 31
0
class _GHASH(_SmoothMAC):
    """GHASH function defined in NIST SP 800-38D, Algorithm 2.

    If X_1, X_2, .. X_m are the blocks of input data, the function
    computes:

       X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H

    in the Galois field GF(2^256) using the reducing polynomial
    (x^128 + x^7 + x^2 + x + 1).
    """
    def __init__(self, hash_subkey, block_size):
        _SmoothMAC.__init__(self, block_size, None, 0)

        self._key = hash_subkey
        self._exp_key = VoidPointer()
        expect_byte_string(self._key)
        result = _raw_galois_lib.ghash_expand(self._key,
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)
        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        self._last_y = create_string_buffer(16)
        for i in xrange(16):
            self._last_y[i] = bchr(0)
        self._mac = _raw_galois_lib.ghash

    def copy(self):
        clone = _GHASH(self._key, self._bs)
        _SmoothMAC._deep_copy(self, clone)
        clone._last_y = self._last_y
        return clone

    def _update(self, block_data):
        expect_byte_string(block_data)
        result = _raw_galois_lib.ghash(self._last_y, block_data,
                                       c_size_t(len(block_data)), self._last_y,
                                       self._exp_key.get())
        if result:
            raise ValueError("Error %d while updating GMAC" % result)

    def _digest(self, left_data):
        return get_raw_buffer(self._last_y)
Exemplo n.º 32
0
class _GHASH(object):
    """GHASH function defined in NIST SP 800-38D, Algorithm 2.

    If X_1, X_2, .. X_m are the blocks of input data, the function
    computes:

       X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H

    in the Galois field GF(2^256) using the reducing polynomial
    (x^128 + x^7 + x^2 + x + 1).
    """

    def __init__(self, subkey):
        assert len(subkey) == 16

        expect_byte_string(subkey)
        self._exp_key = VoidPointer()
        result = _raw_galois_lib.ghash_expand(subkey,
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)

        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        self._last_y = create_string_buffer(16)
        for i in range(16):
            self._last_y[i] = bchr(0)

    def update(self, block_data):
        assert len(block_data) % 16 == 0

        expect_byte_string(block_data)
        result = _raw_galois_lib.ghash(self._last_y,
                                       block_data,
                                       c_size_t(len(block_data)),
                                       self._last_y,
                                       self._exp_key.get())
        if result:
            raise ValueError("Error %d while updating GMAC" % result)

        return self

    def digest(self):
        return get_raw_buffer(self._last_y)
Exemplo n.º 33
0
 def __init__(self, data=None):
     state = VoidPointer()
     result = _raw_keccak_lib.keccak_init(state.address_of(), c_size_t(64), 0x1F)
     if result:
         raise ValueError("Error %d while instantiating SHAKE256" % result)
     self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy)
     self._is_squeezing = False
     if data:
         self.update(data)
Exemplo n.º 34
0
    def __init__(self, key, nonce):
        """Initialize a ChaCha20 cipher object

        See also `new()` at the module level."""

        self.nonce = _copy_bytes(None, None, nonce)

        self._next = (self.encrypt, self.decrypt)
        self._state = VoidPointer()
        result = _raw_chacha20_lib.chacha20_init(self._state.address_of(),
                                                 c_uint8_ptr(key),
                                                 c_size_t(len(key)),
                                                 self.nonce,
                                                 c_size_t(len(nonce)))
        if result:
            raise ValueError("Error %d instantiating a ChaCha20 cipher")
        self._state = SmartPointer(self._state.get(),
                                   _raw_chacha20_lib.chacha20_destroy)
Exemplo n.º 35
0
    def __init__(self, r, s, data):

        if len(r) != 16:
            raise ValueError("Paramater r is not 16 bytes long")
        if len(s) != 16:
            raise ValueError("Parameter s is not 16 bytes long")

        self._mac_tag = None

        state = VoidPointer()
        result = _raw_poly1305.poly1305_init(state.address_of(),
                                             c_uint8_ptr(r), c_size_t(len(r)),
                                             c_uint8_ptr(s), c_size_t(len(s)))
        if result:
            raise ValueError("Error %d while instantiating Poly1305" % result)
        self._state = SmartPointer(state.get(), _raw_poly1305.poly1305_destroy)
        if data:
            self.update(data)
Exemplo n.º 36
0
class _GHASH(object):
    """GHASH function defined in NIST SP 800-38D, Algorithm 2.

    If X_1, X_2, .. X_m are the blocks of input data, the function
    computes:

       X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H

    in the Galois field GF(2^256) using the reducing polynomial
    (x^128 + x^7 + x^2 + x + 1).
    """

    def __init__(self, subkey):
        assert len(subkey) == 16

        expect_byte_string(subkey)
        self._exp_key = VoidPointer()
        result = _raw_galois_lib.ghash_expand(subkey,
                                              self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GMAC key" % result)

        self._exp_key = SmartPointer(self._exp_key.get(),
                                     _raw_galois_lib.ghash_destroy)

        # create_string_buffer always returns a string of zeroes
        self._last_y = create_string_buffer(16)

    def update(self, block_data):
        assert len(block_data) % 16 == 0

        expect_byte_string(block_data)
        result = _raw_galois_lib.ghash(self._last_y,
                                       block_data,
                                       c_size_t(len(block_data)),
                                       self._last_y,
                                       self._exp_key.get())
        if result:
            raise ValueError("Error %d while updating GMAC" % result)

        return self

    def digest(self):
        return get_raw_buffer(self._last_y)
Exemplo n.º 37
0
class _GHASH(object):
    """GHASH function defined in NIST SP 800-38D, Algorithm 2.

    If X_1, X_2, .. X_m are the blocks of input data, the function
    computes:

       X_1*H^{m} + X_2*H^{m-1} + ... + X_m*H

    in the Galois field GF(2^256) using the reducing polynomial
    (x^128 + x^7 + x^2 + x + 1).
    """

    def __init__(self, subkey, ghash_c):
        assert len(subkey) == 16

        self.ghash_c = ghash_c

        self._exp_key = VoidPointer()
        result = ghash_c.ghash_expand(c_uint8_ptr(subkey),
                                      self._exp_key.address_of())
        if result:
            raise ValueError("Error %d while expanding the GHASH key" % result)

        self._exp_key = SmartPointer(self._exp_key.get(),
                                     ghash_c.ghash_destroy)

        # create_string_buffer always returns a string of zeroes
        self._last_y = create_string_buffer(16)

    def update(self, block_data):
        assert len(block_data) % 16 == 0

        result = self.ghash_c.ghash(self._last_y,
                                    c_uint8_ptr(block_data),
                                    c_size_t(len(block_data)),
                                    self._last_y,
                                    self._exp_key.get())
        if result:
            raise ValueError("Error %d while updating GHASH" % result)

        return self

    def digest(self):
        return get_raw_buffer(self._last_y)
Exemplo n.º 38
0
 def __init__(self, data=None):
     state = VoidPointer()
     result = _raw_ripemd160_lib.ripemd160_init(state.address_of())
     if result:
         raise ValueError("Error %d while instantiating RIPEMD160"
                          % result)
     self._state = SmartPointer(state.get(),
                                _raw_ripemd160_lib.ripemd160_destroy)
     if data:
         self.update(data)
Exemplo n.º 39
0
 def _create_keccak(self):
     state = VoidPointer()
     result = _raw_keccak_lib.keccak_init(
         state.address_of(),
         c_size_t(32),  # 32 bytes of capacity (256 bits)
         c_ubyte(12))  # Reduced number of rounds
     if result:
         raise ValueError("Error %d while instantiating KangarooTwelve" %
                          result)
     return SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy)
    def __init__(self, key, nonce):
        """Initialize a ChaCha20 cipher object

        See also `new()` at the module level."""

        self.nonce = _copy_bytes(None, None, nonce)

        self._next = ( self.encrypt, self.decrypt )
        self._state = VoidPointer()
        result = _raw_chacha20_lib.chacha20_init(
                        self._state.address_of(),
                        c_uint8_ptr(key),
                        c_size_t(len(key)),
                        self.nonce,
                        c_size_t(len(nonce)))
        if result:
            raise ValueError("Error %d instantiating a ChaCha20 cipher")
        self._state = SmartPointer(self._state.get(),
                                   _raw_chacha20_lib.chacha20_destroy)
Exemplo n.º 41
0
 def __init__(self, data=None):
     state = VoidPointer()
     result = _raw_sha3_384_lib.SHA3_384_init(state.address_of())
     if result:
         raise ValueError("Error %d while instantiating SHA-3/384"
                          % result)
     self._state = SmartPointer(state.get(),
                                _raw_sha3_384_lib.SHA3_384_destroy)
     if data:
         self.update(data)
Exemplo n.º 42
0
    def __init__(self, key, nonce):
        """Initialize a Salsa20 cipher object

        See also `new()` at the module level."""

        expect_byte_string(key)
        expect_byte_string(nonce)

        self._state = VoidPointer()
        result = _raw_salsa20_lib.Salsa20_stream_init(key, c_size_t(len(key)),
                                                      nonce,
                                                      c_size_t(len(nonce)),
                                                      self._state.address_of())
        if result:
            raise ValueError("Error %d instantiating a Salsa20 cipher")
        self._state = SmartPointer(self._state.get(),
                                   _raw_salsa20_lib.Salsa20_stream_destroy)

        self.block_size = 1
        self.key_size = len(key)
Exemplo n.º 43
0
    def __init__(self, x, y):
        xb = long_to_bytes(x, 32)
        yb = long_to_bytes(y, 32)
        assert (len(xb) == 32)
        assert (len(yb) == 32)

        self._point = VoidPointer()
        result = _ec_lib.ec_ws_new_point(self._point.address_of(),
                                         c_uint8_ptr(xb), c_uint8_ptr(yb),
                                         c_size_t(len(xb)),
                                         _ec_p256_context.get())
        if result:
            if result == 15:
                raise ValueError("The EC point does not belong to the curve")
            raise ValueError("Error %d while instantiating an EC point" %
                             result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the EC point
        self._point = SmartPointer(self._point.get(), _ec_lib.ec_free_point)
Exemplo n.º 44
0
    def __init__(self, data, key, digest_bytes, update_after_digest):

        # The size of the resulting hash in bytes.
        self.digest_size = digest_bytes

        self._update_after_digest = update_after_digest
        self._digest_done = False

        # See https://tools.ietf.org/html/rfc7693
        if digest_bytes in (16, 20, 28, 32) and not key:
            self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes)

        state = VoidPointer()
        result = _raw_blake2s_lib.blake2s_init(state.address_of(),
                                               c_uint8_ptr(key),
                                               c_size_t(len(key)),
                                               c_size_t(digest_bytes))
        if result:
            raise ValueError("Error %d while instantiating BLAKE2s" % result)
        self._state = SmartPointer(state.get(),
                                   _raw_blake2s_lib.blake2s_destroy)
        if data:
            self.update(data)
Exemplo n.º 45
0
    def __init__(self, block_cipher):
        """Create a new block cipher, configured in ECB mode.

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

        self._state = VoidPointer()
        result = raw_ecb_lib.ECB_start_operation(block_cipher.get(),
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %d while instantiating the ECB mode"
                             % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher
        # mode
        self._state = SmartPointer(self._state.get(),
                                   raw_ecb_lib.ECB_stop_operation)

        # Memory allocated for the underlying block cipher is now owned
        # by the cipher mode
        block_cipher.release()
Exemplo n.º 46
0
    def __init__(self, data, truncate):
        self._truncate = truncate

        if truncate is None:
            self.oid = "2.16.840.1.101.3.4.2.3"
            self.digest_size = 64
        elif truncate == "224":
            self.oid = "2.16.840.1.101.3.4.2.5"
            self.digest_size = 28
        elif truncate == "256":
            self.oid = "2.16.840.1.101.3.4.2.6"
            self.digest_size = 32
        else:
            raise ValueError(
                "Incorrect truncation length. It must be '224' or '256'.")

        state = VoidPointer()
        result = _raw_sha512_lib.SHA512_init(state.address_of(),
                                             c_size_t(self.digest_size))
        if result:
            raise ValueError("Error %d while instantiating SHA-512" % result)
        self._state = SmartPointer(state.get(), _raw_sha512_lib.SHA512_destroy)
        if data:
            self.update(data)
Exemplo n.º 47
0
    def __init__(self, data, custom, capacity, function):
        state = VoidPointer()

        if custom or function:
            prefix_unpad = _encode_str(function) + _encode_str(custom)
            prefix = _bytepad(prefix_unpad, (1600 - capacity) // 8)
            self._padding = 0x04
        else:
            prefix = None
            self._padding = 0x1F  # for SHAKE

        result = _raw_keccak_lib.keccak_init(state.address_of(),
                                             c_size_t(capacity // 8),
                                             c_ubyte(24))
        if result:
            raise ValueError("Error %d while instantiating cSHAKE" % result)
        self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy)
        self._is_squeezing = False

        if prefix:
            self.update(prefix)

        if data:
            self.update(data)
Exemplo n.º 48
0
    def __init__(self, data, key, digest_bytes):
        """
        Initialize a BLAKE2s hash object.
        """

        #: The size of the resulting hash in bytes.
        self.digest_size = digest_bytes

        # See https://tools.ietf.org/html/draft-saarinen-blake2-02
        if digest_bytes in (16, 20, 28, 32) and not key:
            self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes)

        expect_byte_string(key)

        state = VoidPointer()
        result = _raw_blake2s_lib.blake2s_init(state.address_of(), key,
                                               c_size_t(len(key)),
                                               c_size_t(digest_bytes))
        if result:
            raise ValueError("Error %d while instantiating BLAKE2s" % result)
        self._state = SmartPointer(state.get(),
                                   _raw_blake2s_lib.blake2s_destroy)
        if data:
            self.update(data)
Exemplo n.º 49
0
    def __init__(self, block_cipher):
        """Create a new block cipher, configured in ECB mode.

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

        self._state = VoidPointer()
        result = raw_ecb_lib.ECB_start_operation(block_cipher.get(),
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %d while instantiating the ECB mode" %
                             result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher
        # mode
        self._state = SmartPointer(self._state.get(),
                                   raw_ecb_lib.ECB_stop_operation)

        # Memory allocated for the underlying block cipher is now owned
        # by the cipher mode
        block_cipher.release()
Exemplo n.º 50
0
    def __init__(self, data, update_after_digest):
        self._update_after_digest = update_after_digest
        self._digest_done = False

        state = VoidPointer()
        result = _raw_keccak_lib.keccak_init(state.address_of(),
                                             c_size_t(self.digest_size * 2),
                                             0x06)
        if result:
            raise ValueError("Error %d while instantiating SHA-3/384"
                             % result)
        self._state = SmartPointer(state.get(),
                                   _raw_keccak_lib.keccak_destroy)
        if data:
            self.update(data)
Exemplo n.º 51
0
    def __init__(self, data, digest_bytes, update_after_digest):
        #: The size of the resulting hash in bytes.
        self.digest_size = digest_bytes

        self._update_after_digest = update_after_digest
        self._digest_done = False

        state = VoidPointer()
        result = _raw_keccak_lib.keccak_init(state.address_of(),
                                             c_size_t(self.digest_size * 2),
                                             0x01)
        if result:
            raise ValueError("Error %d while instantiating keccak" % result)
        self._state = SmartPointer(state.get(),
                                   _raw_keccak_lib.keccak_destroy)
        if data:
            self.update(data)
Exemplo n.º 52
0
def _create_base_cipher(dict_parameters):
    """This method instantiates and returns a handle to a low-level base cipher.
    It will absorb named parameters in the process."""

    try:
        key_in = dict_parameters.pop("key")
    except KeyError:
        raise TypeError("Missing 'key' parameter")

    key = adjust_key_parity(key_in)

    start_operation = _raw_des3_lib.DES3_start_operation
    stop_operation = _raw_des3_lib.DES3_stop_operation

    cipher = VoidPointer()
    result = start_operation(key, c_size_t(len(key)), cipher.address_of())
    if result:
        raise ValueError("Error %X while instantiating the TDES cipher" %
                         result)
    return SmartPointer(cipher.get(), stop_operation)
Exemplo n.º 53
0
def init_p224():
    p = 0xffffffffffffffffffffffffffffffff000000000000000000000001
    b = 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
    order = 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
    Gx = 0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
    Gy = 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34

    p224_modulus = long_to_bytes(p, 28)
    p224_b = long_to_bytes(b, 28)
    p224_order = long_to_bytes(order, 28)

    ec_p224_context = VoidPointer()
    result = _ec_lib.ec_ws_new_context(ec_p224_context.address_of(),
                                       c_uint8_ptr(p224_modulus),
                                       c_uint8_ptr(p224_b),
                                       c_uint8_ptr(p224_order),
                                       c_size_t(len(p224_modulus)),
                                       c_ulonglong(getrandbits(64))
                                       )
    if result:
        raise ImportError("Error %d initializing P-224 context" % result)

    context = SmartPointer(ec_p224_context.get(), _ec_lib.ec_free_context)
    p224 = _Curve(Integer(p),
                  Integer(b),
                  Integer(order),
                  Integer(Gx),
                  Integer(Gy),
                  None,
                  224,
                  "1.3.132.0.33",    # SEC 2
                  context,
                  "NIST P-224",
                  "ecdsa-sha2-nistp224")
    global p224_names
    _curves.update(dict.fromkeys(p224_names, p224))
Exemplo n.º 54
0
class CtrMode(object):
    """*CounTeR (CTR)* mode.

    This mode is very similar to ECB, in that
    encryption of one block is done independently of all other blocks.

    Unlike ECB, the block *position* contributes to the encryption
    and no information leaks about symbol frequency.

    Each message block is associated to a *counter* which
    must be unique across all messages that get encrypted
    with the same key (not just within the same message).
    The counter is as big as the block size.

    Counters can be generated in several ways. The most
    straightword one is to choose an *initial counter block*
    (which can be made public, similarly to the *IV* for the
    other modes) and increment its lowest **m** bits by one
    (modulo *2^m*) for each block. In most cases, **m** is
    chosen to be half the block size.

    See `NIST SP800-38A`_, Section 6.5 (for the mode) and
    Appendix B (for how to manage the *initial counter block*).

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

    def __init__(self, block_cipher, initial_counter_block,
                 prefix_len, counter_len, little_endian):
        """Create a new block cipher, configured in CTR mode.

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

          initial_counter_block : byte string
            The initial plaintext to use to generate the key stream.

            It is as large as the cipher block, and it embeds
            the initial value of the counter.

            This value must not be reused.
            It shall contain a nonce or a random component.
            Reusing the *initial counter block* for encryptions
            performed with the same key compromises confidentiality.

          prefix_len : integer
            The amount of bytes at the beginning of the counter block
            that never change.

          counter_len : integer
            The length in bytes of the counter embedded in the counter
            block.

          little_endian : boolean
            True if the counter in the counter block is an integer encoded
            in little endian mode. If False, it is big endian.
        """

        if len(initial_counter_block) == prefix_len + counter_len:
            #: Nonce; not available if there is a fixed suffix
            self.nonce = initial_counter_block[:prefix_len]

        expect_byte_string(initial_counter_block)
        self._state = VoidPointer()
        result = raw_ctr_lib.CTR_start_operation(block_cipher.get(),
                                                 initial_counter_block,
                                                 c_size_t(len(initial_counter_block)),
                                                 c_size_t(prefix_len),
                                                 counter_len,
                                                 little_endian,
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %X while instatiating the CTR mode"
                             % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   raw_ctr_lib.CTR_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        block_cipher.release()

        #: The block size of the underlying cipher, in bytes.
        self.block_size = len(initial_counter_block)

        self._next = [self.encrypt, self.decrypt]

    def encrypt(self, plaintext):
        """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 : byte string
            The piece of data to encrypt.
            It can be of any length.
        :Return:
            the encrypted data, as a byte string.
            It is as long as *plaintext*.
        """

        if self.encrypt not in self._next:
            raise TypeError("encrypt() cannot be called after decrypt()")
        self._next = [self.encrypt]

        expect_byte_string(plaintext)
        ciphertext = create_string_buffer(len(plaintext))
        result = raw_ctr_lib.CTR_encrypt(self._state.get(),
                                         plaintext,
                                         ciphertext,
                                         c_size_t(len(plaintext)))
        if result:
            if result == 0x60002:
                raise OverflowError("The counter has wrapped around in"
                                    " CTR mode")
            raise ValueError("Error %X while encrypting in CTR mode" % result)
        return get_raw_buffer(ciphertext)

    def decrypt(self, ciphertext):
        """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 : byte string
            The piece of data to decrypt.
            It can be of any length.

        :Return: the decrypted data (byte string).
        """

        if self.decrypt not in self._next:
            raise TypeError("decrypt() cannot be called after encrypt()")
        self._next = [self.decrypt]

        expect_byte_string(ciphertext)
        plaintext = create_string_buffer(len(ciphertext))
        result = raw_ctr_lib.CTR_decrypt(self._state.get(),
                                         ciphertext,
                                         plaintext,
                                         c_size_t(len(ciphertext)))
        if result:
            if result == 0x60002:
                raise OverflowError("The counter has wrapped around in"
                                    " CTR mode")
            raise ValueError("Error %X while decrypting in CTR mode" % result)
        return get_raw_buffer(plaintext)
Exemplo n.º 55
0
class Poly1305_MAC(object):

    digest_size = 16

    def __init__(self, r, s, data):

        if len(r) != 16:
            raise ValueError("Paramater r is not 16 bytes long")
        if len(s) != 16:
            raise ValueError("Parameter s is not 16 bytes long")

        self._mac_tag = None

        state = VoidPointer()
        result = _raw_poly1305.poly1305_init(state.address_of(),
                                             c_uint8_ptr(r), c_size_t(len(r)),
                                             c_uint8_ptr(s), c_size_t(len(s)))
        if result:
            raise ValueError("Error %d while instantiating Poly1305" % result)
        self._state = SmartPointer(state.get(), _raw_poly1305.poly1305_destroy)
        if data:
            self.update(data)

    def update(self, data):

        if self._mac_tag:
            raise TypeError(
                "You can only call 'digest' or 'hexdigest' on this object")

        result = _raw_poly1305.poly1305_update(self._state.get(),
                                               c_uint8_ptr(data),
                                               c_size_t(len(data)))
        if result:
            raise ValueError("Error %d while hashing Poly1305 data" % result)
        return self

    def copy(self):
        raise NotImplementedError()

    def digest(self):

        if self._mac_tag:
            return self._mac_tag

        bfr = create_string_buffer(16)
        result = _raw_poly1305.poly1305_digest(self._state.get(), bfr,
                                               c_size_t(len(bfr)))
        if result:
            raise ValueError("Error %d while creating Poly1305 digest" %
                             result)

        self._mac_tag = get_raw_buffer(bfr)
        return self._mac_tag

    def hexdigest(self):

        return "".join(["%02x" % bord(x) for x in tuple(self.digest())])

    def verify(self, mac_tag):

        secret = get_random_bytes(16)

        mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
        mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())

        if mac1.digest() != mac2.digest():
            raise ValueError("MAC check failed")

    def hexverify(self, hex_mac_tag):

        self.verify(unhexlify(tobytes(hex_mac_tag)))
Exemplo n.º 56
0
class ChaCha20Cipher:
    """ChaCha20 cipher object. Do not create it directly. Use :py:func:`new` instead.

    :var nonce: The nonce with length 8
    :vartype nonce: byte string
    """

    block_size = 1

    def __init__(self, key, nonce):
        """Initialize a ChaCha20 cipher object

        See also `new()` at the module level."""

        self.nonce = _copy_bytes(None, None, nonce)

        self._next = (self.encrypt, self.decrypt)
        self._state = VoidPointer()
        result = _raw_chacha20_lib.chacha20_init(self._state.address_of(),
                                                 c_uint8_ptr(key),
                                                 c_size_t(len(key)),
                                                 self.nonce,
                                                 c_size_t(len(nonce)))
        if result:
            raise ValueError("Error %d instantiating a ChaCha20 cipher")
        self._state = SmartPointer(self._state.get(),
                                   _raw_chacha20_lib.chacha20_destroy)

    def encrypt(self, plaintext):
        """Encrypt a piece of data.

        :param plaintext: The data to encrypt, of any size.
        :type plaintext: bytes, bytearray, memoryview
        :returns: the encrypted byte string, of equal length as the
          plaintext.
        """

        if self.encrypt not in self._next:
            raise TypeError("Cipher object can only be used for decryption")
        self._next = (self.encrypt, )
        return self._encrypt(plaintext)

    def _encrypt(self, plaintext):
        """Encrypt without FSM checks"""

        ciphertext = create_string_buffer(len(plaintext))
        result = _raw_chacha20_lib.chacha20_encrypt(self._state.get(),
                                                    c_uint8_ptr(plaintext),
                                                    ciphertext,
                                                    c_size_t(len(plaintext)))
        if result:
            raise ValueError("Error %d while encrypting with ChaCha20" %
                             result)
        return get_raw_buffer(ciphertext)

    def decrypt(self, ciphertext):
        """Decrypt a piece of data.

        :param ciphertext: The data to decrypt, of any size.
        :type ciphertext: bytes, bytearray, memoryview
        :returns: the decrypted byte string, of equal length as the
          ciphertext.
        """

        if self.decrypt not in self._next:
            raise TypeError("Cipher object can only be used for encryption")
        self._next = (self.decrypt, )

        try:
            return self._encrypt(ciphertext)
        except ValueError, e:
            raise ValueError(str(e).replace("enc", "dec"))
Exemplo n.º 57
0
class Salsa20Cipher:
    """Salsa20 cipher object. Do not create it directly. Use :py:func:`new`
    instead.

    :var nonce: The nonce with length 8
    :vartype nonce: byte string
    """

    def __init__(self, key, nonce):
        """Initialize a Salsa20 cipher object

        See also `new()` at the module level."""

        if len(key) not in key_size:
            raise ValueError("Incorrect key length for Salsa20 (%d bytes)" % len(key))

        if len(nonce) != 8:
            raise ValueError("Incorrect nonce length for Salsa20 (%d bytes)" %
                             len(nonce))

        self.nonce = nonce

        expect_byte_string(key)
        expect_byte_string(nonce)

        self._state = VoidPointer()
        result = _raw_salsa20_lib.Salsa20_stream_init(
                        key,
                        c_size_t(len(key)),
                        nonce,
                        c_size_t(len(nonce)),
                        self._state.address_of())
        if result:
            raise ValueError("Error %d instantiating a Salsa20 cipher")
        self._state = SmartPointer(self._state.get(),
                                   _raw_salsa20_lib.Salsa20_stream_destroy)

        self.block_size = 1
        self.key_size = len(key)

    def encrypt(self, plaintext):
        """Encrypt a piece of data.

        :param plaintext: The data to encrypt, of any size.
        :type plaintext: byte string
        :returns: the encrypted byte string, of equal length as the
          plaintext.
        """

        expect_byte_string(plaintext)
        ciphertext = create_string_buffer(len(plaintext))
        result = _raw_salsa20_lib.Salsa20_stream_encrypt(
                                         self._state.get(),
                                         plaintext,
                                         ciphertext,
                                         c_size_t(len(plaintext)))
        if result:
            raise ValueError("Error %d while encrypting with Salsa20" % result)
        return get_raw_buffer(ciphertext)

    def decrypt(self, ciphertext):
        """Decrypt a piece of data.

        :param ciphertext: The data to decrypt, of any size.
        :type ciphertext: byte string
        :returns: the decrypted byte string, of equal length as the
          ciphertext.
        """

        try:
            return self.encrypt(ciphertext)
        except ValueError, e:
            raise ValueError(str(e).replace("enc", "dec"))
Exemplo n.º 58
0
class OfbMode(object):
    """*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__
    """

    def __init__(self, block_cipher, iv):
        """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.
        """

        self._state = VoidPointer()
        result = raw_ofb_lib.OFB_start_operation(block_cipher.get(),
                                                 c_uint8_ptr(iv),
                                                 c_size_t(len(iv)),
                                                 self._state.address_of())
        if result:
            raise ValueError("Error %d while instatiating the OFB mode"
                             % result)

        # Ensure that object disposal of this Python object will (eventually)
        # free the memory allocated by the raw library for the cipher mode
        self._state = SmartPointer(self._state.get(),
                                   raw_ofb_lib.OFB_stop_operation)

        # Memory allocated for the underlying block cipher is now owed
        # by the cipher mode
        block_cipher.release()

        self.block_size = len(iv)
        """The block size of the underlying cipher, in bytes."""

        self.iv = _copy_bytes(None, None, iv)
        """The Initialization Vector originally used to create the object.
        The value does not change."""

        self.IV = self.iv
        """Alias for `iv`"""

        self._next = [ self.encrypt, self.decrypt ]

    def encrypt(self, plaintext):
        """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.
        :Return:
            the encrypted data, as a byte string.
            It is as long as *plaintext*.
        """

        if self.encrypt not in self._next:
            raise TypeError("encrypt() cannot be called after decrypt()")
        self._next = [ self.encrypt ]

        ciphertext = create_string_buffer(len(plaintext))
        result = raw_ofb_lib.OFB_encrypt(self._state.get(),
                                         c_uint8_ptr(plaintext),
                                         ciphertext,
                                         c_size_t(len(plaintext)))
        if result:
            raise ValueError("Error %d while encrypting in OFB mode" % result)
        return get_raw_buffer(ciphertext)

    def decrypt(self, ciphertext):
        """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.

        :Return: the decrypted data (byte string).
        """

        if self.decrypt not in self._next:
            raise TypeError("decrypt() cannot be called after encrypt()")
        self._next = [ self.decrypt ]

        plaintext = create_string_buffer(len(ciphertext))
        result = raw_ofb_lib.OFB_decrypt(self._state.get(),
                                         c_uint8_ptr(ciphertext),
                                         plaintext,
                                         c_size_t(len(ciphertext)))
        if result:
            raise ValueError("Error %d while decrypting in OFB mode" % result)
        return get_raw_buffer(plaintext)
Exemplo n.º 59
0
class SHA3_384_Hash(object):
    """A SHA3-384 hash object.
    Do not instantiate directly.
    Use the :func:`new` function.

    :ivar oid: ASN.1 Object ID
    :vartype oid: string

    :ivar digest_size: the size in bytes of the resulting hash
    :vartype digest_size: integer
    """

    # The size of the resulting hash in bytes.
    digest_size = 48

    # ASN.1 Object ID
    oid = "2.16.840.1.101.3.4.2.9"

    def __init__(self, data, update_after_digest):
        self._update_after_digest = update_after_digest
        self._digest_done = False

        state = VoidPointer()
        result = _raw_keccak_lib.keccak_init(state.address_of(),
                                             c_size_t(self.digest_size * 2),
                                             0x06)
        if result:
            raise ValueError("Error %d while instantiating SHA-3/384"
                             % result)
        self._state = SmartPointer(state.get(),
                                   _raw_keccak_lib.keccak_destroy)
        if data:
            self.update(data)

    def update(self, data):
        """Continue hashing of a message by consuming the next chunk of data.

        Args:
            data (byte string): The next chunk of the message being hashed.
        """

        if self._digest_done and not self._update_after_digest:
            raise TypeError("You can only call 'digest' or 'hexdigest' on this object")

        expect_byte_string(data)
        result = _raw_keccak_lib.keccak_absorb(self._state.get(),
                                               data,
                                               c_size_t(len(data)))
        if result:
            raise ValueError("Error %d while updating SHA-3/384"
                             % result)
        return self

    def digest(self):
        """Return the **binary** (non-printable) digest of the message that has been hashed so far.

        :return: The hash digest, computed over the data processed so far.
                 Binary form.
        :rtype: byte string
        """

        self._digest_done = True

        bfr = create_string_buffer(self.digest_size)
        result = _raw_keccak_lib.keccak_digest(self._state.get(),
                                               bfr,
                                               c_size_t(self.digest_size))
        if result:
            raise ValueError("Error %d while instantiating SHA-3/384"
                             % result)

        self._digest_value = get_raw_buffer(bfr)
        return self._digest_value

    def hexdigest(self):
        """Return the **printable** digest of the message that has been hashed so far.

        :return: The hash digest, computed over the data processed so far.
                 Hexadecimal encoded.
        :rtype: string
        """

        return "".join(["%02x" % bord(x) for x in self.digest()])

    def new(self):
        """Create a fresh SHA3-384 hash object."""

        return type(self)(None, self._update_after_digest)
Exemplo n.º 60
0
class SHA3_384_Hash(object):
    """Class that implements a SHA-3/384 hash
    """

    #: The size of the resulting hash in bytes.
    digest_size = 48

    name = "SHA3_384"

    def __init__(self, data=None):
        state = VoidPointer()
        result = _raw_sha3_384_lib.SHA3_384_init(state.address_of())
        if result:
            raise ValueError("Error %d while instantiating SHA-3/384"
                             % result)
        self._state = SmartPointer(state.get(),
                                   _raw_sha3_384_lib.SHA3_384_destroy)
        if data:
            self.update(data)

    def update(self, data):
        """Continue hashing of a message by consuming the next chunk of data.

        Repeated calls are equivalent to a single call with the concatenation
        of all the arguments. In other words:

           >>> m.update(a); m.update(b)

        is equivalent to:

           >>> m.update(a+b)

        :Parameters:
          data : byte string
            The next chunk of the message being hashed.
        """

        expect_byte_string(data)
        result = _raw_sha3_384_lib.SHA3_384_update(self._state.get(),
                                                   data,
                                                   c_size_t(len(data)))
        if result:
            raise ValueError("Error %d while instantiating SHA-3/384"
                             % result)

    def digest(self):
        """Return the **binary** (non-printable) digest of the message that has been hashed so far.

        This method does not change the state of the hash object.
        You can continue updating the object after calling this function.

        :Return: A byte string of `digest_size` bytes. It may contain non-ASCII
         characters, including null bytes.
        """

        bfr = create_string_buffer(self.digest_size)
        result = _raw_sha3_384_lib.SHA3_384_digest(self._state.get(),
                                                   bfr)
        if result:
            raise ValueError("Error %d while instantiating SHA-3/384"
                             % result)

        return get_raw_buffer(bfr)

    def hexdigest(self):
        """Return the **printable** digest of the message that has been hashed so far.

        This method does not change the state of the hash object.

        :Return: A string of 2* `digest_size` characters. It contains only
         hexadecimal ASCII digits.
        """

        return "".join(["%02x" % bord(x) for x in self.digest()])

    def copy(self):
        """Return a copy ("clone") of the hash object.

        The copy will have the same internal state as the original hash
        object.
        This can be used to efficiently compute the digests of strings that
        share a common initial substring.

        :Return: A hash object of the same type
        """

        clone = SHA3_384_Hash()
        result = _raw_sha3_384_lib.SHA3_384_copy(self._state.get(),
                                                 clone._state.get())
        if result:
            raise ValueError("Error %d while copying SHA-3/384" % result)
        return clone

    def new(self, data=None):
        return SHA3_384_Hash(data)