Stealth Payments - Sample Code / Proof of Concept

Stealth Payments - Sample Code / Proof of Concept
2014-01-13 11:18 ` Mike Hearn
  
From: Jeremy Spilman @ 2014-01-13  9:18 UTC (permalink / raw)
  To: bitcoin-development

* Transaction *

I spent 1BTC on TestNet to a stealth address...
    TxID: df092896c1347b303da299bc84c92bef1946f455dbdc80ffdb01a18ea4ed8b4c

http://blockexplorer.com/testnet/tx/df092896c1347b303da299bc84c92bef1946f455dbdc80ffdb01a18ea4ed8b4c#i8166574

* Code *

Code which generated this transaction is here:  
https://gist.github.com/jspilman/8396495

Note, one minor change from the protocol we discussed is I'm just using  
the 32-byte x coordinate for the shared secret, not the compressed pubKey  
(so, throwing away the first byte) before hashing with SHA256.

* How it Looks *

After importing the privkey for the TxIn to that transaction  
(importprivkey "cNL8XqRtqwC1YEc9kKspbX2aukWnXfgHQSvjsPYbuPif5Q3DJkEs"  
rescan) you will see two rows in the Transaction List of Bitcoin-QT...

Both rows simply say 'Sent to' with a blank address. One has 1BTC amount  
which is the 2-of-2 stealth multisig, the other has 0BTC amount, and it's  
the OP_RETURN.

I wonder if the 0BTC OP_RETURN transactions should be hidden from the  
Transaction List? 'Transaction Details' truncates the <data> after  
OP_RETURN anyway, so it's not even particularly useful for seeing what  
data you embedded.

* Next Steps *

I'm not quite sure. If we're going to try to deploy this, I think we need  
to fully understand what users who are making these payments should see in  
their wallet software while making a payment, and after a payment has been  
made.

Right now I'm thinking...

   1) Define the PaymentRequest extension
   2) Update Gavin's PHP to generate PaymentRequests for stealth payments
   3) Get Bitcoin-QT loading the PaymentRequest and generating transactions  
 from those PaymentRequests
   4) Write an agent to detect incoming stealth payments

But we would still be showing meaningless rows in the payer's Transaction  
List without some additional work.

If there is a place to add TxOut meta-data with the pubkeys used to  
generate it... well, there must be since the 'Merchant' field is attached  
somehow. So we could probably use the same method to keep the pubKeys  
around.

Maybe the simple way to punt on this is to just show 'Merchant' in the  
address column if it is available and an address is not. We could skip  
saving the pubKeys for now, so there would be no way to send follow on  
stealth payments, but at least the Transaction List would make sense  
instead of looking like two empty transactions.

* Other Open Questions *

I think the biggest is if/how to receive P2P stealth payments in  
Bitcoin-QT as an end-user not a merchant.

I can probably make the necessary changes to IsMine, but I don't know  
where we should keep 'd2'/'Q2' unencrypted so it's available for doing the  
necessary tests, but has no chance of ever be used as a stand-alone  
private key?

And then there's still the question of: when 'd1'/Q1 is available  
decrypted, we must fully verify the transaction, and how to indicate if  
that has or has not been done yet.

It really seems crippled to me without fully integrated support for  
receiving P2P stealth payments in Bitcoin-QT. It doesn't seem like that  
much code, just some details to work out first.




 permalink raw reply	[|nested]
2014-01-13  9:18 [Bitcoin-development] Stealth Payments - Sample Code / Proof of Concept Jeremy Spilman

  2014-01-13 14:10   ` Jeremy Spilman
  
From: Mike Hearn @ 2014-01-13 11:18 UTC (permalink / raw)
  To: Jeremy Spilman;  bitcoin-development

