def reconstruct_secret(shares, strict_mode=True):
    """
    shares must be a container with a sufficient number of well-formatted
    shares used to reconstruct the secret value. If any share format is
    invalid a TSSError exception is raised.
    If strict_mode is False all combinations of shares are tried in order
    to reconstruct the secret. Otherwise this function raises an exception
    TSSError on the first error encountered (either a duplicate share was
    detected or the provided hash value didn't match the one computed from
    the recovered secret).
    This function must return the secret value or raise TSSError.
    """
    ref_header = None
    data_shares = []
    for share in shares:
        share = encode(share)
        if len(share) < 20:
            raise TSSError('share format invalid')
        header = parse_header(share[:20])
        if ref_header is None:
            ref_header = header
            if header[2] > len(shares):
                raise TSSError('not enough shares for reconstructing secret')
        if ref_header != header:
            raise TSSError('invalid share headers %s' % header)
        data_share = share[20:]
        if len(data_share) != header[3]:
            raise TSSError('invalid share data size %d (expected %d)' % \
                               (len(data_share), header[3]))
        data_shares.append(data_share)

    for combination in itertools.combinations(data_shares, ref_header[2]):
        secret = bytearray()
        u = [byte_to_ord(share[0]) for share in combination]
        if len(dict().fromkeys(u)) != len(u):
            if strict_mode:
                raise TSSError('invalid share with duplicate index')
            else:
                continue
        for i in range(1, ref_header[3]):
            v = [byte_to_ord(share[i]) for share in combination]
            secret.append(lagrange_interpolation(u, v))
        secret = bytes(secret)
        if ref_header[1] != Hash.NONE:
            d = Hash.to_func(ref_header[1])()
            digestsize = digest_size(d)
            d.update(secret[:-digestsize])
            if len(secret) < digestsize or d.digest() != secret[-digestsize:]:
                if strict_mode:
                    raise TSSError('hash values mismatch')
                else:
                    continue
            return secret[:-digestsize]
        return secret
    raise TSSError('not enough valid shares for reconstructing the secret')