Here is my attempt at modifying the protocol to fix the unsolicited sending problem. I am not sure if this change doesn't break the security (
Yes it does! See Edit2) or privacy guarantees of the original protocol. I highly appreciate review of this modified protocol.
There are three parties involved: Alice, Bob, and Carol. Bob is designated as Alice's blinded signer publicly in her account metadata. Carol wants to send funds to Alice without needing any private data from Alice. Carol knows she is sending the funds to Alice, so there is no point in blinding Alice's withdraw signature from Carol. The protocol however needs to guarantee that Carol does not have enough information to get Bob to sign a digest that allows Carol to reclaim the sent funds. Bob only needs to verify that a particular user requesting him to generate a blinded signature is a customer (and verify their identity through whatever means is appropriate to provide the multisig protection) before signing with the appropriate keys meant only for that customer. No one other than Alice or Carol (this includes Bob) should be able to associate the sent balance to Alice at any time in this process including after Alice withdraws the balance using the unblinded signature.
Alice's extended public key is K
a (and corresponding private key is k
a). Bob's extended public key is K
b (and corresponding private key is k
b which is specific to Alice.
Carol generates a one-time private key o (corresponding public key is O). She generates shared secret s from the x-coordinate of o * K
a (which can also be derived by Alice using O * k
a). The modified shared secret s' = H (s || "modified"). The index i = H(s' || "index1"), a second index j = H(s' || "index2"), and the values v
1 = H(s' || "value1") and v
2 = H(s' || "value2"). Comparing to the paper, v
1 == a
-1c
-1 and v
2 == d. Carol also uses index i to derive the child public keys P (represents the same P as the one in the paper) and Q', where P = ND(K
b, 2*i + 0) and Q' = ND(K
b, 2*i + 1). She also uses index j to derive the child public key B' = ND(K
a, j). Comparing to the paper, Q' = a
-1Q and B' = a
-1bG.
Carol then calculates kG = v
1P (from the paper, kG == a
-1c
-1P), and r which is defined to be the x-coordinate of kG. From the paper, T (the public key in the withdraw condition) is given by T = r
-1(a
-1bG + a
-1Q + a
-1c
-1dP). We can rewrite this as T = r
-1(B' + Q' + v
1v
2P), which Carol is able to compute.
When Alice receives the funds she can verify that Carol followed the correct procedure. She is able to generate all the same values (including r) starting from the shared secret s. When Alice finally wants to withdraw the funds in another transaction she is going to need the values for a, b, c, and d. Through the index j she is able to calculate the private key for B', which is equivalent to a
-1b from the paper (call that value v
3). By selecting a random value for a, Alice can then calculate the remaining values: b = av
3, c = a
-1(v
1)
-1, and d = v
2. This then allows Alice to generate the blinded digest of digest h: h
2 = ah + b. However, Alice cannot only send h
2 and i to Bob, she must also send a to Bob. As far as I am able to tell, this should not reveal any new information to Bob (would really appreciate a check on this). Also with knowledge of a, even if Bob is colluding with Carol, they cannot withdraw the funds because they are unable to derive b (
Not true! See Edit2). However, if Bob and Carol are colluding, Carol can share j with Bob which along with a and h
2 allows Bob to associate h
2 (and thus Alice's identity) to the digest h (and thus to the balance that Carol sent Alice). But if Bob and Carol are colluding anyway, Carol could just simply tell Bob this information as she was the one who sent the funds to Alice in the first place.
Bob now takes h
2, i and a provided by Alice and computes p
-1 (where P == p
-1G) and q' (where Q' == q'G == a
-1Q == a
-1qp
-1G). Then he computers q = apq'. Finally, Bob computes s
1 = ph
2 + q, sends s
1 back to Alice.
Alice can then use s
1 to compute s
2 = cs
1 + d. The unblinded signature on digest h is then (r, s
2) which is signed using a key corresponding to public key T. This signature allows Alice to withdraw her funds.
Edit: Require Bob's extended public key to be a hardened child specific to Alice or else Alice could determine Bob's master private key by getting him to blinded sign the same hash but with different indices. Even if the private keys for P and Q' were uncorrelated, the master private key could have still been computed by getting him to blind sign the same hash four times but with different indices. This also removes the requirement for Bob to track indices for which he has signed before.
Edit2:
Major flaw found with the above. If Bob and Carol are colluding, they can determine k
a after Alice signs the transaction that withdraw funds sent by Carol. s
2 = c*p*a*h + c*p*a*(k
a + j) + c*p*a*q' + d. Carol knows a*c, d, and j. Bob knows p and q'. Together they know y
1 and y
2 where s
2 = y
1*(h + k
a) + y
2. After Alice publishes the transaction to the network to withdraw the funds, she also necessarily publishes h and s
2, and so at that point Bob and Carol can simply solve for Alice's private key k
a.
Back to the drawing board I guess.