def generichash_blake2b_state_copy(statebuf): """Return a copy of the given blake2b hash state""" newstate = ffi.new("unsigned char[]", crypto_generichash_STATEBYTES) ffi.memmove(newstate, statebuf, crypto_generichash_STATEBYTES) return newstate
def sodium_pad(s, blocksize): """ Pad the input bytearray ``s`` to a multiple of ``blocksize`` using the ISO/IEC 7816-4 algorithm :param s: input bytes string :type s: bytes :param blocksize: :type blocksize: int :return: padded string :rtype: bytes """ ensure(isinstance(s, bytes), raising=exc.TypeError) ensure(isinstance(blocksize, integer_types), raising=exc.TypeError) if blocksize <= 0: raise exc.ValueError s_len = len(s) m_len = s_len + blocksize buf = ffi.new("unsigned char []", m_len) p_len = ffi.new("size_t []", 1) ffi.memmove(buf, s, s_len) rc = lib.sodium_pad(p_len, buf, s_len, blocksize, m_len) ensure(rc == 0, "Padding failure", raising=exc.CryptoError) return ffi.buffer(buf, p_len[0])[:]
def sodium_add(a, b): """ Given a couple of *same-sized* byte sequences, interpreted as the little-endian representation of two unsigned integers, compute the modular addition of the represented values, in constant time for a given common length of the byte sequences. :param a: input bytes buffer :type a: bytes :param b: input bytes buffer :type b: bytes :return: a byte-sequence representing, as a little-endian big integer, the integer value of ``(to_int(a) + to_int(b)) mod 2^(8*len(a))`` :rtype: bytes """ ensure(isinstance(a, bytes), raising=exc.TypeError) ensure(isinstance(b, bytes), raising=exc.TypeError) ln = len(a) ensure(len(b) == ln, raising=exc.TypeError) buf_a = ffi.new("unsigned char []", ln) buf_b = ffi.new("unsigned char []", ln) ffi.memmove(buf_a, a, ln) ffi.memmove(buf_b, b, ln) lib.sodium_add(buf_a, buf_b, ln) return ffi.buffer(buf_a, ln)[:]
def generichash_blake2b_salt_personal(data, digest_size=crypto_generichash_BYTES, key=b'', salt=b'', person=b''): """One shot hash interface :param data: the input data to the hash function :param digest_size: must be at most :py:data:`.crypto_generichash_BYTES_MAX`; the default digest size is :py:data:`.crypto_generichash_BYTES` :type digest_size: int :param key: must be at most :py:data:`.crypto_generichash_KEYBYTES_MAX` long :type key: bytes :param salt: must be at most :py:data:`.crypto_generichash_SALTBYTES` long; will be zero-padded if needed :type salt: bytes :param person: must be at most :py:data:`.crypto_generichash_PERSONALBYTES` long: will be zero-padded if needed :type person: bytes :return: digest_size long digest :rtype: bytes """ _checkparams(digest_size, key, salt, person) ensure(isinstance(data, bytes), 'Input data must be a bytes sequence', raising=exc.TypeError) digest = ffi.new("unsigned char[]", digest_size) # both _salt and _personal must be zero-padded to the correct length _salt = ffi.new("unsigned char []", crypto_generichash_SALTBYTES) _person = ffi.new("unsigned char []", crypto_generichash_PERSONALBYTES) ffi.memmove(_salt, salt, len(salt)) ffi.memmove(_person, person, len(person)) rc = lib.crypto_generichash_blake2b_salt_personal(digest, digest_size, data, len(data), key, len(key), _salt, _person) ensure(rc == 0, 'Unexpected failure', raising=exc.RuntimeError) return ffi.buffer(digest, digest_size)[:]
def generichash_blake2b_init(key=b'', salt=b'', person=b'', digest_size=crypto_generichash_BYTES): """ Create a new initialized blake2b hash state :param key: must be at most :py:data:`.crypto_generichash_KEYBYTES_MAX` long :type key: bytes :param salt: must be at most :py:data:`.crypto_generichash_SALTBYTES` long; will be zero-padded if needed :type salt: bytes :param person: must be at most :py:data:`.crypto_generichash_PERSONALBYTES` long: will be zero-padded if needed :type person: bytes :param digest_size: must be at most :py:data:`.crypto_generichash_BYTES_MAX`; the default digest size is :py:data:`.crypto_generichash_BYTES` :type digest_size: int :return: an initizialized state buffer :rtype: bytes """ _checkparams(digest_size, key, salt, person) statebuf = ffi.new("unsigned char[]", crypto_generichash_STATEBYTES) # both _salt and _personal must be zero-padded to the correct length _salt = ffi.new("unsigned char []", crypto_generichash_SALTBYTES) _person = ffi.new("unsigned char []", crypto_generichash_PERSONALBYTES) ffi.memmove(_salt, salt, len(salt)) ffi.memmove(_person, person, len(person)) rc = lib.crypto_generichash_blake2b_init_salt_personal(statebuf, key, len(key), digest_size, _salt, _person) ensure(rc == 0, 'Unexpected failure', raising=exc.RuntimeError) return statebuf
def sodium_memcmp(inp1, inp2): """ Compare contents of two memory regions in constant time """ ensure(isinstance(inp1, bytes), raising=exc.TypeError) ensure(isinstance(inp2, bytes), raising=exc.TypeError) ln = max(len(inp1), len(inp2)) buf1 = ffi.new("char []", ln) buf2 = ffi.new("char []", ln) ffi.memmove(buf1, inp1, len(inp1)) ffi.memmove(buf2, inp2, len(inp2)) eqL = len(inp1) == len(inp2) eqC = lib.sodium_memcmp(buf1, buf2, ln) == 0 return eqL and eqC
def sodium_increment(inp): """ Increment the value of a byte-sequence interpreted as the little-endian representation of a unsigned big integer. :param inp: input bytes buffer :type inp: bytes :return: a byte-sequence representing, as a little-endian unsigned big integer, the value ``to_int(inp)`` incremented by one. :rtype: bytes """ ensure(isinstance(inp, bytes), raising=exc.TypeError) ln = len(inp) buf = ffi.new("unsigned char []", ln) ffi.memmove(buf, inp, ln) lib.sodium_increment(buf, ln) return ffi.buffer(buf, ln)[:]
def copy(self): _st = self.__class__(self.digest_size) ffi.memmove(_st._statebuf, self._statebuf, crypto_generichash_STATEBYTES) return _st
def generichash_blake2b_salt_personal(data, digest_size=crypto_generichash_BYTES, key=b'', salt=b'', person=b''): """One shot hash interface :param data: the input data to the hash function :param digest_size: must be at most :py:data:`.crypto_generichash_BYTES_MAX`; the default digest size is :py:data:`.crypto_generichash_BYTES` :type digest_size: int :param key: must be at most :py:data:`.crypto_generichash_KEYBYTES_MAX` long :type key: bytes :param salt: must be at most :py:data:`.crypto_generichash_SALTBYTES` long; will be zero-padded if needed :type salt: bytes :param person: must be at most :py:data:`.crypto_generichash_PERSONALBYTES` long: will be zero-padded if needed :type person: bytes :return: digest_size long digest :rtype: bytes """ ensure(isinstance(data, bytes), 'Input data must be a bytes sequence', raising=exc.TypeError) ensure(isinstance(key, bytes), 'Key must be a bytes sequence', raising=exc.TypeError) ensure(isinstance(salt, bytes), 'Salt must be a bytes sequence', raising=exc.TypeError) ensure(isinstance(person, bytes), 'Person must be a bytes sequence', raising=exc.TypeError) ensure(isinstance(digest_size, integer_types), 'Digest size must be an integer number', raising=exc.TypeError) ensure(digest_size <= crypto_generichash_BYTES_MAX, _TOOBIG.format("Digest_size", crypto_generichash_BYTES_MAX), raising=exc.ValueError) ensure(len(key) <= crypto_generichash_KEYBYTES_MAX, _OVERLONG.format("Key", crypto_generichash_KEYBYTES_MAX), raising=exc.ValueError) ensure(len(salt) <= crypto_generichash_SALTBYTES, _OVERLONG.format("Salt", crypto_generichash_SALTBYTES), raising=exc.ValueError) ensure(len(person) <= crypto_generichash_PERSONALBYTES, _OVERLONG.format("Person", crypto_generichash_PERSONALBYTES), raising=exc.ValueError) digest = ffi.new("unsigned char[]", digest_size) # both _salt and _personal must be zero-padded to the correct length _salt = ffi.new("unsigned char []", crypto_generichash_SALTBYTES) _person = ffi.new("unsigned char []", crypto_generichash_PERSONALBYTES) ffi.memmove(_salt, salt, len(salt)) ffi.memmove(_person, person, len(person)) rc = lib.crypto_generichash_blake2b_salt_personal(digest, digest_size, data, len(data), key, len(key), _salt, _person) ensure(rc == 0, 'Unexpected failure', raising=exc.RuntimeError) return ffi.buffer(digest, digest_size)[:]