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)
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 = _copy_bytes(None, None, nonce) self._state = VoidPointer() result = _raw_salsa20_lib.Salsa20_stream_init( c_uint8_ptr(key), c_size_t(len(key)), c_uint8_ptr(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 __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)
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)) self._state = VoidPointer() result = _raw_arc4_lib.ARC4_stream_init(c_uint8_ptr(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 __init__(self, data=None): state = VoidPointer() result = _raw_md2_lib.md2_init(state.address_of()) if result: raise ValueError("Error %d while instantiating MD2" % result) self._state = SmartPointer(state.get(), _raw_md2_lib.md2_destroy) if data: self.update(data)
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 : bytes/bytearray/memoryview 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: self.nonce = _copy_bytes(None, prefix_len, initial_counter_block) """Nonce; not available if there is a fixed suffix""" self._state = VoidPointer() result = raw_ctr_lib.CTR_start_operation( block_cipher.get(), c_uint8_ptr(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() self.block_size = len(initial_counter_block) """The block size of the underlying cipher, in bytes.""" self._next = [self.encrypt, self.decrypt]
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
def __init__(self, data=None): state = VoidPointer() result = _raw_keccak_lib.keccak_init(state.address_of(), c_size_t(32), 0x1F) if result: raise ValueError("Error %d while instantiating SHAKE128" % result) self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy) self._is_squeezing = False if data: self.update(data)
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/256" % result) self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy) if data: self.update(data)
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 : bytes/bytearray/memoryview 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. """ self._state = VoidPointer() result = raw_cfb_lib.CFB_start_operation(block_cipher.get(), c_uint8_ptr(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 = _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 _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 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 _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)
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 __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)
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)
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)
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)
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 instatiating 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()
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(bstr(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)
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") except KeyError: raise TypeError("Missing 'key' parameter") if len(key) not in key_size: raise ValueError("Incorrect Blowfish key length (%d bytes)" % len(key)) start_operation = _raw_blowfish_lib.Blowfish_start_operation stop_operation = _raw_blowfish_lib.Blowfish_stop_operation void_p = VoidPointer() result = start_operation(c_uint8_ptr(key), c_size_t(len(key)), void_p.address_of()) if result: raise ValueError("Error %X while instantiating the Blowfish cipher" % result) return SmartPointer(void_p.get(), stop_operation)
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, 256, "1.2.840.10045.3.1.7", # ANSI X9.62 context, "NIST P-256", "ecdsa-sha2-nistp256") global p256_names _curves.update(dict.fromkeys(p256_names, p256))
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, 384, "1.3.132.0.34", # SEC 2 context, "NIST P-384", "ecdsa-sha2-nistp384") global p384_names _curves.update(dict.fromkeys(p384_names, p384))
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, 521, "1.3.132.0.35", # SEC 2 context, "NIST P-521", "ecdsa-sha2-nistp521") global p521_names _curves.update(dict.fromkeys(p521_names, p521))
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 = _copy_bytes(None, None, nonce) self._state = VoidPointer() result = _raw_salsa20_lib.Salsa20_stream_init( c_uint8_ptr(key), c_size_t(len(key)), c_uint8_ptr(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: bytes/bytearray/memoryview :returns: the encrypted byte string, of equal length as the plaintext. """ ciphertext = create_string_buffer(len(plaintext)) result = _raw_salsa20_lib.Salsa20_stream_encrypt( self._state.get(), c_uint8_ptr(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: bytes/bytearray/memoryview :returns: the decrypted byte string, of equal length as the ciphertext. """ try: return self.encrypt(ciphertext) except ValueError as e: raise ValueError(str(e).replace("enc", "dec"))
class MD2Hash(object): """An MD2 hash object. Do not instantiate directly. Use the :func:`new` function. :ivar oid: ASN.1 Object ID :vartype oid: string :ivar block_size: the size in bytes of the internal message block, input to the compression function :vartype block_size: integer :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 = 16 # The internal block size of the hash algorithm in bytes. block_size = 64 # ASN.1 Object ID oid = "1.2.840.113549.2.2" def __init__(self, data=None): state = VoidPointer() result = _raw_md2_lib.md2_init(state.address_of()) if result: raise ValueError("Error %d while instantiating MD2" % result) self._state = SmartPointer(state.get(), _raw_md2_lib.md2_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/byte array/memoryview): The next chunk of the message being hashed. """ result = _raw_md2_lib.md2_update(self._state.get(), c_uint8_ptr(data), c_size_t(len(data))) if result: raise ValueError("Error %d while instantiating MD2" % result) 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 """ bfr = create_string_buffer(self.digest_size) result = _raw_md2_lib.md2_digest(self._state.get(), bfr) if result: raise ValueError("Error %d while instantiating MD2" % result) return get_raw_buffer(bfr) 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 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 = MD2Hash() result = _raw_md2_lib.md2_copy(self._state.get(), clone._state.get()) if result: raise ValueError("Error %d while copying MD2" % result) return clone def new(self, data=None): return MD2Hash(data)
class ARC4Cipher: """ARC4 cipher object. Do not create it directly. Use :func:`Crypto.Cipher.ARC4.new` instead. """ 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)) self._state = VoidPointer() result = _raw_arc4_lib.ARC4_stream_init(c_uint8_ptr(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. :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. """ ciphertext = create_string_buffer(len(plaintext)) result = _raw_arc4_lib.ARC4_stream_encrypt(self._state.get(), c_uint8_ptr(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. :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. """ try: return self.encrypt(ciphertext) except ValueError as e: raise ValueError(str(e).replace("enc", "dec"))
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 instantiating 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, output=None): """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``. """ if self.encrypt not in self._next: raise TypeError("encrypt() cannot be called after decrypt()") self._next = [self.encrypt] if output is None: ciphertext = create_string_buffer(len(plaintext)) else: ciphertext = output if not is_writeable_buffer(output): raise TypeError( "output must be a bytearray or a writeable memoryview") if len(plaintext) != len(output): raise ValueError( "output must have the same length as the input" " (%d bytes)" % len(plaintext)) result = raw_ofb_lib.OFB_encrypt(self._state.get(), c_uint8_ptr(plaintext), c_uint8_ptr(ciphertext), c_size_t(len(plaintext))) if result: raise ValueError("Error %d while encrypting in OFB mode" % result) if output is None: return get_raw_buffer(ciphertext) else: return None def decrypt(self, ciphertext, output=None): """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``. """ if self.decrypt not in self._next: raise TypeError("decrypt() cannot be called after encrypt()") self._next = [self.decrypt] if output is None: plaintext = create_string_buffer(len(ciphertext)) else: plaintext = output if not is_writeable_buffer(output): raise TypeError( "output must be a bytearray or a writeable memoryview") if len(ciphertext) != len(output): raise ValueError( "output must have the same length as the input" " (%d bytes)" % len(plaintext)) result = raw_ofb_lib.OFB_decrypt(self._state.get(), c_uint8_ptr(ciphertext), c_uint8_ptr(plaintext), c_size_t(len(ciphertext))) if result: raise ValueError("Error %d while decrypting in OFB mode" % result) if output is None: return get_raw_buffer(plaintext) else: return None
class CfbMode(object): """*Cipher FeedBack (CFB)*. This mode is similar to CFB, but it transforms the underlying block cipher into a stream cipher. Plaintext and ciphertext are processed in *segments* of **s** bits. The mode is therefore sometimes labelled **s**-bit CFB. An Initialization Vector (*IV*) is required. See `NIST SP800-38A`_ , Section 6.3. .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf :undocumented: __init__ """ 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 : bytes/bytearray/memoryview 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. """ self._state = VoidPointer() result = raw_cfb_lib.CFB_start_operation(block_cipher.get(), c_uint8_ptr(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 = _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_cfb_lib.CFB_encrypt(self._state.get(), c_uint8_ptr(plaintext), ciphertext, c_size_t(len(plaintext))) if result: raise ValueError("Error %d while encrypting in CFB 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_cfb_lib.CFB_decrypt(self._state.get(), c_uint8_ptr(ciphertext), plaintext, c_size_t(len(ciphertext))) if result: raise ValueError("Error %d while decrypting in CFB mode" % result) return get_raw_buffer(plaintext)
class SHA3_256_Hash(object): """A SHA3-256 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 = 32 # ASN.1 Object ID oid = "2.16.840.1.101.3.4.2.8" 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/256" % 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/byte array/memoryview): 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") result = _raw_keccak_lib.keccak_absorb(self._state.get(), c_uint8_ptr(data), c_size_t(len(data))) if result: raise ValueError("Error %d while updating SHA-3/256" % 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/256" % 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-256 hash object.""" return type(self)(None, self._update_after_digest)
class SHA512Hash(object): """A SHA-512 hash object (possibly in its truncated version SHA-512/224 or SHA-512/256. Do not instantiate directly. Use the :func:`new` function. :ivar oid: ASN.1 Object ID :vartype oid: string :ivar block_size: the size in bytes of the internal message block, input to the compression function :vartype block_size: integer :ivar digest_size: the size in bytes of the resulting hash :vartype digest_size: integer """ # The internal block size of the hash algorithm in bytes. block_size = 128 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) def update(self, data): """Continue hashing of a message by consuming the next chunk of data. Args: data (byte string/byte array/memoryview): The next chunk of the message being hashed. """ result = _raw_sha512_lib.SHA512_update(self._state.get(), c_uint8_ptr(data), c_size_t(len(data))) if result: raise ValueError("Error %d while hashing data with SHA512" % result) 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 """ bfr = create_string_buffer(self.digest_size) result = _raw_sha512_lib.SHA512_digest(self._state.get(), bfr, c_size_t(self.digest_size)) if result: raise ValueError("Error %d while making SHA512 digest" % result) return get_raw_buffer(bfr) 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 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 = SHA512Hash(None, self._truncate) result = _raw_sha512_lib.SHA512_copy(self._state.get(), clone._state.get()) if result: raise ValueError("Error %d while copying SHA512" % result) return clone def new(self, data=None): """Create a fresh SHA-512 hash object.""" return SHA512Hash(data, self._truncate)