Developing Key Box, a tiny wallet, a signer and a broadcaster : Journal Entry for 2018 03(March) 15

in #steemdev6 years ago

March 15th, 2018

In this developer's journal of Keybox:

  • Separation of Keys
  • Making a multisignature transaction

Separation of Keys

There are three peices of software to make this happen. I think that programs that need the master passwords should be tiny, those that need the active key can be medium size and those that need the posting key can be complex. Because these are the keys in order of importance and power. Certainly, moving people's money or changing the account is more important than voting or posting. It turns out you can also spend funds with the master password (owner key).

So, keybox needs the owner key and it will not be used for transactions. It is 200 lines of python code and it will have to be made larger in order to make it a GUI but I can keep two versions. One that is a GUI and one that is a really simple CLI.

Making a multisignature transaction

Now, if we want Two-Factor Authentication. It is necessary to have a multi-signature transactions. The keys should be on different devices. One signer is the end-user's software, the other signer could be on a server which asks for a 6 digit code from the user to confirm a transaction.

Note: This is all on the testnet.

Using keybox, which I have already provided source code for, you can setup an account for multisignature. The problem is, this just does not work at the moment. I keep getting incomplete authority error messages from the RPC servers and I do not know why.

---------------------------
owner
Threshold: 1
        key: STX5kJnwhzphuAdpQLLSgcu5rvA6smznNmQEydSTSTURvHfXhVnbo, weight: 1
---------------------------
active
Threshold: 9
        key: STX87vxdvcxVNAVyhLVKcRzvX6f9y1XnWJV2a8NwbUtcdndzQCtKa, weight: 8
        account:steemfiles weight: 1
---------------------------
posting
Threshold: 1
        key: STX5LhRERMbjJviw3hxaLuMSEgpgn7uYDTWBvDEyJNfXdQcFLF6qX, weight: 1
---------------------------
memo
Threshold: 1
        key: STX6SZXWqS3z1jS4wfeFHehauC5hSsrfWmyTeSwyCoLpa83h2Txdc, weight: 1

In this configuration, steemfiles is a co-signer which can sign the message for elf. The account elf would send money using his active key which may get compromised. If an evil user who works at SteemConnect tries to use the active key, it would not work because it only has a weight of 8 and the threshold is 9. Steemfiles cannot steal the money either because it only has a weight of 1. Together they add up to 9. So, when the transaction is made with the active key of elf, a service that has steemfiles' active key can show the user what transaction is being proposed and the user can approve or disapprove it with some kind of authentication method. Such as with one-time numeric codes.

I wrote a tiny wallet. You can see I sent 10 SBD. If I log in with the master password of elf, condenser apparently uses the owner key to sign my transfers of money to leprechaun. So even with the active key not being enough money can still be spent if the master password is used somewhere. I need to perfect this system before impeding the owner key as well.

Here is an excerpt of the software. Now, it signs it with the single key, and then tries to verify it. Because I use the elf account here, verify_authority() throws an exception and it prints out the transaction as a json string.

                from beem.transactionbuilder import TransactionBuilder
                from beembase.operations import Transfer, Custom_json
                tx = TransactionBuilder(steem_instance=steem)
                tx.appendOps(Transfer(**{
                         "from": user,
                         "to":  recipient,
                         "amount": str(quantity) + " " + currency,
                         "memo": memo
                     }))
                tx.appendWif(str(private_active_key))
                tx.sign()
                try:
                    tx.verify_authority()                    
                except:
                    print(tx.json())
                    # Here we send a tx to steemfiles.com for steemfiles to sign
                else:
                    tx.broadcast()


The json string is:

{'expiration': '2018-03-15T15:50:38', 'ref_block_num': 13727, 'ref_block_prefix': 3435158254, 'operations': [['transfer', {'from': 'elf', 'to': 'leprechaun', 'amount': '10.000 SBD', 'memo': 'multi-factor send'}]], 'extensions': [], 'signatures': ['1f7d9e6056aa6d5e1a35f4753ae4f4c0f6c5b6f71138b505e7f357babb18df71691725b656f86715af6c29614306f24ffd7b61aa4f50767a7d02d5dc37e0bc95e8']}

For the other signature, I try to sign it like this:

old_signatures = tx_json['signatures']
tx_json['signatures'] = []
tx = TransactionBuilder(tx=tx_json, steem_instance=steem)
tx.appendWif(str(private_active_key))
tx.sign()
tx_json = tx.json()
tx_json['signatures'].extend(old_signatures)
print(tx_json)

That leaves me with:

