Pages:
Author

Topic: SIGHASH_WITHINPUTVALUE: Super-lightweight HW wallets and offline data - page 6. (Read 9898 times)

legendary
Activity: 1526
Merit: 1134
Yes, great idea. It will definitely simply devices like the Trezor which I think will be absolutely critical to Bitcoin's long term success.

Gavin has talked about maybe doing a "script 2.0" in future. If that were to happen, then we'd probably introduce new opcodes to split up CHECK(MULTI)SIG anyway, and at that point a new sighash flag wouldn't be required, it'd be implicit in the use of the new opcodes.

Let's discuss this a bit more at the conference, and let's see how next months hard fork goes.
hero member
Activity: 623
Merit: 500
CTO, Ledger
+1 * 2

H(Tx') is useful as well when obtaining a single user confirmation for the whole transaction signing process.

FYI, the way I deal with this issue today (specification update pending), to make things easier :

- A new "trusted input" type is added. A trusted input is : transaction hash + index (prevout) / amount / signature of the previous data (using a key known only by the device)
- The device can generate a trusted input from a transaction output, by parsing a transaction, at any time (so it can be done in a batch before actually using it)
- When creating a new transaction, prevout is replaced by the trusted input.

hero member
Activity: 555
Merit: 654
+1

Excelent idea. But if we are going to hardfork,  it´s time to rethink how the hash of the tx  is computes for signature verification. 
First, we should ban OP_CODESEPARATOR.

But I think the right way to do SIGHASH_WITHINPUTVALUE it is to put the amount outside the script, in another field, and stop embeding things in the input script.

Let
 
Tx' = Tx with all script inputs cleared

TxHash(Tx) = H ( H(Tx') | n | [ amount ] )

Where H() is a double SHA-256 hash. n is the input being verified and amount is the optionally amount.

The advantage of this scheme is that H(Tx) can be cached for the whole transaction, and the second application of H() is very fast. This prevents by design the vulnerability CVE-2013-2292 and it would allow to permit transactions over 100 Kbytes to be standard again.

legendary
Activity: 1232
Merit: 1094
What about using something like a 2 step transaction.

I create a transaction which pays to a new address for 0.1BTC and then signs a transaction which pays from that address to the actual target.

The intermediate address would be generated by the offline system and would be once off.

However, assuming it is accepted, your proposal is cleaner.

Another point is raises is that people should have hard fork ideas ready along with pull requests in the hopes of a mandatory hard fork Smiley.  Your idea also has the nice property of being relatively easy to implement quickly.
hero member
Activity: 668
Merit: 501
Why are We committed to a hard fork next month?
because of the BDB locking problem in 0.7. basically, we want to at least allow 1 MB blocks as intended.
full member
Activity: 308
Merit: 100
Why are We committed to a hard fork next month?
legendary
Activity: 1428
Merit: 1093
Core Armory Developer
I bring this up, because as long as we've committed ourself to a [potential] hardfork in the next month, I think the following should be seriously considered.  Why?  Because "cold storage" is becoming a major force in the Bitcoin world.  More and more people and companies are looking at the benefits and trying to get it setup.  More people are finding themselves wealthy and want to protect it.  It is the holy grail of wallet security (multi-sig, too, but that will probably include offline wallets, instead of replacing it).    But implementation suffers from one extraordinary hurdle.


Example:

Let's say I want to create a $10 offline signing device.  I will put 32 kB of RAM and a small screen and a tiny embedded chip that is just powerful enough for ECDSA signing.   It will sign transactions for me after asking me to physically confirm with a button press.  But the device has so little RAM, it can't support arbitrary transactions.  So, I'll just make sure my online computer software never produces transactions bigger than 10 kB, and just do multiple transactions if necessary.  In Armory, I'll happily make that a configurable parameter.

But there's a serious problem here:  this isn't possible (and the Trezor ran into this).  Because of a tiny little oversight by Satoshi, nothing about the 10kB transaction indicates what the transaction fee is.  Without access to the blockchain, my tiny little device doesn't know whether it's signing 1 BTC input, or 1000 BTC input.  To accommodate this, you must supply all supporting transactions along with the one to be signed (and BIP 10 does this).  By doing this, the offline device can hash the supporting transaction, verify it matches the TxIn it is signing, and then record the 8-byte amount/value from that transaction.   It's a lot of work to verify those 8 bytes...

Worse, I don't have control over this.  I can choose never to create transactions bigger than X kB, and pick X based on my HW.  But if my wallet contains a UTXO that comes from a 100 kB transaction, I have to upload 100 kB to my offline device, just to verify those 8 bytes.  This forces devices like the Trezor, to implement streaming calculations, complicating the protocol 10-fold.  

If you don't do this, an attacker compromising the online computer could trick your offline computer into signing away your entire wallet to transaction fee.  While it's not the most direct way for the attacker to make money, it's the most direct way to ruin you by sending your life savings to some lucky miner (and they may have a way to benefit from it, like owning some mining power).

EDIT: I shouldn't focus entirely on the signing hardware.  Another major problem is bandwidth:  there's a lot of good ways to transfer a few kB securely between an online and offline computer, but not on the order of megabytes.  QR codes are such a method that I keep shooting down, because I have no idea how to make it work with MB of data.


Raw Technical Solution:

All this because Satoshi made one little oversight in the OP_CHECKSIG procedure:  the TxOut script is copied into the input being signed, but not the value.  If the value was copied prepended to the TxOut script, then the offline system only needs to be given the 8 bytes, and it could securely present the correct fee to the user and sign it.  If an attacker compromises the online computer and puts incorrect values into there to trick the offline computer, the offline signature will be invalid (because full nodes verifying the transaction will use the correct value the signature won't match).  

So the technical solution is simple:  Add a new SIGHASH type, which I dub SIGHASH_WITHINPUTVALUE.  This would have hashcode 0x10.  This would be OR'd with the existing hash types.  i.e. Currently all "regular" transactions are signed with (SIGHASH_ALL), now anyone who wants the benefit would sign with (SIGHASH_ALL | SIGHASH_WITHINPUTVALUE).  It is compatible with the existing hash types.

Analogy:
Right Now:  "I, the offline computer, sign this input to be sent to this address, no matter how much this input is worth"
Proposal:  "I, the offline computer, have been told this input is worth 13.28 BTC.  This signature is only valid if that's how much it's actually worth"


Considerations:

This solution has some nice properties:
  • Simple!  For the signing and verification procedures, it's probably only a few lines of code.
  • I have full control over data sizes to be exchanged with the offline device, down to the minimum of being able to sign a one-input-one-output transaction.  Currently, there's no way to avoid having to deal with 100kB-200kB of transaction data transfer (and if you want to be able to sign multi-input tx, you need to be able to handle megabytes)
  • Also makes it resistent to changes at the network level: we plan to allow only 100 kB transactions right now.  So without this new SIGHASH, I design my device to handle up to 100kB.  But in two years, the limit is raised and people start mining 1 MB transactions, and I find that one of my inputs was from a 1 MB transaction.  Hardware upgrade?  Remember, the offline wallet needs to handle 100.0% of all transactions!  
  • No problems with backwards compatibility:  Once the change goes into effect, new devices can be made and wallet software updated, to only use the new SIGHASH type.  It can be used even on wallets that already contain coins... because it only changes what is being signed.
  • Should be completely non-controversial (technically):  this adds an optional restriction to transaction validity.  It doesn't change overall network topology or philosophy at all.  It's like asking the network to confirm, for the signer, that they were given the right value when signing.  That's all.

Downsides:
  • Hardfork (of course).  But we've committed ourselves to a hard-fork next month, anyway.  And the extra hashtype would simply be "present" next month, but not become usable for 6-12 months, to allow time for upgrades.  I think this change has the right combination of simplicity and benefit to be worth throwing in
  • Other clients would break if they're not paying attention and they are in the habit of verifying their own transactions.  Oblivious nodes would still be able to sign transactions, just not verify them.  Not so important for nodes that already trust the network to verify validity of transactions, but I'm sure things would break.

Anyone who has worked on offline wallets knows what a PITA it is to have to deal with supporting transactions.  Most of the ideas proposed in the Improving Offline Tx thread, were shot down because the solution needs to support multi-megabyte transfers.  This solution would eliminate that necessity.
Pages:
Jump to: