Example #1
0
def new_masterkey(passphrase,
                  rand=Random(),
                  get_time=time.time,
                  nb_iterations_test=25000):
    """Create a new masterkey"""
    crypter = Crypter()
    plain_master_key = rand.get_random_bytes(WALLET_CRYPTO_KEY_SIZE)
    rand.add_system_seeds()
    salt = rand.get_random_bytes(WALLET_CRYPTO_SALT_SIZE)
    deriv_method = MasterKey.DERIVMETHOD_EVP_SHA512

    target_seconds = 0.1  #100ms
    # estimate number of derivations for 100ms per decrypt using 25000 iterations.
    start_time = get_time()
    derive_key_from_passphrase(passphrase, salt, nb_iterations_test,
                               deriv_method)
    estimate1 = int((nb_iterations_test * 1.0 * target_seconds) /
                    (get_time() - start_time))
    # try it and take the mean of the estimate1 and estimate2
    start_time = get_time()
    derive_key_from_passphrase(passphrase, salt, estimate1, deriv_method)
    estimate2 = int(estimate1 * target_seconds / (get_time() - start_time))
    deriv_iterations = (estimate1 + estimate2) / 2
    # use it
    key, init_vect = derive_key_from_passphrase(passphrase, salt,
                                                deriv_iterations, deriv_method)
    crypter.set_key(key, init_vect)
    crypted_key = crypter.encrypt(plain_master_key)
    return MasterKey(crypted_key, salt, deriv_method, deriv_iterations)
Example #2
0
 def __init__(self, wallet_database, runmode):
     super(Wallet, self).__init__()
     self.wallet_database = wallet_database
     self.runmode = runmode
     self.addresses = {}
     self.crypter = Crypter()
     self.plain_masterkeys = []
Example #3
0
def decrypt_masterkey(master_key, passphrase):
    """Return plain master key bytestring from a MasterKey object and a passphrase"""
    key, init_vect = derive_key_from_passphrase(passphrase, master_key.salt,  master_key.derive_iterations, master_key.derivation_method)
    crypter = Crypter()
    crypter.set_key(key, init_vect)
    plain_masterkey = crypter.decrypt(master_key.crypted_key)
    return plain_masterkey
Example #4
0
def decrypt_masterkey(master_key, passphrase):
    """Return plain master key bytestring from a MasterKey object and a passphrase"""
    key, init_vect = derive_key_from_passphrase(passphrase, master_key.salt,
                                                master_key.derive_iterations,
                                                master_key.derivation_method)
    crypter = Crypter()
    crypter.set_key(key, init_vect)
    plain_masterkey = crypter.decrypt(master_key.crypted_key)
    return plain_masterkey
Example #5
0
 def __init__(self, wallet_database, runmode):
     super(Wallet, self).__init__()
     self.wallet_database = wallet_database
     self.runmode = runmode
     self.addresses = {}
     self.crypter = Crypter()
     self.plain_masterkeys = []
Example #6
0
    def create(self, passphrase):
        self.wallet_database.begin_updates()
        crypter = Crypter()
        #first create masterkey
        master_key = new_masterkey(passphrase)
        plain_masterkey = decrypt_masterkey(master_key, passphrase)
        self.wallet_database.add_master_key(master_key)
        #create transaction pool
        for i in range(100):
            k = KEY()
            k.generate(True)
            public_key = k.get_pubkey()
            crypter.set_key(plain_masterkey, doublesha256(public_key))
            crypted_secret = crypter.encrypt(k.get_secret())
            self.wallet_database.add_crypted_key(public_key, crypted_secret)
            pool_key = WalletPoolKey(i, 60000, time.time(), public_key)
            self.wallet_database.add_poolkey(pool_key)

        self.wallet_database.commit_updates()
        self.load()
Example #7
0
 def create(self, passphrase):
     self.wallet_database.begin_updates()
     crypter = Crypter()
     #first create masterkey
     master_key =  new_masterkey(passphrase)
     plain_masterkey = decrypt_masterkey(master_key, passphrase)
     self.wallet_database.add_master_key(master_key)
     #create transaction pool
     for i in range(100):
         k = KEY()
         k.generate(True)
         public_key = k.get_pubkey()
         crypter.set_key(plain_masterkey, doublesha256(public_key))
         crypted_secret = crypter.encrypt(k.get_secret())
         self.wallet_database.add_crypted_key(public_key, crypted_secret)
         pool_key = WalletPoolKey(i, 60000, time.time(), public_key)
         self.wallet_database.add_poolkey(pool_key)
         
         
     self.wallet_database.commit_updates()
     self.load()