{'expiration': '2018-03-15T15:52:59', 'ref_block_num': 13774, 'ref_block_prefix': 1848545560, 'operations': [['transfer', {'from': 'elf', 'to': 'leprechaun', 'amount': '10.000 SBD', 'memo': 'multi-factor send'}]], 'extensions': [], 'signatures': ['1f058ee42ec67da75fe773c8a4f5ea9b4b54a67d5eb3659e8cc878c596aa7aa18158793db8d8f3d2b12ce5bda80c2e95399ec9961bbf0f47c177c8702562129874', '1f7d9e6056aa6d5e1a35f4753ae4f4c0f6c5b6f71138b505e7f357babb18df71691725b656f86715af6c29614306f24ffd7b61aa4f50767a7d02d5dc37e0bc95e8']}

Looks good! But when it gets broadcasted I get an error from the RPC server of @almot-digital.

This is how I read the json strings into standard input:

transaction_txt = sys.stdin.read()

transaction_txt = '"'.join(transaction_txt.split('\''))
tx_json = json.loads(transaction_txt)

from beem.transactionbuilder import TransactionBuilder
tx = TransactionBuilder(tx=tx_json, steem_instance=steem)
tx.broadcast()

This is how it fails:

Enter the transaction text now                                                                                                                                                      
Traceback (most recent call last):                                                                                                                                                  
  File "/home/alumno/.local/lib/python3.6/site-packages/beem-0.19.16-py3.6.egg/beemapi/steemnoderpc.py", line 71, in rpcexec                                                        
  File "/home/alumno/.local/lib/python3.6/site-packages/beem-0.19.16-py3.6.egg/beemgrapheneapi/graphenerpc.py", line 242, in rpcexec                                                
beemgrapheneapi.rpcutils.RPCError: 3010000 tx_missing_active_auth: missing required active authority                                                                                
Missing Active Authority elf                                                                                                                                                        
    {"id":"elf","auth":{"weight_threshold":9,"account_auths":[["steemfiles",1]],"key_auths":[["STX87vxdvcxVNAVyhLVKcRzvX6f9y1XnWJV2a8NwbUtcdndzQCtKa",8]]},"owner":{"weight_threshold":1,"account_auths":[],"key_auths":[["STX5kJnwhzphuAdpQLLSgcu5rvA6smznNmQEydSTSTURvHfXhVnbo",1]]}}                                                                                 
    th_a  transaction.cpp:157 verify_authority                                                                                                                                      

The error is signaled by the server so it is not beem failing a good transaction. There is something wrong with the transaction. What is it? Maybe someone who implements libraries or wallet writers can help me out, like @jesta, @holger80. I have an active key signature from both steem and from elf. Now the weights are 1+8. That's teh threshold of 9. What is wrong with the transaction?

Previous Journal Entries:

Dash XjzjT4mr4f7T3E8G9jQQzozTgA2J1ehMkV
LTC LLXj1ZPQPaBA1LFtoU1Gkvu5ZrxYzeLGKt
BitcoinCash 1KVqnW7wZwn2cWbrXmSxsrzqYVC5Wj836u
Bitcoin 1Q1WX5gVPKxJKoQXF6pNNZmstWLR87ityw (too expensive to use for tips)

See also


Sort:  

Maybe, the problem is the testnet-server?
The implementation of the allow-function from beem is almost identical to python-steem. I checked. Other operations as transfer are excepted on the testnet-server, I can see the transaction then on the blockchain. But, the transfer-operation has no effect on the account. The amount of SBD keeps the same. So the testnet server works different than a normal node.

I have never noticed that. I guess it could be. It's unfortunate there is only one out there.

By the way, I have not tried python steem for this. I am hoping python steem will be ready in the next hf

I found some small bugs and fixed them. Maybe it works now? Can you try 0.19.17?
https://utopian.io/utopian-io/@holger80/update-for-beem-sign-and-verify-operation-are-200-faster-now

Unless you can identify why this transaction failed, you will not be closer to solving the problem: {'expiration': '2018-03-15T15:52:59', 'ref_block_num': 13774, 'ref_block_prefix': 1848545560, 'operations': [['transfer', {'from': 'elf', 'to': 'leprechaun', 'amount': '10.000 SBD', 'memo': 'multi-factor send'}]], 'extensions': [], 'signatures': ['1f058ee42ec67da75fe773c8a4f5ea9b4b54a67d5eb3659e8cc878c596aa7aa18158793db8d8f3d2b12ce5bda80c2e95399ec9961bbf0f47c177c8702562129874', '1f7d9e6056aa6d5e1a35f4753ae4f4c0f6c5b6f71138b505e7f357babb18df71691725b656f86715af6c29614306f24ffd7b61aa4f50767a7d02d5dc37e0bc95e8']}

It says "Missing Active Authority elf". Now, elf has 8/9 weight/threshold and steemfiles has 1/9 weight threshold in active. I think that means that these two signatures from steemfiles' active key and elf's active key should be enough. It seems I have this principle wrong somehow.

By the way, with the latest tag release for beem there is no change.

Coin Marketplace

STEEM 0.17
TRX 0.13
JST 0.027
BTC 61129.70
ETH 2660.38
USDT 1.00
SBD 2.55