URI: 
       tmove crypto from wallet class to bitcoin.py - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 5d6496f1f920aa70b129f1e54321ddd59c766b51
   DIR parent 8a8aeb456780c016e876526128be1adf7676db9a
  HTML Author: thomasv <thomasv@gitorious>
       Date:   Fri, 22 Feb 2013 16:17:46 +0100
       
       move crypto from wallet class to bitcoin.py
       
       Diffstat:
         M electrum                            |       4 +++-
         M lib/__init__.py                     |       2 +-
         M lib/bitcoin.py                      |      66 +++++++++++++++++++++++++++++++
         M lib/wallet.py                       |      69 +++----------------------------
       
       4 files changed, 75 insertions(+), 66 deletions(-)
       ---
   DIR diff --git a/electrum b/electrum
       t@@ -662,6 +662,7 @@ if __name__ == '__main__':
                message = ' '.join(args[2:])
                if len(args) > 3:
                    print_msg("Warning: Message was reconstructed from several arguments:", repr(message))
       +
                print_msg(wallet.sign_message(address, message, password))
        
            elif cmd == 'verifymessage':
       t@@ -675,8 +676,9 @@ if __name__ == '__main__':
                    sys.exit(1)
                if len(args) > 4:
                    print_msg("Warning: Message was reconstructed from several arguments:", repr(message))
       +        EC_KEY.verify_message(address, signature, message)
                try:
       -            wallet.verify_message(address, signature, message)
       +            EC_KEY.verify_message(address, signature, message)
                    print_msg(True)
                except BaseException as e:
                    print_error("Verification error: {0}".format(e))
   DIR diff --git a/lib/__init__.py b/lib/__init__.py
       t@@ -7,6 +7,6 @@ from verifier import WalletVerifier
        from interface import Interface, pick_random_server, DEFAULT_SERVERS
        from simple_config import SimpleConfig
        import bitcoin
       -from bitcoin import Transaction
       +from bitcoin import Transaction, EC_KEY
        from mnemonic import mn_encode as mnemonic_encode
        from mnemonic import mn_decode as mnemonic_decode
   DIR diff --git a/lib/bitcoin.py b/lib/bitcoin.py
       t@@ -273,12 +273,78 @@ generator_secp256k1 = ecdsa.ellipticcurve.Point( curve_secp256k1, _Gx, _Gy, _r )
        oid_secp256k1 = (1,3,132,0,10)
        SECP256k1 = ecdsa.curves.Curve("SECP256k1", curve_secp256k1, generator_secp256k1, oid_secp256k1 ) 
        
       +from ecdsa.util import string_to_number, number_to_string
       +
       +def msg_magic(message):
       +    return "\x18Bitcoin Signed Message:\n" + chr( len(message) ) + message
       +
       +
        class EC_KEY(object):
            def __init__( self, secret ):
                self.pubkey = ecdsa.ecdsa.Public_key( generator_secp256k1, generator_secp256k1 * secret )
                self.privkey = ecdsa.ecdsa.Private_key( self.pubkey, secret )
                self.secret = secret
        
       +    def sign_message(self, message, compressed, address):
       +        private_key = ecdsa.SigningKey.from_secret_exponent( self.secret, curve = SECP256k1 )
       +        public_key = private_key.get_verifying_key()
       +        signature = private_key.sign_digest( Hash( msg_magic(message) ), sigencode = ecdsa.util.sigencode_string )
       +        assert public_key.verify_digest( signature, Hash( msg_magic(message) ), sigdecode = ecdsa.util.sigdecode_string)
       +        for i in range(4):
       +            sig = base64.b64encode( chr(27 + i + (4 if compressed else 0)) + signature )
       +            try:
       +                self.verify_message( address, sig, message)
       +                return sig
       +            except:
       +                continue
       +        else:
       +            raise BaseException("error: cannot sign message")
       +
       +    @classmethod
       +    def verify_message(self, address, signature, message):
       +        """ See http://www.secg.org/download/aid-780/sec1-v2.pdf for the math """
       +        from ecdsa import numbertheory, ellipticcurve, util
       +        import msqr
       +        curve = curve_secp256k1
       +        G = generator_secp256k1
       +        order = G.order()
       +        # extract r,s from signature
       +        sig = base64.b64decode(signature)
       +        if len(sig) != 65: raise BaseException("Wrong encoding")
       +        r,s = util.sigdecode_string(sig[1:], order)
       +        nV = ord(sig[0])
       +        if nV < 27 or nV >= 35:
       +            raise BaseException("Bad encoding")
       +        if nV >= 31:
       +            compressed = True
       +            nV -= 4
       +        else:
       +            compressed = False
       +
       +        recid = nV - 27
       +        # 1.1
       +        x = r + (recid/2) * order
       +        # 1.3
       +        alpha = ( x * x * x  + curve.a() * x + curve.b() ) % curve.p()
       +        beta = msqr.modular_sqrt(alpha, curve.p())
       +        y = beta if (beta - recid) % 2 == 0 else curve.p() - beta
       +        # 1.4 the constructor checks that nR is at infinity
       +        R = ellipticcurve.Point(curve, x, y, order)
       +        # 1.5 compute e from message:
       +        h = Hash( msg_magic(message) )
       +        e = string_to_number(h)
       +        minus_e = -e % order
       +        # 1.6 compute Q = r^-1 (sR - eG)
       +        inv_r = numbertheory.inverse_mod(r,order)
       +        Q = inv_r * ( s * R + minus_e * G )
       +        public_key = ecdsa.VerifyingKey.from_public_point( Q, curve = SECP256k1 )
       +        # check that Q is the public key
       +        public_key.verify_digest( sig[1:], h, sigdecode = ecdsa.util.sigdecode_string)
       +        # check that we get the original signing address
       +        addr = public_key_to_bc_address( encode_point(public_key, compressed) )
       +        if address != addr:
       +            raise BaseException("Bad signature")
       +
        
        ###################################### BIP32 ##############################
        
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -216,71 +216,12 @@ class Wallet:
        
                return secexp, compressed
        
       -    def msg_magic(self, message):
       -        return "\x18Bitcoin Signed Message:\n" + chr( len(message) ) + message
       -
            def sign_message(self, address, message, password):
       -        secexp, compressed = self.get_private_key(address, password)
       -        private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 )
       -        public_key = private_key.get_verifying_key()
       -        signature = private_key.sign_digest( Hash( self.msg_magic( message ) ), sigencode = ecdsa.util.sigencode_string )
       -        assert public_key.verify_digest( signature, Hash( self.msg_magic( message ) ), sigdecode = ecdsa.util.sigdecode_string)
       -        for i in range(4):
       -            sig = base64.b64encode( chr(27 + i + (4 if compressed else 0)) + signature )
       -            try:
       -                self.verify_message( address, sig, message)
       -                return sig
       -            except:
       -                continue
       -        else:
       -            raise BaseException("error: cannot sign message")
       -
       -
       -    def verify_message(self, address, signature, message):
       -        """ See http://www.secg.org/download/aid-780/sec1-v2.pdf for the math """
       -        from ecdsa import numbertheory, ellipticcurve, util
       -        import msqr
       -        curve = curve_secp256k1
       -        G = generator_secp256k1
       -        order = G.order()
       -        # extract r,s from signature
       -        sig = base64.b64decode(signature)
       -        if len(sig) != 65: raise BaseException("Wrong encoding")
       -        r,s = util.sigdecode_string(sig[1:], order)
       -        nV = ord(sig[0])
       -        if nV < 27 or nV >= 35:
       -            raise BaseException("Bad encoding")
       -        if nV >= 31:
       -            compressed = True
       -            nV -= 4
       -        else:
       -            compressed = False
       -
       -        recid = nV - 27
       -        # 1.1
       -        x = r + (recid/2) * order
       -        # 1.3
       -        alpha = ( x * x * x  + curve.a() * x + curve.b() ) % curve.p()
       -        beta = msqr.modular_sqrt(alpha, curve.p())
       -        y = beta if (beta - recid) % 2 == 0 else curve.p() - beta
       -        # 1.4 the constructor checks that nR is at infinity
       -        R = ellipticcurve.Point(curve, x, y, order)
       -        # 1.5 compute e from message:
       -        h = Hash( self.msg_magic( message ) )
       -        e = string_to_number(h)
       -        minus_e = -e % order
       -        # 1.6 compute Q = r^-1 (sR - eG)
       -        inv_r = numbertheory.inverse_mod(r,order)
       -        Q = inv_r * ( s * R + minus_e * G )
       -        public_key = ecdsa.VerifyingKey.from_public_point( Q, curve = SECP256k1 )
       -        # check that Q is the public key
       -        public_key.verify_digest( sig[1:], h, sigdecode = ecdsa.util.sigdecode_string)
       -        # check that we get the original signing address
       -        addr = public_key_to_bc_address( encode_point(public_key, compressed) )
       -        if address != addr:
       -            raise BaseException("Bad signature")
       -    
       -
       +        sec = self.get_private_key_base58(address, password)
       +        key = regenerate_key(sec)
       +        compressed = is_compressed(sec)
       +        return key.sign_message(message, compressed, address)
       +        
            def create_new_address(self, for_change):
                n = len(self.change_addresses) if for_change else len(self.addresses)
                address = self.get_new_address(n, for_change)