fix: get_seed
[electrum-nvc.git] / lib / bitcoin.py
index d38f409..d34b0ef 100644 (file)
 
 import hashlib, base64, ecdsa, re
 import hmac
+import aes
 from util import print_error
 
+# AES encryption
+EncodeAES = lambda secret, s: base64.b64encode(aes.encryptData(secret,s))
+DecodeAES = lambda secret, e: aes.decryptData(secret, base64.b64decode(e))
+
+def pw_encode(s, password):
+    if password:
+        secret = Hash(password)
+        return EncodeAES(secret, s)
+    else:
+        return s
+
+def pw_decode(s, password):
+    if password is not None:
+        secret = Hash(password)
+        try:
+            d = DecodeAES(secret, s)
+        except Exception:
+            raise Exception('Invalid password')
+        return d
+    else:
+        return s
+
+
+
+
+
 def rev_hex(s):
     return s.decode('hex')[::-1].encode('hex')
 
@@ -71,7 +98,25 @@ def mnemonic_to_seed(mnemonic, passphrase):
     return PBKDF2(mnemonic, 'mnemonic' + passphrase, iterations = PBKDF2_ROUNDS, macmodule = hmac, digestmodule = hashlib.sha512).read(64)
 
 from version import SEED_PREFIX
-is_seed = lambda x: hmac_sha_512("Seed version", x).encode('hex')[0:2].startswith(SEED_PREFIX)
+is_new_seed = lambda x: hmac_sha_512("Seed version", x.encode('utf8')).encode('hex')[0:2].startswith(SEED_PREFIX)
+
+def is_old_seed(seed):
+    import mnemonic
+    words = seed.strip().split()
+    try:
+        mnemonic.mn_decode(words)
+        uses_electrum_words = True
+    except Exception:
+        uses_electrum_words = False
+
+    try:
+        seed.decode('hex')
+        is_hex = (len(seed) == 32)
+    except Exception:
+        is_hex = False
+         
+    return is_hex or (uses_electrum_words and len(words) == 12)
+
 
 # pywallet openssl private key implementation
 
@@ -256,6 +301,7 @@ def public_key_from_private_key(sec):
     pkey = regenerate_key(sec)
     assert pkey
     compressed = is_compressed(sec)
+    print "is compressed", compressed
     public_key = GetPubKey(pkey.pubkey, compressed)
     return public_key.encode('hex')
 
@@ -267,6 +313,10 @@ def address_from_private_key(sec):
 
 
 def is_valid(addr):
+    return is_address(addr)
+
+
+def is_address(addr):
     ADDRESS_RE = re.compile('[1-9A-HJ-NP-Za-km-z]{26,}\\Z')
     if not ADDRESS_RE.match(addr): return False
     try:
@@ -276,6 +326,14 @@ def is_valid(addr):
     return addr == hash_160_to_bc_address(h, addrtype)
 
 
+def is_private_key(key):
+    try:
+        k = ASecretToSecret(key) 
+        return k is not False
+    except:
+        return False
+
+
 ########### end pywallet functions #######################
 
 try:
@@ -540,18 +598,17 @@ def get_pubkeys_from_secret(secret):
 # However, if n is positive, the resulting private key's corresponding
 #  public key can be determined without the master private key.
 def CKD_priv(k, c, n):
+    is_prime = n & BIP32_PRIME
+    return _CKD_priv(k, c, rev_hex(int_to_hex(n,4)).decode('hex'), is_prime)
+
+def _CKD_priv(k, c, s, is_prime):
     import hmac
     from ecdsa.util import string_to_number, number_to_string
     order = generator_secp256k1.order()
     keypair = EC_KEY(k)
-    K = GetPubKey(keypair.pubkey,True)
-
-    if n & BIP32_PRIME: # We want to make a "secret" address that can't be determined from K
-        data = chr(0) + k + rev_hex(int_to_hex(n,4)).decode('hex')
-        I = hmac.new(c, data, hashlib.sha512).digest()
-    else: # We want a "non-secret" address that can be determined from K
-        I = hmac.new(c, K + rev_hex(int_to_hex(n,4)).decode('hex'), hashlib.sha512).digest()
-        
+    cK = GetPubKey(keypair.pubkey,True)
+    data = chr(0) + k + s if is_prime else cK + s
+    I = hmac.new(c, data, hashlib.sha512).digest()
     k_n = number_to_string( (string_to_number(I[0:32]) + string_to_number(k)) % order , order )
     c_n = I[32:]
     return k_n, c_n
