-
-
Notifications
You must be signed in to change notification settings - Fork 94
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stamps #295
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #295 +/- ##
==========================================
+ Coverage 57.04% 57.49% +0.45%
==========================================
Files 43 43
Lines 3997 4110 +113
==========================================
+ Hits 2280 2363 +83
- Misses 1717 1747 +30
☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bob does not need to know secret_msg to verify kY = C and provide a DLEQ proof verifiable by anyone. This is a conditional proof if secret_msg is not revealed to the third party they can not be sure that the signature is valid even if the DLEQ proof checks out.
While it is trivial to forge (Y, C) type 'signatures', the values are explicitly committed to in the DLEQ here, and thus can be considered valid, if Y = hash_to_curve(x) is satisfied.
def stamp_step1_bob(
Y: PublicKey, C: PublicKey, a: PrivateKey, p_bytes: bytes = b""
) -> Tuple[PrivateKey, PrivateKey]:
if p_bytes:
# deterministic p for testing
p = PrivateKey(privkey=p_bytes, raw=True)
else:
# normally, we generate a random p
p = PrivateKey()
assert p.pubkey
R1: PublicKey = p.pubkey # R1 = pG
R2: PublicKey = Y.mult(p) # type: ignore # R2 = pY
print(R1.serialize().hex(), R2.serialize().hex())
e = hash_e(R1, R2, Y, C)
s = p.tweak_add(a.tweak_mul(e)) # s = p + ea
spk = PrivateKey(s, raw=True)
epk = PrivateKey(e, raw=True)
return epk, spk
Correct! Adjusted appropriately and introduced a new object |
Problem
The BDHKE scheme used in Cashu does not allow users you to verify the mint's blind signature
C
without the knowledge of the mint's private keya
. This is bad since users don't know whether (1) the signatureC
is valid without asking the mint (it would be great to be able to do this because we can implement final offline payments in combination with P2PK) and (2) whether the mint is tagging tokens by using unique private keysa_{nonce}
for every individual token and can thus track all tokens.Solution 1
Chaum-Pedersen DLEQ proofs (implemented in #175) can be used by the minting user
Alice
of a token to ensure thatA = a*G
is indeed the key that signedC_
. To work, it requires the knowledge of the blinding factorr
which the minting wallet ofAlice
has access to.Alice
can also send this proof together withr
toCarol
who can verify the signature.Problem of solution 1
The problem with this approach is
Carol
could actually be the mintBob
and receiver
. However, ifBob
knowsr
, it can be used to break the unlinkability of the token to its previous output, which is bad. For situations where theAlice
knowsCarol
and that they don't collude with the mint, this approach is still ok.Solution 2
Another type of DLEQ proof called a stamp (implemented in this PR) can be used to make the mint commit that it has indeed signed
C
withA = a*G
. This requires an additional round trip after unblinding (since the mint can only ever receiveC
afterAlice
has unblinded it). It does not require the knowledge ofr
and can therefore be posted publicly and does not have to be kept secret from the mint.Problem of solution 2
The problem with this solution is timing and correlations: if
Alice
resubmitsC
immediately after she receivesC_
from the mint, the mint can correlate them (which breaks unlinkability). One approach to mitigate this is to delay the minting ofC_
to the stamping ofC
in time (and/or in token distribution, when sets of tokens are minted/stamped).My first approach in this PR is to allow stamping tokens in
Alice
's wallet upon execution of a commandcashu stamp
that requests stamps on all (or a subset) of tokens in the wallet. This can happen at a later time, say, days after the token has been minted. That way, a mint should not be able to link the minting operation to the stamping operation.Implementation
We introduce a new endpoint
POST /stamp
which takes the following input json data.Note:
ProofY
is the same as aProof
but instead of thesecret
it containsY = hash_to_curve(secret)
.The mint responds with DLEQ proofs
(e,s)
for each providedProof
Todos
Notes:
(x, C)
, but now proving mint's signature onC
by DLEQ proof of equality ofa
inC = aY
andA = aG
via a second DLEQ proof by @moonsettler