[-- Attachment #1: Type: text/plain, Size: 1559 bytes --]

Cool!

On Mon, Jan 13, 2014 at 10:18 AM, Jeremy Spilman <jeremy@taplink•co> wrote:

> I spent 1BTC on TestNet to a stealth address...
>     TxID: df092896c1347b303da299bc84c92bef1946f455dbdc80ffdb01a18ea4ed8b4c
>

... but can you redeem it?


> Code which generated this transaction is here:
> https://gist.github.com/jspilman/8396495


That's rather interesting code. Is this using a private C# bitcoin
implementation?


> I wonder if the 0BTC OP_RETURN transactions should be hidden from the
> Transaction List?
>

Yes, of course. The transaction list should just say something like

    "Payment received from Jeremy,  0.1 BTC"

Maybe the simple way to punt on this is to just show 'Merchant' in the
> address column if it is available and an address is not.


I am surprised it's not already the case! Though "merchant" is perhaps a
bit biased as a name, internally it perhaps should just be called
"Recipient". There's no requirement for you to be a merchant to create
payment protocol requests.


> I can probably make the necessary changes to IsMine, but I don't know
> where we should keep 'd2'/'Q2' unencrypted so it's available for doing the
> necessary tests, but has no chance of ever be used as a stand-alone
> private key?
>

The wallet format would need extending.

I'd feel a lot more comfortable if the protocol was reviewed by a
professional cryptographer though. I think think Gregory already brought up
an issue to do with people able to detect such payments by testing if
decrypted values are points on the curve, or something like that.

[-- Attachment #2: Type: text/html, Size: 2711 bytes --]

 permalink raw reply	[|nested]
2014-01-13 11:18 ` Mike Hearn

  
From: Jeremy Spilman @ 2014-01-13 14:10 UTC ( / )
  To: Mike Hearn;  bitcoin-development



On Mon, 13 Jan 2014 03:18:28 -0800, Mike Hearn <mike@plan99•net> wrote:

> Cool!
>
> On Mon, Jan 13, 2014 at 10:18 AM, Jeremy Spilman <jeremy@taplink•co>  
> wrote:
>> I spent 1BTC on TestNet to a stealth address...
>>    TxID:  
>> df092896c1347b303da299bc84c92bef1946f455dbdc80ffdb01a18ea4ed8b4c
>
> ... but can you redeem it?

But of course!

Every time the test runs it makes a new ephemeral key, so I wrote a  
separate test with hard-coded values from the block chain (as it would be  
in real-life) to create a redeeming Tx. I've added the RedeemStealth code  
to the Gist.

It sent successfully using sendrawtransaction, TxID:  
ed92364d2b6f6528dea32dbf6c4d5d6291b601aff1ddb4eeb124d003c7c7ff07

I'm self mining since no one else seems to be on TestNet this time of  
night... going to catch some sleep, hopefully by the time I wake up it'll  
be on the chain.


>> Code which generated this transaction is here:
>> https://gist.github.com/jspilman/8396495
>
> That's rather interesting code. Is this using a private C# bitcoin  
> implementation?

Indeed it is. One day I may publish the libraries, but they aren't doing  
anything particularly special under the hood, just the standard  
Bitcoin/EC/BIP32 stuff and using OpenSSL under the hood instead of the  
more typical BouncyCastle.

I just tried to keep things extremely concise in the APIs. Hopefully all  
the function calls are obvious what they are doing. Since there's no  
actual wallet behind it, the code to setup the inputs is a bit annoying,  
but actually building and signing transactions is super clean.


>> I wonder if the 0BTC OP_RETURN transactions should be hidden from the
>> Transaction List?
>
> Yes, of course. The transaction list should just say something like
>
>    "Payment received from Jeremy,  0.1 BTC"

In this case I'm just looking at the payee wallet, but yes, "Payment set  
to Jeremy" should be possible, with the name coming from the CN.

>
>> Maybe the simple way to punt on this is to just show 'Merchant' in the
>> address column if it is available and an address is not.
>
> I am surprised it's not already the case! Though "merchant" is perhaps a  
> bit biased as a name, internally it perhaps should just be called  
> "Recipient". >There's no requirement for you to be a merchant to create  
> payment protocol requests.

Yeah, right now for PaymentProtocol fulfilled payments, on the payer's  
Transaction List, it shows the address in the 'Address' column, but if you  
right-click and look at 'Transaction details' you will see something like:


    Status: 42 confirmations
    Date: 1/12/2014 21:07
    To: mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV
    Debit: -0.10 BTC
    Net amount: -0.10 BTC
    Transaction ID:  
93c50347e35062a3501fcea15d1a22ace8d1b059affb9913fc9e7df4e7d6a00b-000
    Merchant: www.bitcoincore.org



I agree 'Merchant' might not be the best name, especially since when  
you're making the payment the field is labeled simply 'Pay To'.



But I think we agree, why show 'mrhz5ZgSF3C1BSdyCKt3gEdhKoRL5BNfJV' in the  
transaction list instead of just "Paid To: www.bitcoincore.org" and then  
perhaps the Memo field could be stuck under 'Transaction details', instead  
of losing that important bit of info.

>
>> I can probably make the necessary changes to IsMine, but I don't know
>> where we should keep 'd2'/'Q2' unencrypted so it's available for doing  
>> the
>> necessary tests, but has no chance of ever be used as a stand-alone
>> private key?
>
> The wallet format would need extending.
>
> I'd feel a lot more comfortable if the protocol was reviewed by a  
> professional cryptographer though. I think think Gregory already brought  
> up an issue >to do with people able to detect such payments by testing  
> if decrypted values are points on the curve, or something like that.

Not sure I follow that, will look forward to hearing more about it.

The only risk I know of is that there are checks in theory that you would  
do on Q1/Q2, but since the payee is the one generating Q1/Q2 they would  
literally be attacking themselves. I referenced two papers in a prior  
email specifically on reusing ephemeral keys in ECDH, and the validation  
you need to do on Q1/Q2 when re-using an ephemeral key to send two  
messages to two different pubKeys. I think the idea of checking the  
pubKeys when re-using ephemeral keys is more when the pubKeys are under  
the attackers control. But the validation is not complicated, and I'll see  
if I can add it tomorrow.

It would be good to fully understand how a possible small-group attack  
would work...  This is a bit of guess-work on my part:

    If a payee managed to foot-shoot themselves with a bad Q2 pubKey, then  
gives out d2/Q2 to a scanning service run by Mallory...

    Mallory has d2/Q2, given P from a transaction, he calculates S2 (as  
usual):

       byte[] S2 = EC.DH(d2, P);

    But with the small sub-group attack with Q2 he can learn 'e' (the  
ephemeral private key) used:

       byte[] S2 = EC.DH(e, Q2);

    and from that he can calculate S1 directly, when he should only know S2.

       byte[] S1 = EC.DH(e, Q1);

So does that mean Mallory can find 'd1'? It looks like you would need  
another small sub-group attack on P, the ephemeral public key, so another  
key the attacker doesn't control which would have to randomly be bad.

       byte[] S1 = EC.DH(d1, P);

But I'm definitely not a professional cryptographer. Perhaps Matthew Green  
might be a good candidate to review this?

AND YAY, my stealth redemption Tx just went through, goodnight :-)  
http://blockexplorer.com/testnet/tx/df092896c1347b303da299bc84c92bef1946f455dbdc80ffdb01a18ea4ed8b4c#o0