@@ -563,34 +620,38 @@ def CKD_priv(k, c, n):
 # This function allows us to find the nth public key, as long as n is 
 #  non-negative. If n is negative, we need the master private key to find it.
 def CKD_pub(cK, c, n):
+    if n & BIP32_PRIME: raise
+    return _CKD_pub(cK, c, rev_hex(int_to_hex(n,4)).decode('hex'))
+
+# helper function, callable with arbitrary string
+def _CKD_pub(cK, c, s):
     import hmac
     from ecdsa.util import string_to_number, number_to_string
     order = generator_secp256k1.order()
-    if n & BIP32_PRIME: raise
-    I = hmac.new(c, cK + rev_hex(int_to_hex(n,4)).decode('hex'), hashlib.sha512).digest()
+    I = hmac.new(c, cK + s, hashlib.sha512).digest()
     curve = SECP256k1
     pubkey_point = string_to_number(I[0:32])*curve.generator + ser_to_point(cK)
     public_key = ecdsa.VerifyingKey.from_public_point( pubkey_point, curve = SECP256k1 )
     c_n = I[32:]
     cK_n = GetPubKey(public_key.pubkey,True)
-
     return cK_n, c_n
 
 
-def parse_xprv(xprv):
-    xprv = DecodeBase58Check( xprv )
-    assert len(xprv) == 78
-    assert xprv[0:4] == "0488ADE4".decode('hex')
-    depth = ord(xprv[4])
-    fingerprint = xprv[5:9]
-    child_number = xprv[9:13]
-    c = xprv[13:13+32]
-    k = xprv[13+33:]
-    K, cK = get_pubkeys_from_secret(k)
-    key_id = hash_160(cK)
-    print "keyid", key_id.encode('hex')
-    print "address", hash_160_to_bc_address(key_id)
-    print "secret key", SecretToASecret(k, True)
+
+def deserialize_xkey(xkey):
+    xkey = DecodeBase58Check(xkey) 
+    assert len(xkey) == 78
+    assert xkey[0:4].encode('hex') in ["0488ade4", "0488b21e"]
+    depth = ord(xkey[4])
+    fingerprint = xkey[5:9]
+    child_number = xkey[9:13]
+    c = xkey[13:13+32]
+    if xkey[0:4].encode('hex') == "0488ade4":
+        K_or_k = xkey[13+33:]
+    else:
+        K_or_k = xkey[13+32:]
+    return depth, fingerprint, child_number, c, K_or_k
+
 
 
 def bip32_root(seed):
@@ -607,15 +668,8 @@ def bip32_root(seed):
 
 
 def bip32_private_derivation(xprv, branch, sequence):
-    xprv = DecodeBase58Check( xprv ) 
-    assert len(xprv) == 78
-    assert xprv[0:4] == "0488ADE4".decode('hex')
+    depth, fingerprint, child_number, c, k = deserialize_xkey(xprv)
     assert sequence.startswith(branch)
-    depth = ord(xprv[4])
-    fingerprint = xprv[5:9]
-    child_number = xprv[9:13]
-    c = xprv[13:13+32]
-    k = xprv[13+33:]
     sequence = sequence[len(branch):]
     for n in sequence.split('/'):
         if n == '': continue
@@ -635,15 +689,8 @@ def bip32_private_derivation(xprv, branch, sequence):
 
 
 def bip32_public_derivation(xpub, branch, sequence):
-    xpub = DecodeBase58Check( xpub ) 
-    assert len(xpub) == 78
-    assert xpub[0:4] == "0488B21E".decode('hex')
+    depth, fingerprint, child_number, c, cK = deserialize_xkey(xpub)
     assert sequence.startswith(branch)
-    depth = ord(xpub[4])
-    fingerprint = xpub[5:9]
-    child_number = xpub[9:13]
-    c = xpub[13:13+32]
-    cK = xpub[13+32:]
     sequence = sequence[len(branch):]
     for n in sequence.split('/'):
         if n == '': continue
@@ -670,7 +717,7 @@ def bip32_private_key(sequence, k, chain):
 
 ################################## transactions
 
-MIN_RELAY_TX_FEE = 10000
+MIN_RELAY_TX_FEE = 1000
 
 
 
@@ -683,7 +730,6 @@ def test_bip32(seed, sequence):
     xprv, xpub = bip32_root(seed)
     print xpub
     print xprv
-    #parse_xprv(xprv)
 
     assert sequence[0:2] == "m/"
     path = 'm'