Author

Topic: unlinkable public deterministic wallet addresses (Read 2336 times)

legendary
Activity: 1120
Merit: 1160
December 23, 2013, 10:21:03 AM
#6
There is one additional advantage of sender derived addresses: the recipient has a global shared static address so it can act as a trust anchor to ward off diversion attacks in a simple and space efficient way without signatures.  It can act like an SSH TOFU (trust on first use) fingerprint.  Users can compare fingerprints, call up the company, expect the fingerprint advertised on all official emails, SSL static content web site, business cards, trust directories, PGP signed by key employees etc.  (Diversion attack meaning where someone hacks a server and replaces the addresses with their own).   Furthermore people can check that fingerprint in their offline wallet for investment level amounts.

The main reason I, and for that matter Amir Taaki, proposed "stealth addresses" in the first place was because I wanted to add them to OpenPGP keys - later other CA systems too - as an additional user ID so that wallet software could re-use that infrastructure to validate who you were trying to pay. I'd strongly suggest using that basic mechanism even if trust-on-first-use is used to validate rather than web-of-trust. One interesting thing about all this is it does suggest that the ability to encode a small amount of additional metadata that can only be seen by the recipient in the transaction would be useful, such as an account code, to disambiguate payments.

I also think this stuff ties into privacy models fairly tightly, so I want to do some formalization of that first. IE for SPV clients, what's your anonymity set of other transactions you are hidden in, and how do you make sure that set stays at the level you think it does?
sr. member
Activity: 404
Merit: 362
in bitcoin we trust
It seems to me you could make public derivation unlinkable eg by creating a random secret "chain code" and encrypting it for the recipient.  So c' = random, Qi = c'G+Q, E( Q, c' ).  Where E is public key encryption with Q public key, such as EC elgamal E(Q,c') = (A,B) where k=random, point C=[c',f(c')] where EC is defined by function f, A=C+kQ, B=kG.  Decryption is c'=[A-xB].x.  Now to receive transactions you need a full client and attempt to decrypt c" values and check if c"*Q=?Qi.

Apparently forum user bytecode proposed something related to this in the past.

Some update on this.  I had discussed on IRC the idea of using a 'bloom-bait' to make this a little more SPV friendly, eg by including the last byte of the public key, but it does erode the anonymity set though.

Alternatively one could make a separate pairing message with no inputs (other then anonymous unlinkable fee for anti-DoS) to send E.  In this way the pairing message sends E(Q,c') (actually deterministic c' for idempotency/crash recovery reasons).  And c' becomes the shared chaincode for a normal BIP 32 HD sub-wallet specific to sender-recipient pair and secret to them.  There is some risk of time correlation of pairing and first payment are made immediately, and some risk of failure due to non-communication of the pairing message, meaning the recipient does not know c'.  This part is not ideal, sending a single combined message is preferable but incurs trial-decryption and a full node, or a delegation to a full-node that learns the chain-code and does the trial decryption.  Probably one could delegate trial decryption to a full node, and the payload is a super-encrypted chain-code.