Example #8
0
def new_masterkey(passphrase, rand=Random(), get_time=time.time, nb_iterations_test=25000):
    """Create a new masterkey"""
    crypter = Crypter()
    plain_master_key = rand.get_random_bytes(WALLET_CRYPTO_KEY_SIZE)
    rand.add_system_seeds()
    salt = rand.get_random_bytes(WALLET_CRYPTO_SALT_SIZE)
    deriv_method = MasterKey.DERIVMETHOD_EVP_SHA512
    
    target_seconds = 0.1 #100ms
    # estimate number of derivations for 100ms per decrypt using 25000 iterations.
    start_time = get_time()
    derive_key_from_passphrase(passphrase, salt, nb_iterations_test, deriv_method)
    estimate1 = int((nb_iterations_test * 1.0 * target_seconds) / (get_time() - start_time))
    # try it and take the mean of the estimate1 and estimate2
    start_time = get_time()
    derive_key_from_passphrase(passphrase, salt, estimate1, deriv_method)
    estimate2 = int(estimate1 * target_seconds / (get_time() - start_time))
    deriv_iterations = (estimate1 + estimate2) / 2
    # use it
    key, init_vect = derive_key_from_passphrase(passphrase, salt, deriv_iterations, deriv_method)
    crypter.set_key(key, init_vect)
    crypted_key = crypter.encrypt(plain_master_key)
    return MasterKey(crypted_key, salt, deriv_method, deriv_iterations)
