# TupleHash128

TupleHash128 is a variable-lengh hash function for tuples of byte strings, derived from SHA-3, and standardized in NIST SP 800-185.

TupleHash128 provides a robust way to hash a sequence of byte strings, while maintaining the semantics of each single string, and with a security strength of 128 bits.

For example, let’s assume that a banking application combines the following strings to validate a money transfer: `deposit`, amount (e.g., `100`), and username (e.g., `joe`). The application uses SHA256 and naively concatenates the strings to obtain a credential to authorize the operation:

    SHA256("deposit100joe")

A malicious user could register a second user `000joe`, so that the system computes, for the same small transfer:

    SHA256("deposit100000joe")

which is also the same credential that authorizes a much larger transfer to the other user `joe`.

TupleHash128 makes the composition of all strings into a digest more robust by ensuring that the size of each individual byte string is considered. Each byte string is submitted in its entirety via the `update()` method.

This is an example showing how to generate a TupleHash128 for the 3 bytes strings above:

    >>> from Crypto.Hash import TupleHash128
    >>>
    >>> hd = TupleHash128.new(digest_bytes=16)
    >>> hd.update(b'deposit')
    >>> hd.update(b'100')
    >>> hd.update(b'joe')
    >>> print(hd.hexdigest())
    4c095be894c21cfe7076a7d0fe3f70ed

Multiple byte strings can be submitted. Each argument is a separate element in the tuple:

    >>> from Crypto.Hash import TupleHash128
    >>>
    >>> hd = TupleHash128.new(digest_bytes=16)
    >>> hd.update(b'deposit', b'100', b'joe')
    >>> print(hd.hexdigest())
    4c095be894c21cfe7076a7d0fe3f70ed

Any or even all the byte strings in the sequence can be empty. An empty byte string is significant: calling `update(b'')` will still contribute to and modify the final digest.

An application can select the length of the digest by means of the initialization parameters `digest_bytes` or `digest_bits`. For instance, while the traditional SHA256 can only produce 32-byte tags, with TupleHash128 you can produce a 16-byte tag (see the example above) but also a 33-byte tag:

    >>> from Crypto.Hash import TupleHash128
    >>>
    >>> hd = TupleHash128.new(digest_bytes=33)
    >>> hd.update(b'deposit')
    >>> hd.update(b'100')
    >>> hd.update(b'joe')
    >>> print(hd.hexdigest())
    23339e4f61527ade355f11e0496766bf929435eaff1ad20ad9bf9e01fddbe307

Note how the 16-byte digest is NOT just the truncated version of the 33-byte digest: they are cryptographically uncorrelated.

class Crypto.Hash.TupleHash128.TupleHash(custom, cshake, digest_size)

  A Tuple hash object. Do not instantiate directly. Use the `new()` function.

  digest()

    Return the binary (non-printable) digest of the tuple of byte strings.

    Returns:

      The hash digest. Binary form.

    Return type:

      byte string

  hexdigest()

    Return the printable digest of the tuple of byte strings.

    Returns:

      The hash digest. Hexadecimal encoded.

    Return type:

      string

  new(**kwargs)

    Return a new instance of a TupleHash object. See `new()`.

  update(*data)

    Authenticate the next tuple of byte strings. TupleHash guarantees the logical separation between each byte string.

    Parameters:

      data (bytes/bytearray/memoryview) – One or more items to hash.

Crypto.Hash.TupleHash128.new(**kwargs)

  Create a new TupleHash128 object.

  Parameters:

    - digest_bytes (integer) – Optional. The size of the digest, in bytes. Default is 64. Minimum is 8.

    - digest_bits (integer) – Optional and alternative to `digest_bytes`. The size of the digest, in bits (and in steps of 8). Default is 512. Minimum is 64.

    - custom (bytes) – Optional. A customization bytestring (`S` in SP 800-185).

  Return:

    A `TupleHash` object