コード例 #1
0
def generate_hashes(n, k, header):
    collision_length = n / (k + 1)
    bit_len = collision_length + 1
    hash_length = (k + 1) * ((collision_length + 7) // 8)
    indices_per_hash_output = 512 / n
    num_indices = 2**k

    digest = blake2b(digest_size=(512 / n) * n / 8, person=zcash_person(n, k))
    digest.update(header[:140])
    num_bytes = ord(header[140]) if ord(header[140]) < 253 else struct.unpack(
        '<H', header[141:143])[0]
    assert num_bytes == bit_len * num_indices / 8, 'Block header does not match Equihash parameters'
    i = 143 if ord(header[140]) == 253 else 141
    soln = get_indices_from_minimal(bytearray(header[i:i + num_bytes]),
                                    bit_len)

    hashes = []
    for xi in soln:
        r = xi % indices_per_hash_output
        # X_i = H(I||V||x_i)
        curr_digest = digest.copy()
        hash_xi(curr_digest, xi / indices_per_hash_output)
        tmp_hash = curr_digest.digest()
        hashes.append(
            expand_array(bytearray(tmp_hash[r * n / 8:(r + 1) * n / 8]),
                         hash_length, collision_length))
    return soln, hashes
コード例 #2
0
ファイル: test-pow.py プロジェクト: str4d/zcash-pow
 def testExpandAndCompress(self):
     out = expand_array(self.compact, len(self.expanded),
                        self.bit_len, self.byte_pad)
     self.assertEqual(self.expanded, out)
     out = compress_array(self.expanded, len(self.compact),
                          self.bit_len, self.byte_pad)
     self.assertEqual(self.compact, out)
コード例 #3
0
def get_indices_from_minimal(minimal, bit_len):
    eh_index_size = 4
    assert (bit_len + 7) / 8 <= eh_index_size
    len_indices = 8 * eh_index_size * len(minimal) / bit_len
    byte_pad = eh_index_size - (bit_len + 7) / 8
    expanded = expand_array(minimal, len_indices, bit_len, byte_pad)
    return [
        struct.unpack('>I', expanded[i:i + 4])[0]
        for i in range(0, len_indices, eh_index_size)
    ]
コード例 #4
0
def gbp_basic(digest, n, k):
    '''Implementation of Basic Wagner's algorithm for the GBP.'''
    collision_length = n / (k + 1)
    hash_length = (k + 1) * ((collision_length + 7) // 8)
    indices_per_hash_output = 512 / n

    # 1) Generate first list
    if DEBUG: print 'Generating first list'
    X = []
    tmp_hash = ''
    if DEBUG and progressbar: bar = progressbar.ProgressBar()
    else: bar = lambda x: x
    for i in bar(range(0, 2**(collision_length + 1))):
        r = i % indices_per_hash_output
        if r == 0:
            # X_i = H(I||V||x_i)
            curr_digest = digest.copy()
            hash_xi(curr_digest, i / indices_per_hash_output)
            tmp_hash = curr_digest.digest()
        X.append((expand_array(bytearray(tmp_hash[r * n / 8:(r + 1) * n / 8]),
                               hash_length, collision_length), (i, )))

    # 3) Repeat step 2 until 2n/(k+1) bits remain
    for i in range(1, k):
        if DEBUG: print 'Round %d:' % i

        # 2a) Sort the list
        if DEBUG: print '- Sorting list'
        X.sort(key=itemgetter(0))
        if DEBUG and VERBOSE:
            for Xi in X[-32:]:
                print '%s %s' % (print_hash(Xi[0]), Xi[1])

        if DEBUG: print '- Finding collisions'
        Xc = []
        if DEBUG and progressbar:
            orig_size = len(X)
            pbar = progressbar.ProgressBar(max_value=orig_size)
        while len(X) > 0:
            # 2b) Find next set of unordered pairs with collisions on first n/(k+1) bits
            j = 1
            while j < len(X):
                if not has_collision(X[-1][0], X[-1 - j][0], i,
                                     collision_length):
                    break
                j += 1

            # 2c) Store tuples (X_i ^ X_j, (i, j)) on the table
            for l in range(0, j - 1):
                for m in range(l + 1, j):
                    # Check that there are no duplicate indices in tuples i and j
                    if distinct_indices(X[-1 - l][1], X[-1 - m][1]):
                        if X[-1 - l][1][0] < X[-1 - m][1][0]:
                            concat = X[-1 - l][1] + X[-1 - m][1]
                        else:
                            concat = X[-1 - m][1] + X[-1 - l][1]
                        Xc.append((xor(X[-1 - l][0], X[-1 - m][0]), concat))

            # 2d) Drop this set
            while j > 0:
                X.pop(-1)
                j -= 1
            if DEBUG and progressbar: pbar.update(orig_size - len(X))
        if DEBUG and progressbar: pbar.finish()
        # 2e) Replace previous list with new list
        X = Xc

    # k+1) Find a collision on last 2n(k+1) bits
    if DEBUG:
        print 'Final round:'
        print '- Sorting list'
    X.sort(key=itemgetter(0))
    if DEBUG and VERBOSE:
        for Xi in X[-32:]:
            print '%s %s' % (print_hash(Xi[0]), Xi[1])
    if DEBUG: print '- Finding collisions'
    solns = []
    if DEBUG and progressbar:
        orig_size = len(X)
        pbar = progressbar.ProgressBar(max_value=orig_size,
                                       redirect_stdout=True)
    while len(X) > 0:
        j = 1
        while j < len(X):
            if not (has_collision(X[-1][0], X[-1 - j][0], k, collision_length)
                    and has_collision(X[-1][0], X[-1 - j][0], k + 1,
                                      collision_length)):
                break
            j += 1

        for l in range(0, j - 1):
            for m in range(l + 1, j):
                res = xor(X[-1 - l][0], X[-1 - m][0])
                if count_zeroes(res) == 8 * hash_length and distinct_indices(
                        X[-1 - l][1], X[-1 - m][1]):
                    if DEBUG and VERBOSE:
                        print 'Found solution:'
                        print '- %s %s' % (print_hash(
                            X[-1 - l][0]), X[-1 - l][1])
                        print '- %s %s' % (print_hash(
                            X[-1 - m][0]), X[-1 - m][1])
                    if X[-1 - l][1][0] < X[-1 - m][1][0]:
                        solns.append(list(X[-1 - l][1] + X[-1 - m][1]))
                    else:
                        solns.append(list(X[-1 - m][1] + X[-1 - l][1]))

        # 2d) Drop this set
        while j > 0:
            X.pop(-1)
            j -= 1
        if DEBUG and progressbar: pbar.update(orig_size - len(X))
    if DEBUG and progressbar: pbar.finish()
    return solns
コード例 #5
0
ファイル: pow.py プロジェクト: str4d/zcash-pow
def gbp_basic(digest, n, k):
    '''Implementation of Basic Wagner's algorithm for the GBP.'''
    collision_length = n/(k+1)
    hash_length = (k+1)*((collision_length+7)//8)
    indices_per_hash_output = 512/n

    # 1) Generate first list
    if DEBUG: print 'Generating first list'
    X = []
    tmp_hash = ''
    if DEBUG and progressbar: bar = progressbar.ProgressBar()
    else: bar = lambda x: x
    for i in bar(range(0, 2**(collision_length+1))):
        r = i % indices_per_hash_output
        if r == 0:
            # X_i = H(I||V||x_i)
            curr_digest = digest.copy()
            hash_xi(curr_digest, i/indices_per_hash_output)
            tmp_hash = curr_digest.digest()
        X.append((
            expand_array(bytearray(tmp_hash[r*n/8:(r+1)*n/8]),
                         hash_length, collision_length),
            (i,)
        ))

    # 3) Repeat step 2 until 2n/(k+1) bits remain
    for i in range(1, k):
        if DEBUG: print 'Round %d:' % i

        # 2a) Sort the list
        if DEBUG: print '- Sorting list'
        X.sort(key=itemgetter(0))
        if DEBUG and VERBOSE:
            for Xi in X[-32:]:
                print '%s %s' % (print_hash(Xi[0]), Xi[1])

        if DEBUG: print '- Finding collisions'
        Xc = []
        if DEBUG and progressbar:
            orig_size = len(X)
            pbar = progressbar.ProgressBar(max_value=orig_size)
        while len(X) > 0:
            # 2b) Find next set of unordered pairs with collisions on first n/(k+1) bits
            j = 1
            while j < len(X):
                if not has_collision(X[-1][0], X[-1-j][0], i, collision_length):
                    break
                j += 1

            # 2c) Store tuples (X_i ^ X_j, (i, j)) on the table
            for l in range(0, j-1):
                for m in range(l+1, j):
                    # Check that there are no duplicate indices in tuples i and j
                    if distinct_indices(X[-1-l][1], X[-1-m][1]):
                        if X[-1-l][1][0] < X[-1-m][1][0]:
                            concat = X[-1-l][1] + X[-1-m][1]
                        else:
                            concat = X[-1-m][1] + X[-1-l][1]
                        Xc.append((xor(X[-1-l][0], X[-1-m][0]), concat))

            # 2d) Drop this set
            while j > 0:
                X.pop(-1)
                j -= 1
            if DEBUG and progressbar: pbar.update(orig_size - len(X))
        if DEBUG and progressbar: pbar.finish()
        # 2e) Replace previous list with new list
        X = Xc

    # k+1) Find a collision on last 2n(k+1) bits
    if DEBUG:
        print 'Final round:'
        print '- Sorting list'
    X.sort(key=itemgetter(0))
    if DEBUG and VERBOSE:
        for Xi in X[-32:]:
            print '%s %s' % (print_hash(Xi[0]), Xi[1])
    if DEBUG: print '- Finding collisions'
    solns = []
    if DEBUG and progressbar:
        orig_size = len(X)
        pbar = progressbar.ProgressBar(max_value=orig_size, redirect_stdout=True)
    while len(X) > 0:
        j = 1
        while j < len(X):
            if not (has_collision(X[-1][0], X[-1-j][0], k, collision_length) and
                    has_collision(X[-1][0], X[-1-j][0], k+1, collision_length)):
                break
            j += 1

        for l in range(0, j-1):
            for m in range(l+1, j):
                res = xor(X[-1-l][0], X[-1-m][0])
                if count_zeroes(res) == 8*hash_length and distinct_indices(X[-1-l][1], X[-1-m][1]):
                    if DEBUG and VERBOSE:
                        print 'Found solution:'
                        print '- %s %s' % (print_hash(X[-1-l][0]), X[-1-l][1])
                        print '- %s %s' % (print_hash(X[-1-m][0]), X[-1-m][1])
                    if X[-1-l][1][0] < X[-1-m][1][0]:
                        solns.append(list(X[-1-l][1] + X[-1-m][1]))
                    else:
                        solns.append(list(X[-1-m][1] + X[-1-l][1]))

        # 2d) Drop this set
        while j > 0:
            X.pop(-1)
            j -= 1
        if DEBUG and progressbar: pbar.update(orig_size - len(X))
    if DEBUG and progressbar: pbar.finish()
    return solns