Example #9
0
class Wallet(Observable):
    '''
        Wallet implementes the basic satoshi wallet logic.
           Database logic is implemented in WalletDatabase
           Features requiring a blockchain are implemented in WalletAccount.
    '''
    EVT_NEW_TRANSACTION = Observable.createevent()

    def __init__(self, wallet_database, runmode):
        super(Wallet, self).__init__()
        self.wallet_database = wallet_database
        self.runmode = runmode
        self.addresses = {}
        self.crypter = Crypter()
        self.plain_masterkeys = []

    def open(self):
        self.wallet_database.open()
        self.load()

    def create(self, passphrase):
        self.wallet_database.begin_updates()
        crypter = Crypter()
        #first create masterkey
        master_key = new_masterkey(passphrase)
        plain_masterkey = decrypt_masterkey(master_key, passphrase)
        self.wallet_database.add_master_key(master_key)
        #create transaction pool
        for i in range(100):
            k = KEY()
            k.generate(True)
            public_key = k.get_pubkey()
            crypter.set_key(plain_masterkey, doublesha256(public_key))
            crypted_secret = crypter.encrypt(k.get_secret())
            self.wallet_database.add_crypted_key(public_key, crypted_secret)
            pool_key = WalletPoolKey(i, 60000, time.time(), public_key)
            self.wallet_database.add_poolkey(pool_key)

        self.wallet_database.commit_updates()
        self.load()

    def load(self):
        for public_key, keypair in self.wallet_database.get_keys().iteritems():
            self.addresses[BitcoinAddress.from_publickey(
                public_key, self.runmode)] = (public_key, False)
        for public_key, secret in self.wallet_database.get_crypted_keys(
        ).iteritems():
            self.addresses[BitcoinAddress.from_publickey(
                public_key, self.runmode)] = (public_key, True)

    def begin_updates(self):
        self.wallet_database.begin_updates()

    def commit_updates(self):
        self.wallet_database.commit_updates()

    def get_receive_key(self):
        return self.wallet_database.get_receive_key()

    def allocate_key(self, public_key, label=None, ischange=False):
        address = BitcoinAddress.from_publickey(public_key, self.runmode)
        return self.wallet_database.allocate_key(public_key, address, label)

    def add_transaction(self, hashtx, wallet_tx):
        self.wallet_database.set_transaction(hashtx, wallet_tx)

    def get_transaction(self, hashtx):
        return self.wallet_database.get_transaction(hashtx)

    def set_transaction(self, hashtx, wallet_tx):
        self.wallet_database.set_transaction(hashtx, wallet_tx)

    def del_transaction(self, hashtx):
        self.wallet_database.del_transaction(hashtx)

    """
        yields ( public_key, is_crypted, address, description ) entries.
    """

    def iterkeys(self):
        names = self.wallet_database.get_names()
        for address, (public_key, is_crypted) in self.addresses.iteritems():
            description = self.get_address_description(public_key)
            yield (public_key, is_crypted, address, description)

    def get_address_description(self, public_key):
        address = BitcoinAddress.from_publickey(public_key, self.runmode)
        description = ""
        if public_key in self.wallet_database.poolkeys_by_public_key:
            poolkey = self.wallet_database.poolkeys_by_public_key[public_key]
            description = "Pool (id:%d, time:%s)" % (
                poolkey.poolnum,
                time.strftime("%Y-%m-%d %H:%m:%S", time.gmtime(poolkey.time)))
        else:
            if address in self.wallet_database.get_names():
                description = "Receive (\"%s\")" % self.wallet_database.get_names(
                )[address].name
            else:
                description = "Change"
        return description

    def iter_my_outputs(self):
        for hash, wallet_tx in self.wallet_database.get_wallet_txs().iteritems(
        ):
            for index, txout in enumerate(wallet_tx.merkle_tx.tx.out_list):
                if not wallet_tx.is_spent(index) and self.is_mine(txout):
                    yield (wallet_tx.merkle_tx.tx, Outpoint(hash,
                                                            index), txout)
                    #yield ControlledOutput(hash, wallet_tx.merkle_tx.tx, index, txout, self.get_keypair_for_output(txout))

    ''''
        A TxIn is "debit" if the previous output is in the wallet and is mine.
        If it is, get_debit_txin will return the value spent.
        Debit transaction are used only for transaction history.
        The balance is computed using unspent transactions.
    '''

    def get_debit_txin(self, txin):
        if txin.previous_output.hash not in self.wallet_database.get_wallet_txs(
        ):
            return 0
        txprev = self.wallet_database.get_wallet_txs()[
            txin.previous_output.hash]
        txout = txprev.merkle_tx.tx.out_list[txin.previous_output.index]
        if not self.is_mine(txout):
            return 0
        return txout.value

    def get_debit_tx(self, wallet_tx):
        return sum(
            self.get_debit_txin(txin)
            for txin in wallet_tx.merkle_tx.tx.in_list)

    def get_credit_txout(self, txout):
        if self.is_mine(txout):
            return txout.value
        return 0

    def get_credit_tx(self, wallet_tx):
        return sum(
            self.get_credit_txout(txout)
            for txout in wallet_tx.merkle_tx.tx.out_list)

    def iter_transaction_history(self):  # see wallet.cpp:448 GetAmounts
        for hash, wallet_tx in self.wallet_database.get_wallet_txs().iteritems(
        ):
            debit = self.get_debit_tx(wallet_tx)
            for txout in wallet_tx.merkle_tx.tx.out_list:
                address = extract_txout_address(txout, self.runmode)
                name = ""
                #print self.get_names()
                #print encode_base58check(chr(ADDRESSVERSION[self.runmode]) + address)
                if address and address in self.get_names():
                    name = self.get_names()[address].name
                if debit > 0 and self.is_change(txout):
                    pass
                elif debit > 0:
                    yield (wallet_tx, hash, wallet_tx.time_received, address,
                           name, -txout.value)
                elif self.is_mine(txout):
                    yield (wallet_tx, hash, wallet_tx.time_received, address,
                           name, txout.value)

    def get_wallet_txs(self):
        return self.wallet_database.get_wallet_txs()

    def get_keypairs(self):
        return self.wallet_database.keypairs

    def get_poolkeys(self):
        return self.wallet_database.get_poolkeys()

    def get_names(self):
        return self.wallet_database.get_names()

    def have_key_for_addresss(self, address):
        return (address in self.addresses)

    def is_passphrase_required(self, txout):
        address = extract_txout_address(txout, self.runmode)
        _, is_crypted = self.addresses[address]
        return is_crypted

    def unlock(self, passphrases):
        for pphrase in passphrases:
            for mkey in self.get_master_keys().values():
                self.plain_masterkeys.append(decrypt_masterkey(mkey, pphrase))

    """ Return a private key for a txout as binary bignum. 
    
        Requires unlock() if this key in encrypted  """

    def get_txout_private_key_secret(self, txout):
        address = extract_txout_address(txout, self.runmode)
        public_key, is_crypted = self.addresses[address]
        return self.get_private_key_secret(public_key)

    def get_private_key_secret(self, public_key):
        if public_key in self.wallet_database.keys:  # private key is not crypted
            k = KEY()
            k.set_privkey(self.wallet_database.keys[public_key].private_key)
            return k.get_secret()
        crypted_secret = self.wallet_database.get_crypted_keys()[public_key]
        for key in self.plain_masterkeys:
            self.crypter.set_key(key, doublesha256(public_key))
            secret = self.crypter.decrypt(crypted_secret)
            k = KEY()
            is_compressed = len(public_key) == 33
            k.set_secret(secret, is_compressed)
            if k.get_pubkey() == public_key:
                return secret
        raise KeyDecryptException(
            "Can't decrypt private key, wallet not unlocked or incorrect masterkey"
        )

    def lock(self):
        self.plain_masterkeys = []

    def is_mine(self, txout):
        address = extract_txout_address(txout, self.runmode)
        if not address:  # if unknown script type, return False
            return False
        return self.have_key_for_addresss(address)

    """ Return the wallet's besthash as Uint256() or None if not supported """

    def get_besthash_reference(self):
        locator = self.wallet_database.get_block_locator()
        if locator:
            return self.wallet_database.get_block_locator().highest()

    def is_change(self, txout):
        # Fix to be implemented in main client, see wallet.cpp:390
        # current bad assumption is that any payment to a TX_PUBKEYHASH that
        # is mine but isn't in the address book is change.
        address = extract_txout_address(txout, self.runmode)
        return self.is_mine(txout) and (address not in self.get_names())

    def get_master_keys(self):
        return self.wallet_database.get_master_keys()
