optional
In this document, we present an extension of Cashu's crypto system to allow a user Alice
to verify the mint Bob
's signature using only Bob
's public keys. We explain how another user Carol
who receives ecash from Alice
can execute the DLEQ proof as well. This is achieved using a Discrete Log Equality (DLEQ) proof. Previously, Bob
's signature could only be checked by himself using his own private keys (NUT-00).
The purpose of this DLEQ is to prove that the mint has used the same private key a
for creating its public key A
(NUT-01) and for signing the BlindedMessage B'
. Bob
returns the DLEQ proof additional to the blind signature C'
for a mint or swap operation.
The complete DLEQ proof reads
# DLEQ Proof
(These steps occur when Bob returns C')
Bob:
r = random nonce
R1 = r*G
R2 = r*B'
e = hash(R1,R2,A,C')
s = r + e*a
return e, s
Alice:
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'
The hash(x) function generates a deterministic Sha256 hash for a given input list of PublicKey
. The uncompressed hexadecimal representations of each PublicKey
is concatenated before taking the Sha256 hash.
def hash_e(*publickeys: PublicKey) -> bytes:
e_ = ""
for p in publickeys:
_p = p.serialize(compressed=False).hex()
e_ += str(_p)
e = hashlib.sha256(e_.encode("utf-8")).digest()
return e
The mint produces these DLEQ proofs when returning BlindSignature
's in the responses for minting (NUT-04) and swapping (NUT-03) tokens. The BlindSignature
object is extended in the following way to include the DLEQ proof:
{
"id": <str>,
"amount": <int>,
"C_": <str>,
"dleq": { <-- New: DLEQ proof
"e": <str>,
"s": <str>
}
}
e
and s
are the DLEQ proof.
In order for Alice
to communicate the DLEQ to another user Carol
, we extend the Proof
(see NUT-00) object and include the DLEQ proof. As explained below, we also need to include the blinding factor r
for the proof to be convincing to another user Carol
.
{
"id": <str>,
"amount": <int>,
"secret": <str>,
"C": <str>,
"dleq": { <-- New: DLEQ proof
"e": <str>,
"s": <str>,
"r": <str>
}
}
e
and s
are the challenge and response of the DLEQ proof returned by Bob
, r
is the blinding factor of Alice
that was used to generate the Proof
. Alice
serializes these proofs like any other in a token (see NUT-00) to send it to another user Carol
.
When minting or swapping tokens, Alice
receives DLEQ proofs in the BlindSignature
response from the mint Bob
. Alice
checks the validity of the DLEQ proofs for each ecash token she receives via the equations:
R1 = s*G - e*A
R2 = s*B' - e*C'
e == hash(R1,R2,A,C') # must be True
Here, the variables are
A
– the public keyBob
used to sign this Proof(e, s)
– the DLEQ proof returned byBob
B'
–Alice
'sBlindedMessage
C'
–Bob
'sBlindSignature
onB'
In order to execute the proof, Alice
needs e, s
that are returned in the BlindSignature
by Bob
. Alice
further needs B'
(the BlindedMessage
Alice
created and Bob
signed) and C'
(the blind signature in the BlindSignature
response) from Bob
, and A
(the public key of Bob
with which he signed the BlindedMessage). All these values are available to Alice
during or after calling the mint and swap operations.
If a DLEQ proof is included in the mint's BlindSignature
response, wallets MUST verify the DLEQ proof.
Carol
is a user that receives Proofs
in a token from another user Alice. When Alice
sends Proofs
with DLEQ proofs to Carol
or when Alice
posts the Proofs
publicly, Carol
can validate the DLEQ proof herself and verify Bob
's signature without having to talk to Bob
. Alice
includes the following information in the Proof
(see above):
(x, C)
– the ecashProof
(e, s)
– the DLEQ proof revealed byAlice
r
–Alice
's blinding factor
Here, x
is the Proof's secret, and C
is the mint's signature on it. To execute the DLEQ proof like Alice
did above, Carol
needs (B', C')
which she can compute herself using the blinding factor r
that she receives from Alice
.
To verify the DLEQ proof of a received token, Carol
needs to reconstruct B'
and C'
using the blinding factor r
that Alice
has included in the Proof
she sent to Carol
. Since Carol
now has all the necessary information, she can execute the same equations to verify the DLEQ proof as Alice
did:
Y = hash_to_curve(x)
C' = C + r*A
B' = Y + r*G
R1 = ... (same as Alice)
If a DLEQ proof is included in a received token, wallets MUST verify the proof.