Blind Schnorr Signature Interactive Demo

Disguise a Nostr event, blindly sign, then unblind the signature and post it!

What are blind signatures?
In order to sign a message with regular schnorr signatures, a secret key and a nonce (random number) are used to sign a challenge for the message, producing a signature. This signature-nonce pair can then be verified against the signer's public key, proving the person signed off on the message using their secret key.

Blind signatures allow for a user (you!) to disguise a message challenge and then request a server to sign your disguised challenge. The user can then take this signature and unblind it. Resulting in a signature that is valid for the original challenge they disguised, while looking completely different to the challenge which the server was asked to sign.

Blind signatures are powerful for protecting user privacy, where a server can act as an authority or coordinator while remaining blind to the exact details of what they are signing off on.

See this fantastic article by Nadav @ suredbits for an intro on blind signatures and some motivations for the mathematics.

Follow steps 1-6

Let's create a message (or Nostr post!), blind it, and ask the Blind Schnorr Server to sign it. The server signs the disguised challenge, and sends back a signature.
We can then unblind this signature, revealing a completely separate signature that is not only valid but also looks completely unrelated to what we asked of the server.

In order to get a better idea for how blind schnorr signatures work, interaction with the signing server is on the left, and our local computation is on the right (WASM).


The server has some private key \(x\) and public key \(X = x*G\).
(\(G\) is the generator point of an elliptic curve - basically all you need to know is that it is impossible to find the secret \(x\) from knowing \(X\)).

1. Generate a nonce

Server generates a new random secret \(k\) and uses it to create a public nonce \(R=k*G\), and saves them.

Server Public Key \(X\):

Nonce \(R\):


2. Choose a message

Choose a message for the server to blindly sign \(m\),

Message \(m\):