Example #10
0
class Wallet(Observable):
    '''
        Wallet implementes the basic satoshi wallet logic.
           Database logic is implemented in WalletDatabase
           Features requiring a blockchain are implemented in WalletAccount.
    '''
    EVT_NEW_TRANSACTION = Observable.createevent()
    
    def __init__(self, wallet_database, runmode):
        super(Wallet, self).__init__()
        self.wallet_database = wallet_database
        self.runmode = runmode
        self.addresses = {}
        self.crypter = Crypter()
        self.plain_masterkeys = []
    
    def open(self):
        self.wallet_database.open()
        self.load()
        
    def create(self, passphrase):
        self.wallet_database.begin_updates()
        crypter = Crypter()
        #first create masterkey
        master_key =  new_masterkey(passphrase)
        plain_masterkey = decrypt_masterkey(master_key, passphrase)
        self.wallet_database.add_master_key(master_key)
        #create transaction pool
        for i in range(100):
            k = KEY()
            k.generate(True)
            public_key = k.get_pubkey()
            crypter.set_key(plain_masterkey, doublesha256(public_key))
            crypted_secret = crypter.encrypt(k.get_secret())
            self.wallet_database.add_crypted_key(public_key, crypted_secret)
            pool_key = WalletPoolKey(i, 60000, time.time(), public_key)
            self.wallet_database.add_poolkey(pool_key)
            
            
        self.wallet_database.commit_updates()
        self.load()
        
    def load(self):
        for public_key, keypair in self.wallet_database.get_keys().iteritems():
            self.addresses[BitcoinAddress.from_publickey(public_key, self.runmode)] = (public_key, False)
        for public_key, secret in self.wallet_database.get_crypted_keys().iteritems():
            self.addresses[BitcoinAddress.from_publickey(public_key, self.runmode)] = (public_key, True)

    def begin_updates(self):
        self.wallet_database.begin_updates()
        
    def commit_updates(self):
        self.wallet_database.commit_updates()
             
    def get_receive_key(self):
        return self.wallet_database.get_receive_key()
        
    def allocate_key(self, public_key, label=None, ischange=False):
        address = BitcoinAddress.from_publickey(public_key, self.runmode) 
        return self.wallet_database.allocate_key(public_key, address, label)
    
    def add_transaction(self, hashtx, wallet_tx):
        self.wallet_database.set_transaction(hashtx, wallet_tx)

    def get_transaction(self, hashtx):
        return self.wallet_database.get_transaction(hashtx)

    def set_transaction(self, hashtx, wallet_tx):
        self.wallet_database.set_transaction(hashtx, wallet_tx)

    def del_transaction(self, hashtx):
        self.wallet_database.del_transaction(hashtx)

    """
        yields ( public_key, is_crypted, address, description ) entries.
    """
    def iterkeys(self):
        names = self.wallet_database.get_names()
        for address, (public_key, is_crypted) in self.addresses.iteritems():
            description = self.get_address_description(public_key)
            yield (public_key, is_crypted, address, description)
            
    def get_address_description(self, public_key):
        address = BitcoinAddress.from_publickey(public_key, self.runmode)
        description = ""
        if public_key in self.wallet_database.poolkeys_by_public_key:
            poolkey = self.wallet_database.poolkeys_by_public_key[public_key]
            description = "Pool (id:%d, time:%s)" % (poolkey.poolnum, time.strftime("%Y-%m-%d %H:%m:%S", time.gmtime(poolkey.time)))
        else:
            if address in self.wallet_database.get_names():
                description = "Receive (\"%s\")" % self.wallet_database.get_names()[address].name
            else: 
                description = "Change" 
        return description
        
    def iter_my_outputs(self):
        for hash, wallet_tx in self.wallet_database.get_wallet_txs().iteritems():
            for index, txout in enumerate(wallet_tx.merkle_tx.tx.out_list):
                if not wallet_tx.is_spent(index) and self.is_mine(txout):
                    yield (wallet_tx.merkle_tx.tx, Outpoint(hash, index), txout)
                    #yield ControlledOutput(hash, wallet_tx.merkle_tx.tx, index, txout, self.get_keypair_for_output(txout))
    ''''
        A TxIn is "debit" if the previous output is in the wallet and is mine.
        If it is, get_debit_txin will return the value spent.
        Debit transaction are used only for transaction history.
        The balance is computed using unspent transactions.
    '''
    def get_debit_txin(self, txin):
        if txin.previous_output.hash not in self.wallet_database.get_wallet_txs():
            return 0
        txprev = self.wallet_database.get_wallet_txs()[txin.previous_output.hash]
        txout = txprev.merkle_tx.tx.out_list[txin.previous_output.index]
        if not self.is_mine(txout):
            return 0
        return txout.value
        
    def get_debit_tx(self, wallet_tx):
        return sum(self.get_debit_txin(txin) for txin  in wallet_tx.merkle_tx.tx.in_list)

    def get_credit_txout(self, txout):
        if self.is_mine(txout):
            return txout.value
        return 0
        
    def get_credit_tx(self, wallet_tx):
        return sum(self.get_credit_txout(txout) for txout  in wallet_tx.merkle_tx.tx.out_list)
     
    def iter_transaction_history(self): # see wallet.cpp:448 GetAmounts
        for hash, wallet_tx in self.wallet_database.get_wallet_txs().iteritems():
            debit = self.get_debit_tx(wallet_tx)
            for txout in wallet_tx.merkle_tx.tx.out_list:
                address = extract_txout_address(txout, self.runmode)
                name = ""
                #print self.get_names()
                #print encode_base58check(chr(ADDRESSVERSION[self.runmode]) + address)
                if address and address in self.get_names():
                    name = self.get_names()[address].name
                if debit > 0 and self.is_change(txout):
                    pass
                elif debit > 0:
                    yield (wallet_tx, hash, wallet_tx.time_received, address, name, -txout.value)
                elif self.is_mine(txout):
                    yield (wallet_tx, hash, wallet_tx.time_received, address, name, txout.value)
          
    def get_wallet_txs(self):
        return self.wallet_database.get_wallet_txs()

    def get_keypairs(self):
        return self.wallet_database.keypairs
    
    def get_poolkeys(self):
        return self.wallet_database.get_poolkeys()
    
    def get_names(self):
        return self.wallet_database.get_names()
    
    def have_key_for_addresss(self, address):
        return (address in self.addresses)


    
    def is_passphrase_required(self, txout):
        address = extract_txout_address(txout, self.runmode)
        _, is_crypted = self.addresses[address]
        return is_crypted
    
    def unlock(self, passphrases):
        for pphrase in passphrases:
            for mkey in self.get_master_keys().values():
                self.plain_masterkeys.append(decrypt_masterkey(mkey, pphrase))
 
    """ Return a private key for a txout as binary bignum. 
    
        Requires unlock() if this key in encrypted  """

    def get_txout_private_key_secret(self, txout):
        address = extract_txout_address(txout, self.runmode)
        public_key, is_crypted = self.addresses[address]
        return self.get_private_key_secret(public_key)
    
    def get_private_key_secret(self, public_key):
        if public_key in self.wallet_database.keys: # private key is not crypted
            k = KEY()
            k.set_privkey(self.wallet_database.keys[public_key].private_key)
            return k.get_secret()
        crypted_secret = self.wallet_database.get_crypted_keys()[public_key]
        for key in self.plain_masterkeys:
            self.crypter.set_key(key, doublesha256(public_key))
            secret = self.crypter.decrypt(crypted_secret)
            k = KEY()
            is_compressed = len(public_key) == 33
            k.set_secret(secret, is_compressed)
            if k.get_pubkey() == public_key:
                return secret
        raise KeyDecryptException("Can't decrypt private key, wallet not unlocked or incorrect masterkey")
            
    def lock(self):
        self.plain_masterkeys = []
      

    def is_mine(self, txout):
        address = extract_txout_address(txout, self.runmode)
        if not address: # if unknown script type, return False
            return False
        return self.have_key_for_addresss(address)

    """ Return the wallet's besthash as Uint256() or None if not supported """
    def get_besthash_reference(self):
        locator = self.wallet_database.get_block_locator()
        if locator:
            return self.wallet_database.get_block_locator().highest()
    
    def is_change(self, txout): 
        # Fix to be implemented in main client, see wallet.cpp:390
        # current bad assumption is that any payment to a TX_PUBKEYHASH that
        # is mine but isn't in the address book is change. 
        address = extract_txout_address(txout, self.runmode)
        return self.is_mine(txout) and (address not in self.get_names())
  
    def get_master_keys(self):
        return self.wallet_database.get_master_keys()
