def new_keys(): "Generate a public/private keypair for hash-based signatures" sk = "" digest1 = "" digest2 = "" # First half for n in range(256): for b in False, True: secret = os.urandom(32) sk += secret digest1 += sha256(secret) # First Second for n in range(256): for b in False, True: secret = os.urandom(32) sk += secret digest2 += sha256(secret) pk = sha256(sha256(digest1) + sha256(digest2)) return pk, sk
def verify(msg, sig, pk): "verify a 256-bit value using hash-bash signatures" msg = crypturd.fixed_length_key(msg, 32) checksum = 0 digest = "" for i in range(32): c = ord(msg[i]) checksum += c digest += hash_times(sig[i * 32:i * 32 + 32], 256 - c) digest += hash_times(sig[-64:-32], checksum // 256) digest += hash_times(sig[-32:], checksum % 256) return sha256(digest) == pk
def new_keys(sk=None): "Generate a public/private keypair for hash-based signatures" if not sk or len(sk) < 32 * 34: sk = os.urandom(32 * 34) pk = "" # 32 secrets for 32 blocks of 8-bits each for n in range(32): pk += hash_times(sk[n * 32:n * 32 + 32], 256) # 2 checksum blocks pk += hash_times(sk[-64:-32], 32) pk += hash_times(sk[-32:], 256) return sha256(pk), sk
def digest_right(msg2, sig): "verify 2 256-bit values using hash-bash signatures (second part)" msg1 = crypturd.fixed_length_key(msg2, 32) digest2 = "" M2 = crypturd.bigendian2int(msg2) for i in range(256): zero = sig[i * 64 + 16384:i * 64 + 16416] one = sig[i * 64 + 16416:i * 64 + 16448] if ((1 << i) & M2) > 0: one = crypturd.sha256(one) else: zero = crypturd.sha256(zero) digest2 += zero + one return sha256(digest2)
def digest_left(msg1, sig): "verify 2 256-bit values using hash-bash signatures (first part)" msg1 = crypturd.fixed_length_key(msg1, 32) digest1 = "" M1 = crypturd.bigendian2int(msg1) for i in range(256): zero = sig[i * 64:i * 64 + 32] one = sig[i * 64 + 32:i * 64 + 64] if ((1 << i) & M1) > 0: one = crypturd.sha256(one) else: zero = crypturd.sha256(zero) digest1 += zero + one return sha256(digest1)
def verify(msg1, msg2, sig, pk): "verify 2 256-bit values using hash-bash signatures" return sha256(digest_left(msg1, sig) + digest_right(msg2, sig)) == pk