def __init__(self, data, key, digest_bytes, update_after_digest): """ Initialize a BLAKE2b hash object. """ #: 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/draft-saarinen-blake2-02 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)
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)) #: 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 _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) expect_byte_string(key) 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(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, 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 ]
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) You cannot use ``update`` anymore after the first call to ``read``. :Parameters: data : byte string The next chunk of the message being hashed. """ if self._is_squeezing: raise TypeError("You cannot call 'update' after the first 'read'") 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 SHAKE128 state" % result) return self
def read(self, length): """ Compute the next piece of XOF output. .. note:: You cannot use :meth:`update` anymore after the first call to :meth:`read`. Args: length (integer): the amount of bytes this method must return :return: the next piece of XOF output (of the given length) :rtype: byte string """ self._is_squeezing = True bfr = create_string_buffer(length) result = _raw_keccak_lib.keccak_squeeze(self._state.get(), bfr, c_size_t(length)) if result: raise ValueError("Error %d while extracting from SHAKE128" % result) return get_raw_buffer(bfr)
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. """ 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/224" % result) return self
def _update(self, assoc_data, assoc_data_len): expect_byte_string(assoc_data) result = _raw_ocb_lib.OCB_update(self._state.get(), assoc_data, c_size_t(assoc_data_len)) if result: raise ValueError("Error %d while MAC-ing in OCB mode" % result)
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 decrypt(self, ciphertext): """Decrypt data with the key set at initialization. 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. The length must be multiple of the cipher block length. :Return: the decrypted data (byte string). It is as long as *ciphertext*. """ expect_byte_string(ciphertext) plaintext = create_string_buffer(len(ciphertext)) result = raw_ecb_lib.ECB_decrypt(self._state.get(), ciphertext, plaintext, c_size_t(len(ciphertext))) if result: raise ValueError("Error %d while decrypting in ECB mode" % result) return get_raw_buffer(plaintext)
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)
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 _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) != key_size: raise ValueError("Incorrect DES key length (%d bytes)" % len(key)) start_operation = _raw_des_lib.DES_start_operation stop_operation = _raw_des_lib.DES_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 DES cipher" % result) return SmartPointer(cipher.get(), stop_operation)
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
def encrypt(self, plaintext): """Encrypt data with the key set at initialization. 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. The length must be multiple of the cipher block length. :Return: the encrypted data, as a byte string. It is as long as *plaintext*. """ ciphertext = create_string_buffer(len(plaintext)) result = raw_ecb_lib.ECB_encrypt(self._state.get(), c_uint8_ptr(plaintext), ciphertext, c_size_t(len(plaintext))) if result: if result == 3: raise ValueError("Data must be aligned to block boundary in ECB mode") raise ValueError("Error %d while encrypting in ECB mode" % result) return get_raw_buffer(ciphertext)
def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): """Compute the expensive inner loop in PBKDF-HMAC.""" assert iterations > 0 bfr = create_string_buffer(len(first_digest)); result = _raw_sha256_lib.SHA256_pbkdf2_hmac_assist( inner._state.get(), outer._state.get(), first_digest, bfr, c_size_t(iterations), c_size_t(len(first_digest))) if result: raise ValueError("Error %d with PBKDF2-HMAC assist for SHA256" % result) return get_raw_buffer(bfr)
def __int__(self): # buf will contain the integer encoded in decimal plus the trailing # zero, and possibly the negative sign. # dig10(x) < log10(x) + 1 = log2(x)/log2(10) + 1 < log2(x)/3 + 1 buf_len = _gmp.mpz_sizeinbase(self._mpz_p, 2) // 3 + 3 buf = create_string_buffer(buf_len) _gmp.gmp_snprintf(buf, c_size_t(buf_len), b("%Zd"), self._mpz_p) return int(get_c_string(buf))
def strxor_c(term, c): """Return term xored with a sequence of characters c.""" expect_byte_string(term) if not 0 <= c < 256: raise ValueError("c must be in range(256)") result = create_string_buffer(len(term)) _raw_strxor.strxor_c(term, c, result, c_size_t(len(term))) return get_raw_buffer(result)
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 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 encrypt(self, plaintext, output=None): """Encrypt data with the key set at initialization. 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. The length must be multiple of the cipher block 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 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_ecb_lib.ECB_encrypt(self._state.get(), c_uint8_ptr(plaintext), c_uint8_ptr(ciphertext), c_size_t(len(plaintext))) if result: if result == 3: raise ValueError("Data must be aligned to block boundary in ECB mode") raise ValueError("Error %d while encrypting in ECB mode" % result) if output is None: return get_raw_buffer(ciphertext) else: return None
def from_bytes(byte_string): """Convert a byte string into a number. :Parameters: byte_string : byte string The input number, encoded in network order. It can only be non-negative. :Return: The ``Integer`` object carrying the same value as the input. """ result = Integer(0) _gmp.mpz_import( result._mpz_p, c_size_t(len(byte_string)), # Amount of words to read 1, # Big endian c_size_t(1), # Each word is 1 byte long 0, # Endianess within a word - not relevant c_size_t(0), # No nails byte_string) return result
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/224" % result) self._state = SmartPointer(state.get(), _raw_keccak_lib.keccak_destroy) if data: self.update(data)
def strxor(term1, term2): """Return term1 xored with term2. The two byte strings must have equal length.""" expect_byte_string(term1) expect_byte_string(term2) if len(term1) != len(term2): raise ValueError("Only byte strings of equal length can be xored") result = create_string_buffer(len(term1)) _raw_strxor.strxor(term1, term2, result, c_size_t(len(term1))) return get_raw_buffer(result)
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 _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 strxor_c(term, c): """XOR of a byte string with a repeated sequence of characters. Return: A new byte string, :data:`term` with all its bytes xored with :data:`c`. """ if not 0 <= c < 256: raise ValueError("c must be in range(256)") result = create_string_buffer(len(term)) _raw_strxor.strxor_c(c_uint8_ptr(term), c, result, c_size_t(len(term))) return get_raw_buffer(result)
def _transcrypt_aligned(self, in_data, in_data_len, trans_func, trans_desc): out_data = create_string_buffer(in_data_len) result = trans_func(self._state.get(), in_data, out_data, c_size_t(in_data_len)) if result: raise ValueError("Error %d while %sing in OCB mode" % (result, trans_desc)) return get_raw_buffer(out_data)
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 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_sha256_lib.SHA256_update(self._state.get(), c_uint8_ptr(data), c_size_t(len(data))) if result: raise ValueError("Error %d while hashing data with SHA256" % result)
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, 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]
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_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 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_blake2s_lib.blake2s_update(self._state.get(), data, c_size_t(len(data))) if result: raise ValueError("Error %d while hashing BLAKE2s data" % result) return self
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 update(self, data): """Authenticate the next chunk of message. Args: data (byte string/byte array/memoryview): The next chunk of 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 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 squeezing keccak" % result) return get_raw_buffer(bfr)
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._is_squeezing: raise TypeError("You cannot call 'update' after the first 'read'") 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 SHAKE128 state" % result) return self
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 keccak" % result) return self
def inplace_pow(self, exponent, modulus=None): exp_value = int(exponent) if exp_value < 0: raise ValueError("Exponent must not be negative") # No modular reduction if modulus is None: self._value = pow(self._value, exp_value) return self # With modular reduction mod_value = int(modulus) if mod_value < 0: raise ValueError("Modulus must be positive") if mod_value == 0: raise ZeroDivisionError("Modulus cannot be zero") # C extension only works with odd moduli if (mod_value & 1) == 0: self._value = pow(self._value, exp_value, mod_value) return self max_len = len(long_to_bytes(max(self._value, exp_value, mod_value))) base_b = long_to_bytes(self._value, max_len) exp_b = long_to_bytes(exp_value, max_len) modulus_b = long_to_bytes(mod_value, max_len) out = create_string_buffer(max_len) error = _raw_montgomery.monty_pow( base_b, exp_b, modulus_b, out, c_size_t(max_len), c_ulonglong(getrandbits(64)) ) if error: raise ValueError("monty_pow failed with error: %d" % error) result = bytes_to_long(get_raw_buffer(out)) self._value = result return self
def digest(self): """Return the **binary** (non-printable) digest of the message that has been hashed so far. You cannot update the hash anymore after the first call to ``digest`` (or ``hexdigest``). :Return: A byte string of `digest_size` bytes. It may contain non-ASCII characters, including null bytes. """ 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 squeezing keccak" % result) return get_raw_buffer(bfr)
def monty_pow(base, exp, modulus): max_len = len(long_to_bytes(max(base, exp, modulus))) base_b, exp_b, modulus_b = [ long_to_bytes(x, max_len) for x in (base, exp, modulus) ] out = create_string_buffer(max_len) error = _raw_montgomery.monty_pow(base_b, exp_b, modulus_b, out, c_size_t(max_len), c_ulonglong(32)) if error == 2: raise ExceptionModulus() if error: raise ValueError("monty_pow failed with error: %d" % error) result = bytes_to_long(get_raw_buffer(out)) return result
def _compute_mac_tag(self): if self._mac_tag is not None: return if self._cache_A: self._update(self._cache_A, len(self._cache_A)) self._cache_A = b"" mac_tag = create_string_buffer(16) result = _raw_ocb_lib.OCB_digest(self._state.get(), mac_tag, c_size_t(len(mac_tag)) ) if result: raise ValueError("Error %d while computing digest in OCB mode" % result) self._mac_tag = get_raw_buffer(mac_tag)[:self._mac_len]
def _pbkdf2_hmac_assist(inner, outer, first_digest, iterations): """Compute the expensive inner loop in PBKDF-HMAC.""" assert len(first_digest) == digest_size assert iterations > 0 bfr = create_string_buffer(digest_size); result = _raw_sha512_lib.SHA512_pbkdf2_hmac_assist( inner._state.get(), outer._state.get(), first_digest, bfr, c_size_t(iterations)) if result: raise ValueError("Error %d with PBKDF2-HMAC assis for SHA512" % result) return get_raw_buffer(bfr)
def read(self, length): """Return the next ``length`` bytes of **binary** (non-printable) digest for the message. You cannot use ``update`` anymore after the first call to ``read``. :Return: A byte string of `length` bytes. """ self._is_squeezing = True bfr = create_string_buffer(length) result = _raw_keccak_lib.keccak_squeeze(self._state.get(), bfr, c_size_t(length)) if result: raise ValueError("Error %d while extracting from SHAKE256" % result) return get_raw_buffer(bfr)
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/array 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_ctr_lib.CTR_encrypt(self._state.get(), c_uint8_ptr(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 : bytes/bytearray/memoryview The piece of data to decrypt. Its length must be multiple of the cipher block size. :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_cbc_lib.CBC_decrypt(self._state.get(), c_uint8_ptr(ciphertext), plaintext, c_size_t(len(ciphertext))) if result: if result == 3: raise ValueError( "Data must be padded to %d byte boundary in CBC mode" % self.block_size) raise ValueError("Error %d while decrypting in CBC mode" % result) return get_raw_buffer(plaintext)
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) That also means that you cannot reuse an object for encrypting or decrypting other data with the same key. This function does not add any padding to the plaintext. :Parameters: plaintext : byte string The piece of data to encrypt. Its lenght must be multiple of the cipher block size. :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_cbc_lib.CBC_encrypt(self._state.get(), plaintext, ciphertext, c_size_t(len(plaintext))) if result: raise ValueError("Error %d while encrypting in CBC mode" % result) return get_raw_buffer(ciphertext)
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 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_ctr_lib.CTR_decrypt(self._state.get(), c_uint8_ptr(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)
def strxor_c(term, c, output=None): """XOR a byte string with a repeated sequence of characters. Args: term(bytes/bytearray/memoryview): The first term of the XOR operation. c (bytes): The byte that makes up the second term of the XOR operation. output (None or bytearray/memoryview): If not ``None``, the location where the result is stored into. Return: If ``output`` is ``None``, a new ``bytes`` string with the result. Otherwise ``None``. """ if not 0 <= c < 256: raise ValueError("c must be in range(256)") if output is None: result = create_string_buffer(len(term)) else: # Note: output may overlap with either input result = output if _is_immutable(output): raise TypeError("output must be a bytearray or a writeable memoryview") if len(term) != len(output): raise ValueError("output must have the same length as the input" " (%d bytes)" % len(term)) _raw_strxor.strxor_c(c_uint8_ptr(term), c, c_uint8_ptr(result), c_size_t(len(term)) ) if output is None: return get_raw_buffer(result) else: return None
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)
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_ofb_lib.OFB_decrypt(self._state.get(), ciphertext, plaintext, c_size_t(len(ciphertext))) if result: raise ValueError("Error %d while decrypting in OFB mode" % result) return get_raw_buffer(plaintext)
def strxor(term1, term2, output=None): """XOR two byte strings. Args: term1 (bytes/bytearray/memoryview): The first term of the XOR operation. term2 (bytes/bytearray/memoryview): The second term of the XOR operation. output (bytearray/memoryview): The location where the result must be written to. If ``None``, the result is returned. :Return: If ``output`` is ``None``, a new ``bytes`` string with the result. Otherwise ``None``. """ if len(term1) != len(term2): raise ValueError("Only byte strings of equal length can be xored") if output is None: result = create_string_buffer(len(term1)) else: # Note: output may overlap with either input result = output if _is_immutable(output): raise TypeError("output must be a bytearray or a writeable memoryview") if len(term1) != len(output): raise ValueError("output must have the same length as the input" " (%d bytes)" % len(term1)) _raw_strxor.strxor(c_uint8_ptr(term1), c_uint8_ptr(term2), c_uint8_ptr(result), c_size_t(len(term1))) if output is None: return get_raw_buffer(result) else: return None
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/byte array/memoryview The next chunk of the message being hashed. """ result = _raw_md4_lib.md4_update(self._state.get(), c_uint8_ptr(data), c_size_t(len(data))) if result: raise ValueError("Error %d while instantiating MD4" % result)
def digest(self): """Return the **binary** (non-printable) MAC tag of the message authenticated so far. :return: The MAC tag digest, computed over the data processed so far. Binary form. :rtype: byte string """ 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 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_sha224_lib.SHA224_update(self._state.get(), data, c_size_t(len(data))) if result: raise ValueError("Error %d while instantiating SHA224" % result)
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") if len(key) != key_size: raise ValueError("Incorrect DES key length (%d bytes)" % len(key)) start_operation = _raw_des_lib.DES_start_operation stop_operation = _raw_des_lib.DES_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 DES 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 encrypt(self, plaintext, output=None): """Encrypt a piece of data. Args: plaintext(bytes/bytearray/memoryview): The data to encrypt, of any size. Keyword Args: output(bytes/bytearray/memoryview): The location where the ciphertext is written to. If ``None``, the ciphertext is returned. Returns: If ``output`` is ``None``, the ciphertext is returned as ``bytes``. Otherwise, ``None``. """ if output is None: ciphertext = create_string_buffer(len(plaintext)) else: ciphertext = output if _is_immutable(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_salsa20_lib.Salsa20_stream_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 with Salsa20" % result) if output is None: return get_raw_buffer(ciphertext) else: return None