Example #11
0
        "be4afa6923ad06790b0f8c3345131499cf2b149ca422bd11a7e67a76347c51a456a2d626f75da1ff809632fca7165d71"
    ),
                           salt=decodehexstr("8cdcbd8a494b0eeb"),
                           derivation_method=MasterKey.DERIVMETHOD_EVP_SHA512,
                           derive_iterations=45193,
                           other_derivation_parameters="")
    #Decrypt the master crypted_key using the passphrase
    plain_masterkey = decrypt_masterkey(master_key, "hello")
    #Decrypt a crypted_secret
    public_key = decodehexstr(
        "046a82d73af2cc093e3df7ae0185f045946970bcd5f0ef26f82d4f9a24e0d50f977c51e311e079e3183cfadd67d9b3f089fe7ba94a196c365fbd9e03b8c423787d"
    )
    crypted_secret = decodehexstr(
        "ff914ab69f58af92ac56de85051441e729cc51e11608d563e2a266ce3b8c59f573ed6a1828ff98fadb345890b6ed2626"
    )
    crypter2 = Crypter()
    crypter2.set_key(plain_masterkey, doublesha256(public_key))
    secret = crypter2.decrypt(crypted_secret)
    print hexstr(secret)
    #Test the secret
    k = KEY()
    k.set_secret(secret)
    sig = signature1 = k.sign("sign something")
    k2 = KEY()
    k2.set_pubkey(public_key)
    print k2.verify("sign something", sig)

    #Create a new masterkey
    m = new_masterkey("hello hello")
    print m
    print hexstr(decrypt_masterkey(m, "hello hello"))
