The goal of this protocol is for Bob to get Alice to perform a Diffie-Hellman key exchange blindly, such that when the unblinded value is returned, Alice recognizes it as her own, but can’t distinguish it from others (i.e. similar to a blind signature).
Alice:
A = a*G
return A
Bob:
Y = hash_to_curve(secret_message)
r = random blinding factor
B'= Y + r*G
return B'
Alice:
C' = a*B'
(= a*Y + a*r*G)
return C'
Bob:
C = C' - r*A
(= C' - a*r*G)
(= a*Y)
return C, secret_message
Alice:
Y = hash_to_curve(secret_message)
C == a*Y
If true, C must have originated from Alice
I unearthed this protocol from a seemingly long forgotten cypherpunk mailing list post by David Wagner from 1996 (edit: perhaps not as forgotten as I thought, as Lucre is an implementation of it). It was devised as an alternative to RSA blinding in order to get around the now-expired patent by David Chaum. As in all ecash protocols, the secret_message
is remembered by Alice
in order to prevent double spends.
One benefit of this scheme is that it's relatively straightforward to perform in a threshold setting (only requires curve multiplication). One downside is that validation is more involved than simply checking a signature, as this step requries repeating the Diffie-Hellman Key Exchange.
The protocol also has one additional weakness that can be addressed. Bob can't be certain that C'
was correctly generated and thus corresponds to a*B'
. Alice can resolve this by also supplying a discrete log equality proof (DLEQ), showing that a
in A = a*G
is equal to a
in C' = a*B'
. This equality can be proven with a relatively simple Schnorr signature, as described below.
(These steps occur once Alice returns C')
Alice:
r = random nonce
R1 = r*G
R2 = r*B'
e = hash(R1,R2,A,C')
s = r + e*a
return e, s
Bob:
R1 = s*G - e*A
R2 = s*B'- e*C'
e == hash(R1,R2,A,C')
If true, a in A = a*G must be equal to a in C' = a*B'
Thanks to Eric Sirion, Andrew Poelstra, and Adam Gibson for their helpful comments.
I read through the original Wagner post and this protocol and agree with everything (though I'm not entirely clear on the use-case here for blind DH key exchange), including your main observation about verifiability of C'.
On:
I think there's kind of two aspects to why this is "wrong": first, you should be careful to include in the description of the DLEQ protocol: the Verifier has an additional final step, which is given the response of form (s, R_1, R_2), to reconstruct the hash e =?= h(R_1, R_2, A, C').
And second, to mention: in PoDLE in JM I deliberately switched it around to have one less transmitted piece: response: (s, e) and Verifier must do: R_1 = s*G_1 - e*P_1, R_2 = s*G_2 - e*P_2; and then verify the hash is e. If your only goal is to reduce the transmitted data by c. 32 bytes, there you have it.
It's actually pretty interesting to figure out whether your proposal is actually sound though; my suspicion is that it isn't, but it's not trivial. Because the 'customer' (Bob) gives the new base point B' after the 'bank' (Alice) has already committed to A, it does at least mean the idea of simply returning the sum is not trivially wrong, but I would need to really carefully think about it to be sure either way. Intuitively, your verification equation is a schnorr sig verification so it should be a ZkPOK of a single key, not a DLEQ proof of two keys (needs two sigma protocols, not one!).