I am not sure if its analogous to bytecode's idea or not (didnt find the original), but retep also proposed on idea another variant of this same idea: to use static DH for the encoding instead of EC Elgamal (aka ECIES), which is basically centered on the artefact that the paired users dont care to choose a chaincode, a random, negotiated one would do.  For that eg the sender has a public key from an input say P=eG, and the recipient has public key Q=dG, then they use ECDH to arrive at shared code c'=H(eQ)=H(dP).  retep called this a stealth-address, so using BIP 32 it creates a sequence of HD addesses as Si=M(c',i), and the recipient compressed address is S'i=H(Si) so the recipient with a full node can scan for these.  Or delegate scanning to a full node.

Again an explicit bloom-bait tag could be used to reduce scanning at the cost of anonymity set.  To make it backwards compatible retep suggested to grind the address to give it a prefix with the added bonus that many tools already keep address prefix indexes.  (Address grinding might modify BIP32 to add a grinding counter: Si=M(c',i,ctr)).  That does imply some grinding cost which slows things down, but its somewhat backwards compatible and arguably indistinguishble to some extent.  Ground address prefixes, or explicit bloom-bait tags, may have adverse effects on CoinJoin as the tag/mark is visible and anonymity set reducing.

To my way of thinking therefore there are still gaps in the viability of this approach.  While it is quite attractive to have a safe way to have static base addresses with sender derived addresses or chain codes, it is not so far scalable to light nodes.  But if a way can be found to make this scale to light nodes without introducing an anonymity set problem it could be a big step forward as seemingly users on a recurring and on going basis dont understand and dont like single-use addresses on the receiving end.  Clearly single use addresses are problematic.

This approach above could work for recurring business things like exchanges, payment processors etc as those entities are typically running full nodes anyway.  You could say those entities anyway
have the infrastructure and communication pattern to support HD sub-wallet addresses.

There is one additional advantage of sender derived addresses: the recipient has a global shared static address so it can act as a trust anchor to ward off diversion attacks in a simple and space efficient way without signatures.  It can act like an SSH TOFU (trust on first use) fingerprint.  Users can compare fingerprints, call up the company, expect the fingerprint advertised on all official emails, SSL static content web site, business cards, trust directories, PGP signed by key employees etc.  (Diversion attack meaning where someone hacks a server and replaces the addresses with their own).   Furthermore people can check that fingerprint in their offline wallet for investment level amounts.

Adam

[edit: NB for this general scheme to work, the recipient needs to advertis an uncompressed address, ie the x-coord of Q, rather than H(Q).  That might even be compatible with older uncompressed BTC addresses, I am not sure]
sr. member
Activity: 404
Merit: 362
in bitcoin we trust
It seems to me you could make public derivation unlinkable eg by creating a random secret "chain code" and encrypting it for the recipient.
Public derivation is called public because it's performed with the public key values.  The chain code is never made public as part of the blockchain and would normally be made available only over an encrypted channel, if its even shared at all.

OK that makes better sense!  (I thought I must be missing something).

So with that clarification I wonder what the benefits if any are of public unlinkable derivation (public key and random encrypted chain code). 

- I think one thing is it could provide an infinite look-ahead - ie you dont need to look for keys of iteration i for some number of steps ahead, you could probably search all of them for the parent hierarchical base key, ie just decrypt E( Q, c' ) to find c' and verify to see if its one of yours vs random garbage.

- Another property is the sender after the fact doesnt know who he sent to if he doesnt log random c' values. 

- Also there's no stored chain code on the sender to be compromised (he can start from scratch fetching the base address from the shop site online and delete it with cookies, web logs etc at end of session)

Adam

ps It wasnt obvious reading BIP 32 and even looking now I dont see mention of the security requirements for handling chain codes.  If thats not frozen it might make sense to put a note saying that somewhere.  I could even take a stab at the edit - looks like its an editable page.
staff
Activity: 4284
Merit: 8808
It seems to me you could make public derivation unlinkable eg by creating a random secret "chain code" and encrypting it for the recipient.
Public derivation is called public because it's performed with the public key values.  The chain code is never made public as part of the blockchain and would normally be made available only over an encrypted channel, if its even shared at all.
sr. member
Activity: 404
Merit: 362
in bitcoin we trust
So in BIP 32 private key is x, base public key Q=xG, then public derivation is Qi = m*G+Q where m = MAC(c,Q,i) and c is the public "chain code"
[...]
you could make public derivation unlinkable eg by creating a random secret "chain code" and encrypting it for the recipient.  So c' = random, Qi = c'G+Q, E( Q, c' ).  Where E is public key encryption with Q public key, such as EC elgamal E(Q,c') = (A,B) where k=random, point C=[c',f(c')] where EC is defined by function f, A=C+kQ, B=kG.  Decryption is c'=[A-xB].x.

except you probably want c' to be random but derived as in BIP 32 like c"=random, ci=MAC(c",Q,i) to avoid maliciously chosen ci values as the recipient is eventually going to sign a tx using x+ci as a private key; seemingly ECDSA is relatively immune to that (from looking at the question briefly) but in the general case for other signature schemes that is a potential opening.

Adam
sr. member
Activity: 404
Merit: 362
in bitcoin we trust
So in BIP 32 https://en.bitcoin.it/wiki/BIP_0032 (simplifying) the base private key is x, base public key Q=xG, then public derivation (BIP calls this function CKD) is Qi = m*G+Q where m = MAC(c,Q,i) and c is the public "chain code" (they use MAC HMAC-SHA512).  The recipient can derive key x_i corresponding to Qi as x_i = m+x mod n (because m*G+x*G = (m+x)*G).

Now this is good for security but not so good for privacy as any public derived address is linkable as an analyst can just repeat the derivation function and check which key Q it is for.  In theory part of the reason to even use multiple receiving keys at all is to reduce linkability (unless there is an account benefit - one for each sender?)

(With private derivation (also specified in BIP 32) conversely here x_i = m'+x where m'=MAC(C,x,i), and Qi=x_i*G so there is no linking but that can only be computed knowing the private key x, so it is not publicly computable, and does not interoperate ie for using public derivation both sender and recipient have to use the public derivation method; and for private derivation the recipient has to generate and send the address to the sender, you cant mix public & private derivation as they are incompatible).

It seems to me you could make public derivation unlinkable eg by creating a random secret "chain code" and encrypting it for the recipient.  So c' = random, Qi = c'G+Q, E( Q, c' ).  Where E is public key encryption with Q public key, such as EC elgamal E(Q,c') = (A,B) where k=random, point C=[c',f(c')] where EC is defined by function f, A=C+kQ, B=kG.  Decryption is c'=[A-xB].x.  Now to receive transactions you need a full client and attempt to decrypt c" values and check if c"*Q=?Qi.

With out of band coordination the sender and recipient could reduce the amount of full decryption the recipient needs to do.  (Eg he can replace public key encryption function E by AES and a shared key)

Adam
Jump to: