Monday, August 12, 2013

Another Simple sha256 Proof of work

This is a very simple implementation of a proof of work for Python 3. The idea is to encode a string in sha256 and look for a token that will make the string+token to start with a given number of zeros.

It is based on this link: simple-hashcash-implementation

The main difference is that this code create trailing zeros and sha1while my use leading zeros and sha256.


import math, itertools
from hashlib import *


def lz(n):
# Number of leading 0s in binary representation of integer n.
    if n <=0 : return 0

#   string with binary representation
    b = bin(n)[2:].zfill(256)

    i = 0
    for c in b:
#       print(c)
        if c == '0':
            i = i + 1
        else:
            break
    return i

def irange(n):
# Implementation of xrange(n) that does not overflow.
    i = 0
    while i < n:
        yield i; i += 1

def all_strings(charset='0123456789abcdef'):
# Yields all strings in given character set, sorted by length.
    m = len(charset)   
    for n in itertools.count(0):
        for i in irange(m**n):
            yield ''.join([charset[(i//(m**j))%m] for j in range(n)])


def hash(s_to_hash):
# Hash function used by hashcash. Returns an integer.
    s = s_to_hash.encode('utf-8')
    return int(sha256(s).hexdigest(), 16)

def mt(s_to_hash, n, charset='0123456789abcdef'):
# Makes hashcash token of value 'n' against basestring 's'.
    s = s_to_hash.encode('utf-8')
    h = sha256(s).hexdigest()
    for token in all_strings(charset):
        if lz(hash(h + token)) >= n: return token

def vt(s_to_hash, token):
# Returns hashcash value of given token against basestring 's'.

    s = (s_to_hash).encode('utf-8')
    return lz(hash(sha256(s).hexdigest() + token))
#

def Example():

    StringToConvert = input("Enter a string: ")
    MinLeadingZeros = int(input("Leading Zeros required: "))

    csha = StringToConvert.encode('utf-8')
    c_hex = sha256(csha).hexdigest()
    print("String sha256 (hex encoded): " + c_hex + "\n")
   
    c_bin = bin(int(c_hex, 16))[2:].zfill(256)
    print("String sha256 (bin encoded): " + c_bin + "\n")

    token = mt(StringToConvert,MinLeadingZeros)
    print("Token for this sha256: " + token)

    c_t = (c_hex + token).encode('utf-8')
    print("String + token (hex encoded): " + c_hex + token + "\n")

    c_t_hex = sha256(c_t).hexdigest()
    print("String + token sha256 (hex encoded): " + c_t_hex + "\n")

    c_t_bin = bin(int(c_t_hex, 16))[2:].zfill(256)
    print("String + token (bin encoded): " + c_t_bin + "\n")

    print("Verify Token")

    l_z = vt(StringToConvert,token)
    print("Verified Leading Zeros: " + str(l_z) + "\n")
   

def GetToken():
    StringToConvert = input("Enter a string: ")
    MinLeadingZeros = int(input("Leading Zeros required: "))

    StringToken = mt(StringToConvert, MinLeadingZeros)
    print(StringToken)

def VerifyToken():
    StringToVerify = input("Enter a string: ")
    TokenToVerify = input("Enter a Token: ")

    LeadingZeros = vt(StringToVerify, TokenToVerify)
    print(LeadingZeros)