Example #12
0
    from coinpy.tools.hex import decodehexstr
    from coinpy.tools.hex import hexstr
    from coinpy.model.wallet.masterkey import MasterKey
    from coinpy.tools.bitcoin.sha256 import doublesha256
    from coinpy.tools.crypto.ecdsa.ecdsa_ssl import KEY

    master_key = MasterKey(crypted_key=decodehexstr("be4afa6923ad06790b0f8c3345131499cf2b149ca422bd11a7e67a76347c51a456a2d626f75da1ff809632fca7165d71"), 
                           salt=decodehexstr("8cdcbd8a494b0eeb"),
                           derivation_method=MasterKey.DERIVMETHOD_EVP_SHA512, 
                           derive_iterations=45193, other_derivation_parameters="")
    #Decrypt the master crypted_key using the passphrase
    plain_masterkey = decrypt_masterkey(master_key, "hello")
    #Decrypt a crypted_secret
    public_key = decodehexstr("046a82d73af2cc093e3df7ae0185f045946970bcd5f0ef26f82d4f9a24e0d50f977c51e311e079e3183cfadd67d9b3f089fe7ba94a196c365fbd9e03b8c423787d")
    crypted_secret = decodehexstr("ff914ab69f58af92ac56de85051441e729cc51e11608d563e2a266ce3b8c59f573ed6a1828ff98fadb345890b6ed2626")
    crypter2 = Crypter()
    crypter2.set_key(plain_masterkey, doublesha256(public_key))
    secret = crypter2.decrypt(crypted_secret)
    print hexstr(secret)
    #Test the secret
    k = KEY()
    k.set_secret(secret)
    sig = signature1 = k.sign("sign something")
    k2 = KEY()
    k2.set_pubkey(public_key)
    print k2.verify("sign something", sig)
    
    #Create a new masterkey
    m =  new_masterkey("hello hello")
    print m
    print hexstr(decrypt_masterkey(m, "hello hello" ))