def safe_public_child_key(extended_public_key, chain_code, i, return_as_hex=True): if not extended_public_key or not chain_code: return None AP = extended_public_key cP = chain_code assert 0 <= i < 2**31 i_bytes = i.to_bytes(4, 'little') if i < 2**31: # regular, non-hardened child Z = Fk(b'\x02' + AP + i_bytes, cP) c = Fk(b'\x03' + AP + i_bytes, cP)[32:] else: raise Exception("Can't create hardened keys from public key") ZL, ZR = Z[:28], Z[32:] A = ed25519.encodepoint( ed25519.edwards( ed25519.decodepoint(AP), ed25519.scalarmultbase(8 * int.from_bytes(ZL, 'little')))) # VERY IMPORTANT. DO NOT USE A CHILD KEY THAT IS EQUIVALENT TO THE IDENTITY POINT # "If Ai is the identity point (0, 1), discard the child." # - "BIP32-Ed25519 Hierarchical Deterministic Keys over a Non-linear Keyspace" (https://drive.google.com/file/d/0ByMtMw2hul0EMFJuNnZORDR2NDA/view) if A == ed25519.encodepoint([0, 1]): return -1 if return_as_hex: return (A.hex(), c.hex()) else: return (A, c)
def private_child_key(node, i): if not node: return None # unpack argument ((kLP, kRP), AP, cP) = node assert 0 <= i < 2**32 i_bytes = i.to_bytes(4, 'little') if i < 2**31: # regular child Z = Fk(b'\x02' + AP + i_bytes, cP) c = Fk(b'\x03' + AP + i_bytes, cP)[32:] else: # hardened child Z = Fk(b'\x00' + (kLP + kRP) + i_bytes, cP) c = Fk(b'\x01' + (kLP + kRP) + i_bytes, cP)[32:] ZL, ZR = Z[:28], Z[32:] kLn = (int.from_bytes(ZL, 'little') * 8) + int.from_bytes(kLP, 'little') # "If kL is divisible by the base order n, discard the child." # - "BIP32-Ed25519 Hierarchical Deterministic Keys over a Non-linear Keyspace" (https://drive.google.com/file/d/0ByMtMw2hul0EMFJuNnZORDR2NDA/view) if kLn % ed25519.l == 0: return -1 kRn = (int.from_bytes(ZR, 'little') + int.from_bytes(kRP, 'little')) % 2**256 kL = kLn.to_bytes(32, 'little') kR = kRn.to_bytes(32, 'little') A = ed25519.encodepoint( ed25519.scalarmultbase(int.from_bytes(kL, 'little'))) return ((kL, kR), A, c)
def generate_key_derivation(public, private): point = ed25519.scalarmult(ed25519.decodepoint(unhexlify(public)), hex2int(private)) ##multiply by 8 for security res = ed25519.scalarmult(point, 8) ## return hex encoding of the resulting point return hexlify(ed25519.encodepoint(res))
def private_child_key(node, i): if not node: return None # unpack argument ((kLP, kRP), AP, cP) = node assert 0 <= i < 2**32 i_bytes = i.to_bytes(4, 'little') if i < 2**31: # regular child Z = Fk(b'\x02' + AP + i_bytes, cP) c = Fk(b'\x03' + AP + i_bytes, cP)[32:] else: # harderned child Z = Fk(b'\x00' + (kLP + kRP) + i_bytes, cP) c = Fk(b'\x01' + (kLP + kRP) + i_bytes, cP)[32:] ZL, ZR = Z[:28], Z[32:] kLn = int.from_bytes(ZL, 'little') * 8 + int.from_bytes(kLP, 'little') if kLn % ed25519.l == 0: return None kRn = (int.from_bytes(ZR, 'little') + int.from_bytes(kRP, 'little')) % 2**256 kL = kLn.to_bytes(32, 'little') kR = kRn.to_bytes(32, 'little') A = ed25519.encodepoint( ed25519.scalarmult(ed25519.B, int.from_bytes(kL, 'little'))).encode('iso-8859-1') return ((kL, kR), A, c)
def special_signing( kL, kR, A, M ): # private/secret key left and right sides kL & kR, public key A, and message M in bytes r = h512(kR + M) r = int.from_bytes(r, 'little') % ed25519.l # base order n R = ed25519.encodepoint(ed25519.scalarmultbase(r)) x = int.from_bytes(h512(R + A + M), 'little') S = ed25519.encodeint((r + (x * int.from_bytes(kL, 'little'))) % ed25519.l) return R + S
def generate_stealth_address(publicViewKey, privateTxKey, publicSpendKey, index): ## multiply r*A derivation = utils.generate_key_derivation(publicViewKey, privateTxKey) ## concatenate index to derivation then hash and reduce ## Hs(rA|i) scalar = utils.derivation_to_scalar(derivation, index) ## multiply by base point ## Hs(rA|i)G sG = ed25519.scalarmultbase(utils.hex2int(scalar)) ## interpret the public spend key as a point on the curve pubPoint = ed25519.decodepoint(unhexlify(publicSpendKey)) ## add the public spend key to the previously calculated point ## Hs(rA|i)G + B output = ed25519.edwards(pubPoint, sG) ## convert the point to a hex encoded public key return hexlify(ed25519.encodepoint(output))
def root_key(master_secret): k = bytearray(h512(master_secret)) kL, kR = k[:32], k[32:] if kL[31] & 0b00100000: return None # clear lowest three bits of the first byte kL[0] = clear_bit(kL[0], 0b00000111) # clear highest bit of the last byte kL[31] = clear_bit(kL[31], 0b10000000) # set second highest bit of the last byte kL[31] = set_bit(kL[31], 0b01000000) # root public key A = ed25519.encodepoint( ed25519.scalarmult(ed25519.B, int.from_bytes(kL, 'little'))).encode('iso-8859-1') # root chain code c = h256(b'\x01' + master_secret) return ((kL, kR), A, c)
def root_key(master_secret): if type(master_secret) is not bytes: raise Exception("master_secret must be of type 'bytes'") if len(master_secret) != 32: raise Exception("master_secret must be 32 bytes (256-bits)") k = bytearray(h512(master_secret)) kL, kR = k[:32], k[32:] if kL[31] & 0b00100000: return None # clear lowest three bits of the first byte kL[0] = clear_bit(kL[0], 0b00000111) # clear highest bit of the last byte kL[31] = clear_bit(kL[31], 0b10000000) # set second highest bit of the last byte kL[31] = set_bit(kL[31], 0b01000000) # root public key A = ed25519.encodepoint( ed25519.scalarmultbase(int.from_bytes(kL, 'little'))) # root chain code c = h256(b'\x01' + master_secret) return ((kL, kR), A, c)
def fromPoint(aa): #supposed to reverse toPoint binvalue = ed25519.encodepoint(aa) return binascii.hexlify(binvalue)
def scalarmult_simple(pk, num): #returns point encoded to hex.. num is an int, not a hex return ed25519.encodepoint(ed25519.scalarmult(toPoint(pk), num)) #pub key is not just x coord..
def public_key(sk): #returns point encoded to binary .. sk is just an int.. return ed25519.encodepoint(ed25519.scalarmultbase(sk)) #pub key is not just x coord..
def publickey_to_privatekey(privateKey): point = ed25519.scalarmultbase(hex2int(privateKey)) return hexlify(ed25519.encodepoint(point))
def createLeaf(public_key , message): pk = ed.encodepoint(public_key) leaf = hashPadded(pk, message) return(leaf[2:])
import ed25519 sk = 32 * chr(0) pk = ed25519.publickey(sk) print "publickey for 0 is", pk.encode('hex') for i in [0, 1, 10]: print "encodeint %d = %s" % (i, ed25519.encodeint(i).encode('hex')) for p in [ (0, 0), (1, 1), (10, 0), (1, 10), (9639205628789703341510410801487549615560488670885798085067615194958049462616, 18930617471878267742194159801949745215346600387277955685031939302387136031291 ) ]: print "encodepoint %s = %s" % (repr(p), ed25519.encodepoint(p).encode('hex')) msg = "This is a secret message" sig = ed25519.signature(msg, sk, pk) print 'signature("%s") = %s' % (msg, sig.encode('hex')) try: ed25519.checkvalid(sig, msg, pk) print 'check signature result: true' except: print 'check signature result: false'
def public_key(sk): #returns point encoded to binary .. sk is just an int.. return ed25519.encodepoint( ed25519.scalarmultbase(sk)) #pub key is not just x coord..
def scalarmult_simple(pk, num): #returns point encoded to hex.. num is an int, not a hex return ed25519.encodepoint(ed25519.scalarmult( toPoint(pk), num)) #pub key is not just x coord..
def subKeys(P1, P2): return binascii.hexlify(ed25519.encodepoint(ed25519.edwards_Minus(toPoint(P1), toPoint(P2))))
def subKeys(P1, P2): return binascii.hexlify( ed25519.encodepoint(ed25519.edwards_Minus(toPoint(P1), toPoint(P2))))
def public_from_int(i): pubkey = ed25519.encodepoint(ed25519.scalarmultbase(i)) return hexlify(pubkey)