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.rsstuff tobinonceand introduce a singularnoncethat 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
Nonewhen 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
1and whether to immediately sign (never concurrent) - [x] Decide whether
already_signedis appropriate. - [x]
BlindSigner::drain_signor 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 SignRequests 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 SignatureRequests, 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.