secp256kfun
secp256kfun copied to clipboard
Blind Schnorr Signatures
Blind schnorr signatures
Todo:
- [x] proptest
- [x] docs & synopsis
- [x]
fn BlindingTweaks::from_values(alpha, beta)
- [x] Improved method for
needs_negations
? - [x] ~~Move frost and musig
nonce.rs
stuff tobinonce
and introduce a singularnonce
that generates with even-Y (don't have to manually negate in tests & everywhere)~~ Justderive_nonce!()
for now - [x] ~~wrapper~~. Instead follow: Blind Schnorr Signatures and Signed ElGamal Encryption in the Algebraic Group Model .
- [x] A better wrapper that stores some basic ID / context for maximum N sessions, returning
None
when sessions are maxed out. Do not give out any signatures until all N sessions are connected. - [x] Do not also tweak public key (
t
) - [x] Check whether nonce belongs to current signing session at start of
sign()
- [x] Decide whether max_sessions can be
1
and whether to immediately sign (never concurrent) - [x] Decide whether
already_signed
is appropriate. - [x]
BlindSigner::drain_sign
or something to sign remaining
maybe insecure -- do not use
227b6f2e8630a7c74e6341ce076d5277a0d49675 is an attempt to make this secure (still almost certainly insecure -- do not use).
To safely sign, the signing server should use safe_blind_sign_multiple
for N
SignRequest
s where 1 of N
requests are dropped. From my reading this makes parallel signing attacks too difficult as you are unable to rely on all sessions (is 1 of N
always sufficient?).
I doubt this API is ideal (particularly if async), but it's somewhere to start
I'd like to clean up the multiple uses of "blinded" and "tweaked". The struct Blinder
is a bit confusing as to what is disguised and what is not.
These changes have introduced a BlindSigner
to manage the state of a signing server in order to be secure against an adversary trying to forge a signature by solving the ROS problem.
The BlindSigner
uses its internal schnorr nonce_gen()
and a sid
to generate nonces.
Users' requests are processed with sequential calls to sign
on SignatureRequest
s, returning nothing until the BlindSigner
receives max_sessions
requests. Then it will sign all-but-one of the signature requests (in order to avoid concurrent singing attacks) and forget all the nonces
I have made it so that you can set max_sessions
to 1
, resulting in instant signing and never "disconnecting". I have also exposed BlindSigner::sign_single
which should never be called in parallel (documented).
Latest commits make steps to more safely handle state and a clearer distinction between parallel and single-call execution. There is now a sign_all_but_one
to drain all signature requests that were loaded into sign
, can be called whenever instead of waiting for max_sessions
number of signatures.