secp256k1_test/
schnorr.rs

1// Bitcoin secp256k1 bindings
2// Written in 2014 by
3//   Dawid Ciężarkiewicz
4//   Andrew Poelstra
5//
6// To the extent possible under law, the author(s) have dedicated all
7// copyright and related and neighboring rights to this software to
8// the public domain worldwide. This software is distributed without
9// any warranty.
10//
11// You should have received a copy of the CC0 Public Domain Dedication
12// along with this software.
13// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
14//
15
16//! # Schnorr signatures
17
18use ContextFlag;
19use Error;
20use Message;
21use Secp256k1;
22
23use constants;
24use ffi;
25use key::{SecretKey, PublicKey};
26
27use std::{mem, ptr};
28use std::convert::From;
29
30/// A Schnorr signature.
31pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
32impl_array_newtype!(Signature, u8, constants::SCHNORR_SIGNATURE_SIZE);
33impl_pretty_debug!(Signature);
34
35impl Signature {
36    /// Deserializes a signature from a 64-byte vector
37    pub fn deserialize(data: &[u8]) -> Signature {
38        assert_eq!(data.len(), constants::SCHNORR_SIGNATURE_SIZE);
39        let mut ret = [0; constants::SCHNORR_SIGNATURE_SIZE];
40        ret[..].copy_from_slice(data);
41        Signature(ret)
42    }
43
44    /// Serializes a signature to a 64-byte vector
45    pub fn serialize(&self) -> Vec<u8> {
46        Vec::from(&self.0[..])
47    }
48}
49
50impl Secp256k1 {
51    /// Create a Schnorr signature
52    pub fn sign_schnorr(&self, msg: &Message, sk: &SecretKey) -> Result<Signature, Error> {
53        if self.caps == ContextFlag::VerifyOnly || self.caps == ContextFlag::None {
54            return Err(Error::IncapableContext);
55        }
56
57        let mut ret: Signature = unsafe { mem::uninitialized() };
58        unsafe {
59            // We can assume the return value because it's not possible to construct
60            // an invalid signature from a valid `Message` and `SecretKey`
61            let err = ffi::secp256k1_schnorr_sign(self.ctx, ret.as_mut_ptr(), msg.as_ptr(),
62                                                  sk.as_ptr(), ffi::secp256k1_nonce_function_rfc6979,
63                                                  ptr::null());
64            debug_assert_eq!(err, 1);
65        }
66        Ok(ret)
67    }
68
69    /// Verify a Schnorr signature
70    pub fn verify_schnorr(&self, msg: &Message, sig: &Signature, pk: &PublicKey) -> Result<(), Error> {
71        if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None {
72            return Err(Error::IncapableContext);
73        }
74
75        if !pk.is_valid() {
76            Err(Error::InvalidPublicKey)
77        } else if unsafe { ffi::secp256k1_schnorr_verify(self.ctx, sig.as_ptr(), msg.as_ptr(),
78                                                         pk.as_ptr()) } == 0 {
79            Err(Error::IncorrectSignature)
80        } else {
81            Ok(())
82        }
83    }
84
85    /// Retrieves the public key for which `sig` is a valid signature for `msg`.
86    /// Requires a verify-capable context.
87    pub fn recover_schnorr(&self, msg: &Message, sig: &Signature)
88                           -> Result<PublicKey, Error> {
89        if self.caps == ContextFlag::SignOnly || self.caps == ContextFlag::None {
90            return Err(Error::IncapableContext);
91        }
92
93        let mut pk = unsafe { ffi::PublicKey::blank() };
94        unsafe {
95            if ffi::secp256k1_schnorr_recover(self.ctx, &mut pk,
96                                              sig.as_ptr(), msg.as_ptr()) != 1 {
97                return Err(Error::InvalidSignature);
98            }
99        };
100        Ok(PublicKey::from(pk))
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use rand::{Rng, thread_rng};
107    use ContextFlag;
108    use Message;
109    use Secp256k1;
110    use Error::IncapableContext;
111    use super::Signature;
112
113    #[test]
114    fn capabilities() {
115        let none = Secp256k1::with_caps(ContextFlag::None);
116        let sign = Secp256k1::with_caps(ContextFlag::SignOnly);
117        let vrfy = Secp256k1::with_caps(ContextFlag::VerifyOnly);
118        let full = Secp256k1::with_caps(ContextFlag::Full);
119
120        let mut msg = [0u8; 32];
121        thread_rng().fill_bytes(&mut msg);
122        let msg = Message::from_slice(&msg).unwrap();
123
124        let (sk, pk) = full.generate_keypair(&mut thread_rng()).unwrap();
125
126        // Try signing
127        assert_eq!(none.sign_schnorr(&msg, &sk), Err(IncapableContext));
128        assert_eq!(vrfy.sign_schnorr(&msg, &sk), Err(IncapableContext));
129        assert!(sign.sign_schnorr(&msg, &sk).is_ok());
130        assert!(full.sign_schnorr(&msg, &sk).is_ok());
131        assert_eq!(sign.sign_schnorr(&msg, &sk), full.sign_schnorr(&msg, &sk));
132        let sig = full.sign_schnorr(&msg, &sk).unwrap();
133
134        // Try verifying
135        assert_eq!(none.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext));
136        assert_eq!(sign.verify_schnorr(&msg, &sig, &pk), Err(IncapableContext));
137        assert!(vrfy.verify_schnorr(&msg, &sig, &pk).is_ok());
138        assert!(full.verify_schnorr(&msg, &sig, &pk).is_ok());
139
140        // Try pk recovery
141        assert_eq!(none.recover_schnorr(&msg, &sig), Err(IncapableContext));
142        assert_eq!(sign.recover_schnorr(&msg, &sig), Err(IncapableContext));
143        assert!(vrfy.recover_schnorr(&msg, &sig).is_ok());
144        assert!(full.recover_schnorr(&msg, &sig).is_ok());
145
146        assert_eq!(vrfy.recover_schnorr(&msg, &sig),
147                   full.recover_schnorr(&msg, &sig));
148        assert_eq!(full.recover_schnorr(&msg, &sig), Ok(pk));
149    }
150
151    #[test]
152    fn sign_verify() {
153        let mut s = Secp256k1::new();
154        s.randomize(&mut thread_rng());
155
156        let mut msg = [0u8; 32];
157        thread_rng().fill_bytes(&mut msg);
158        let msg = Message::from_slice(&msg).unwrap();
159
160        let (sk, pk) = s.generate_keypair(&mut thread_rng()).unwrap();
161
162        let sig = s.sign_schnorr(&msg, &sk).unwrap();
163        assert!(s.verify_schnorr(&msg, &sig, &pk).is_ok());
164    }
165
166    #[test]
167    fn deserialize() {
168        let mut s = Secp256k1::new();
169        s.randomize(&mut thread_rng());
170
171        let mut msg = [0u8; 32];
172        thread_rng().fill_bytes(&mut msg);
173        let msg = Message::from_slice(&msg).unwrap();
174
175        let (sk, _) = s.generate_keypair(&mut thread_rng()).unwrap();
176
177        let sig1 = s.sign_schnorr(&msg, &sk).unwrap();
178        let sig2 = Signature::deserialize(&sig1.serialize());
179        assert_eq!(sig1, sig2);
180    }
181}
182