Expand description

Schnorr signature variants using Ristretto point compression.

Example

Creating a signature on a message is simple.

First, we need to generate a Keypair, which includes both public and secret halves of an asymmetric key. To do so, we need a cryptographically secure pseudorandom number generator (CSPRNG).

use rand::{Rng, rngs::OsRng};
use schnorrkel::{Keypair,Signature};

let keypair: Keypair = Keypair::generate_with(OsRng);

We can now use this keypair to sign a message:

let context = signing_context(b"this signature does this thing");
let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
let signature: Signature = keypair.sign(context.bytes(message));

As well as to verify that this is, indeed, a valid signature on that message:

assert!(keypair.verify(context.bytes(message), &signature).is_ok());

Anyone else, given the public half of the keypair can also easily verify this signature:

use schnorrkel::PublicKey;
let public_key: PublicKey = keypair.public;
assert!(public_key.verify(context.bytes(message), &signature).is_ok());

Serialisation

PublicKeys, MiniSecretKeys, Keypairs, and Signatures can be serialised into byte-arrays by calling .to_bytes(). It’s perfectly acceptible and safe to transfer and/or store those bytes. (Of course, never transfer your secret key to anyone else, since they will only need the public key to verify your signatures!)

use schnorrkel::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, KEYPAIR_LENGTH, SIGNATURE_LENGTH};

let public_key_bytes: [u8; PUBLIC_KEY_LENGTH] = public_key.to_bytes();
let secret_key_bytes: [u8; SECRET_KEY_LENGTH] = keypair.secret.to_bytes();
let keypair_bytes:    [u8; KEYPAIR_LENGTH]    = keypair.to_bytes();
let signature_bytes:  [u8; SIGNATURE_LENGTH]  = signature.to_bytes();

And similarly, decoded from bytes with ::from_bytes():

let public_key: PublicKey = PublicKey::from_bytes(&public_key_bytes)?;
let secret_key: SecretKey = SecretKey::from_bytes(&secret_key_bytes)?;
let keypair:    Keypair   = Keypair::from_bytes(&keypair_bytes)?;
let signature:  Signature = Signature::from_bytes(&signature_bytes)?;

Using Serde

If you prefer the bytes to be wrapped in another serialisation format, all types additionally come with built-in serde support by building schnorrkell via:

$ cargo build --features="serde"

They can be then serialised into any of the wire formats which serde supports. For example, using bincode:

use bincode::{serialize};

let encoded_public_key: Vec<u8> = serialize(&public_key).unwrap();
let encoded_signature: Vec<u8> = serialize(&signature).unwrap();

After sending the encoded_public_key and encoded_signature, the recipient may deserialise them and verify:

use bincode::{deserialize};

let message: &[u8] = "This is a test of the tsunami alert system.".as_bytes();
let decoded_public_key: PublicKey = deserialize(&encoded_public_key).unwrap();
let decoded_signature: Signature = deserialize(&encoded_signature).unwrap();

assert!( public_key.verify(context.bytes(message), &signature).is_ok() );

Re-exports

pub use crate::keys::*;
pub use crate::context::signing_context;
pub use crate::sign::Signature;
pub use crate::sign::SIGNATURE_LENGTH;
pub use crate::errors::SignatureError;
pub use crate::errors::SignatureResult;

Modules

Elliptic curve Qu-Vanstone implicit certificate scheme (ECQV) for Ristretto

Schnorr signature contexts and configuration, adaptable to most Schnorr signature schemes.

Implementation of “hierarchical deterministic key derivation” (HDKD) for Schnorr signatures on Ristretto

Errors which may occur when parsing keys and/or signatures to or from wire formats.

Schnorr signatures on the 2-torsion free subgroup of ed25519, as provided by the Ristretto point compression.

Implementation for Ristretto Schnorr signatures of “Simple Schnorr Multi-Signatures with Applications to Bitcoin” by Gregory Maxwell, Andrew Poelstra, Yannick Seurin, and Pieter Wuille https://eprint.iacr.org/2018/068

Ristretto point tooling

Schnorr signature creation and verification, including batch verification.

Implementation of a Verifiable Random Function (VRF) using Ristretto points and Schnorr DLEQ proofs.

Functions

Verify a batch of signatures on messages with their respective public_keys.

Verify a batch of signatures on messages with their respective public_keys.

Verify a batch of signatures on messages with their respective public_keys.