secp256k1/
schnorr.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Support for schnorr signatures.
4//!
5
6use core::{fmt, ptr, str};
7
8#[cfg(feature = "rand")]
9use rand::{CryptoRng, Rng};
10use secp256k1_sys::SchnorrSigExtraParams;
11
12use crate::ffi::{self, CPtr};
13use crate::key::{Keypair, XOnlyPublicKey};
14#[cfg(feature = "global-context")]
15use crate::SECP256K1;
16use crate::{constants, from_hex, Error, Secp256k1, Signing, Verification};
17
18/// Represents a schnorr signature.
19#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
21impl_array_newtype!(Signature, u8, constants::SCHNORR_SIGNATURE_SIZE);
22impl_pretty_debug!(Signature);
23
24#[cfg(feature = "serde")]
25impl serde::Serialize for Signature {
26    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
27        if s.is_human_readable() {
28            s.collect_str(self)
29        } else {
30            s.serialize_bytes(&self[..])
31        }
32    }
33}
34
35#[cfg(feature = "serde")]
36impl<'de> serde::Deserialize<'de> for Signature {
37    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
38        if d.is_human_readable() {
39            d.deserialize_str(super::serde_util::FromStrVisitor::new(
40                "a hex string representing 64 byte schnorr signature",
41            ))
42        } else {
43            d.deserialize_bytes(super::serde_util::BytesVisitor::new(
44                "raw 64 bytes schnorr signature",
45                |x| x.try_into().map(Signature::from_byte_array),
46            ))
47        }
48    }
49}
50
51impl fmt::LowerHex for Signature {
52    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53        for ch in &self.0[..] {
54            write!(f, "{:02x}", ch)?;
55        }
56        Ok(())
57    }
58}
59
60impl fmt::Display for Signature {
61    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
62}
63
64impl str::FromStr for Signature {
65    type Err = Error;
66    fn from_str(s: &str) -> Result<Signature, Error> {
67        let mut res = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
68        match from_hex(s, &mut res) {
69            Ok(constants::SCHNORR_SIGNATURE_SIZE) => Ok(Signature::from_byte_array(res)),
70            _ => Err(Error::InvalidSignature),
71        }
72    }
73}
74
75impl Signature {
76    /// Construct a `Signature` from a 64 bytes array.
77    #[inline]
78    pub fn from_byte_array(sig: [u8; constants::SCHNORR_SIGNATURE_SIZE]) -> Self { Self(sig) }
79
80    /// Creates a `Signature` directly from a slice.
81    #[deprecated(since = "0.30.0", note = "Use `from_byte_array` instead.")]
82    #[inline]
83    pub fn from_slice(data: &[u8]) -> Result<Signature, Error> {
84        match data.len() {
85            constants::SCHNORR_SIGNATURE_SIZE => {
86                let mut ret = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
87                ret[..].copy_from_slice(data);
88                Ok(Signature(ret))
89            }
90            _ => Err(Error::InvalidSignature),
91        }
92    }
93
94    /// Returns a signature as a byte array.
95    #[deprecated(since = "0.30.0", note = "Use `to_byte_array` instead.")]
96    pub fn serialize(&self) -> [u8; constants::SCHNORR_SIGNATURE_SIZE] { self.0 }
97
98    /// Returns a signature as a byte array.
99    #[inline]
100    pub fn to_byte_array(self) -> [u8; constants::SCHNORR_SIGNATURE_SIZE] { self.0 }
101
102    /// Returns a signature as a byte array.
103    #[inline]
104    pub fn as_byte_array(&self) -> &[u8; constants::SCHNORR_SIGNATURE_SIZE] { &self.0 }
105
106    /// Verifies a schnorr signature for `msg` using `pk` and the global [`SECP256K1`] context.
107    #[inline]
108    #[cfg(feature = "global-context")]
109    pub fn verify(&self, msg: &[u8], pk: &XOnlyPublicKey) -> Result<(), Error> {
110        SECP256K1.verify_schnorr(self, msg, pk)
111    }
112}
113
114impl<C: Signing> Secp256k1<C> {
115    fn sign_schnorr_helper(
116        &self,
117        msg: &[u8],
118        keypair: &Keypair,
119        nonce_data: *const ffi::types::c_uchar,
120    ) -> Signature {
121        unsafe {
122            let mut sig = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
123            let extra = SchnorrSigExtraParams::new(None, nonce_data.cast());
124            assert_eq!(
125                1,
126                ffi::secp256k1_schnorrsig_sign_custom(
127                    self.ctx.as_ptr(),
128                    sig.as_mut_c_ptr(),
129                    msg.as_c_ptr(),
130                    msg.len(),
131                    keypair.as_c_ptr(),
132                    &extra,
133                )
134            );
135
136            Signature(sig)
137        }
138    }
139
140    /// Creates a schnorr signature internally using the [`rand::rngs::ThreadRng`] random number
141    /// generator to generate the auxiliary random data.
142    #[cfg(all(feature = "rand", feature = "std"))]
143    pub fn sign_schnorr(&self, msg: &[u8], keypair: &Keypair) -> Signature {
144        self.sign_schnorr_with_rng(msg, keypair, &mut rand::rng())
145    }
146
147    /// Creates a schnorr signature without using any auxiliary random data.
148    pub fn sign_schnorr_no_aux_rand(&self, msg: &[u8], keypair: &Keypair) -> Signature {
149        self.sign_schnorr_helper(msg, keypair, ptr::null())
150    }
151
152    /// Creates a schnorr signature using the given auxiliary random data.
153    pub fn sign_schnorr_with_aux_rand(
154        &self,
155        msg: &[u8],
156        keypair: &Keypair,
157        aux_rand: &[u8; 32],
158    ) -> Signature {
159        self.sign_schnorr_helper(msg, keypair, aux_rand.as_c_ptr() as *const ffi::types::c_uchar)
160    }
161
162    /// Creates a schnorr signature using the given random number generator to
163    /// generate the auxiliary random data.
164    #[cfg(feature = "rand")]
165    pub fn sign_schnorr_with_rng<R: Rng + CryptoRng>(
166        &self,
167        msg: &[u8],
168        keypair: &Keypair,
169        rng: &mut R,
170    ) -> Signature {
171        let mut aux = [0u8; 32];
172        rng.fill_bytes(&mut aux);
173        self.sign_schnorr_helper(msg, keypair, aux.as_c_ptr() as *const ffi::types::c_uchar)
174    }
175}
176
177impl<C: Verification> Secp256k1<C> {
178    /// Verifies a schnorr signature.
179    pub fn verify_schnorr(
180        &self,
181        sig: &Signature,
182        msg: &[u8],
183        pubkey: &XOnlyPublicKey,
184    ) -> Result<(), Error> {
185        unsafe {
186            let ret = ffi::secp256k1_schnorrsig_verify(
187                self.ctx.as_ptr(),
188                sig.as_c_ptr(),
189                msg.as_c_ptr(),
190                msg.len(),
191                pubkey.as_c_ptr(),
192            );
193
194            if ret == 1 {
195                Ok(())
196            } else {
197                Err(Error::IncorrectSignature)
198            }
199        }
200    }
201}
202
203#[cfg(test)]
204#[allow(unused_imports)]
205mod tests {
206    use core::str::FromStr;
207
208    #[cfg(all(feature = "rand", feature = "std"))]
209    use rand::rngs::ThreadRng;
210    #[cfg(target_arch = "wasm32")]
211    use wasm_bindgen_test::wasm_bindgen_test as test;
212
213    use super::*;
214    use crate::schnorr::{Keypair, Signature, XOnlyPublicKey};
215    use crate::Error::InvalidPublicKey;
216    use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
217
218    #[cfg(all(not(secp256k1_fuzz), feature = "alloc"))]
219    macro_rules! hex_32 {
220        ($hex:expr) => {{
221            let mut result = [0u8; 32];
222            from_hex($hex, &mut result).expect("valid hex string");
223            result
224        }};
225    }
226
227    #[test]
228    #[cfg(all(feature = "rand", feature = "std"))]
229    fn schnorr_sign_with_aux_rand_verify() {
230        sign_helper(|secp, msg, seckey, rng| {
231            let aux_rand = crate::random_32_bytes(rng);
232            secp.sign_schnorr_with_aux_rand(msg, seckey, &aux_rand)
233        })
234    }
235
236    #[test]
237    #[cfg(all(feature = "rand", feature = "std"))]
238    fn schnor_sign_with_rng_verify() {
239        sign_helper(|secp, msg, seckey, rng| secp.sign_schnorr_with_rng(msg, seckey, rng))
240    }
241
242    #[test]
243    #[cfg(all(feature = "rand", feature = "std"))]
244    fn schnorr_sign_verify() { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr(msg, seckey)) }
245
246    #[test]
247    #[cfg(all(feature = "rand", feature = "std"))]
248    fn schnorr_sign_no_aux_rand_verify() {
249        sign_helper(|secp, msg, seckey, _| secp.sign_schnorr_no_aux_rand(msg, seckey))
250    }
251
252    #[cfg(all(feature = "rand", feature = "std"))]
253    fn sign_helper(sign: fn(&Secp256k1<crate::All>, &[u8], &Keypair, &mut ThreadRng) -> Signature) {
254        let secp = Secp256k1::new();
255
256        let mut rng = rand::rng();
257        let kp = Keypair::new(&secp, &mut rng);
258        let (pk, _parity) = kp.x_only_public_key();
259
260        for _ in 0..100 {
261            let msg = crate::random_32_bytes(&mut rand::rng());
262
263            let sig = sign(&secp, &msg, &kp, &mut rng);
264
265            assert!(secp.verify_schnorr(&sig, &msg, &pk).is_ok());
266        }
267    }
268
269    #[test]
270    #[cfg(feature = "alloc")]
271    #[cfg(not(secp256k1_fuzz))] // fixed sig vectors can't work with fuzz-sigs
272    fn schnorr_sign() {
273        let secp = Secp256k1::new();
274
275        let msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
276        let sk = Keypair::from_seckey_str(
277            &secp,
278            "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF",
279        )
280        .unwrap();
281        let aux_rand: [u8; 32] =
282            hex_32!("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB");
283        let expected_sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
284
285        let sig = secp.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
286
287        assert_eq!(expected_sig, sig);
288    }
289
290    #[test]
291    #[cfg(not(secp256k1_fuzz))] // fixed sig vectors can't work with fuzz-sigs
292    #[cfg(feature = "alloc")]
293    fn schnorr_verify() {
294        let secp = Secp256k1::new();
295
296        let msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
297        let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
298        let pubkey = XOnlyPublicKey::from_str(
299            "B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390",
300        )
301        .unwrap();
302
303        assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok());
304    }
305
306    #[test]
307    fn test_serialize() {
308        let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
309        let sig_bytes = sig.to_byte_array();
310        let bytes = [
311            100, 112, 253, 19, 3, 221, 164, 253, 167, 23, 185, 131, 113, 83, 194, 74, 110, 171, 55,
312            113, 131, 252, 67, 143, 147, 158, 14, 210, 182, 32, 233, 238, 80, 119, 196, 168, 184,
313            220, 162, 137, 99, 215, 114, 169, 79, 95, 13, 223, 89, 142, 28, 71, 193, 55, 249, 25,
314            51, 39, 76, 124, 62, 218, 220, 232,
315        ];
316        assert_eq!(sig_bytes, bytes);
317    }
318
319    #[test]
320    #[allow(deprecated)]
321    fn test_pubkey_from_slice() {
322        let pk = XOnlyPublicKey::from_slice(&[
323            0xB3, 0x3C, 0xC9, 0xED, 0xC0, 0x96, 0xD0, 0xA8, 0x34, 0x16, 0x96, 0x4B, 0xD3, 0xC6,
324            0x24, 0x7B, 0x8F, 0xEC, 0xD2, 0x56, 0xE4, 0xEF, 0xA7, 0x87, 0x0D, 0x2C, 0x85, 0x4B,
325            0xDE, 0xB3, 0x33, 0x90,
326        ]);
327        assert!(pk.is_ok());
328    }
329
330    #[test]
331    #[allow(deprecated)]
332    fn test_pubkey_from_bad_slice() {
333        // Bad sizes
334        assert_eq!(XOnlyPublicKey::from_slice(&[]), Err(InvalidPublicKey));
335        assert_eq!(XOnlyPublicKey::from_slice(&[1, 2, 3]), Err(InvalidPublicKey));
336        assert_eq!(
337            XOnlyPublicKey::from_slice(&[0; constants::SCHNORR_PUBLIC_KEY_SIZE - 1]),
338            Err(InvalidPublicKey)
339        );
340        assert_eq!(
341            XOnlyPublicKey::from_slice(&[0; constants::SCHNORR_PUBLIC_KEY_SIZE + 1]),
342            Err(InvalidPublicKey)
343        );
344
345        // Bad parse
346        assert_eq!(
347            XOnlyPublicKey::from_slice(&[0xff; constants::SCHNORR_PUBLIC_KEY_SIZE]),
348            Err(InvalidPublicKey)
349        );
350        // In fuzzing mode restrictions on public key validity are much more
351        // relaxed, thus the invalid check below is expected to fail.
352        #[cfg(not(secp256k1_fuzz))]
353        assert_eq!(
354            XOnlyPublicKey::from_slice(&[0x55; constants::SCHNORR_PUBLIC_KEY_SIZE]),
355            Err(InvalidPublicKey)
356        );
357        assert_eq!(XOnlyPublicKey::from_slice(&[]), Err(InvalidPublicKey));
358    }
359
360    #[test]
361    #[cfg(all(feature = "rand", feature = "std"))]
362    fn test_pubkey_serialize_roundtrip() {
363        let secp = Secp256k1::new();
364        let kp = Keypair::new(&secp, &mut rand::rng());
365        let (pk, _parity) = kp.x_only_public_key();
366
367        let ser = pk.serialize();
368        let pubkey2 = XOnlyPublicKey::from_byte_array(ser).unwrap();
369        assert_eq!(pk, pubkey2);
370    }
371
372    #[test]
373    #[cfg(feature = "alloc")]
374    fn test_xonly_key_extraction() {
375        let secp = Secp256k1::new();
376        let sk_str = "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF";
377        let keypair = Keypair::from_seckey_str(&secp, sk_str).unwrap();
378        let sk = SecretKey::from_keypair(&keypair);
379        assert_eq!(SecretKey::from_str(sk_str).unwrap(), sk);
380        let pk = crate::key::PublicKey::from_keypair(&keypair);
381        assert_eq!(crate::key::PublicKey::from_secret_key(&secp, &sk), pk);
382        let (xpk, _parity) = keypair.x_only_public_key();
383        assert_eq!(XOnlyPublicKey::from(pk), xpk);
384    }
385
386    #[test]
387    #[cfg(feature = "std")]
388    fn test_pubkey_display_output() {
389        #[cfg(not(secp256k1_fuzz))]
390        let pk = {
391            let secp = Secp256k1::new();
392            static SK_BYTES: [u8; 32] = [
393                0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
394                0x06, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63,
395                0x63, 0x63, 0x63, 0x63,
396            ];
397
398            let kp = Keypair::from_seckey_byte_array(&secp, SK_BYTES).expect("sk");
399
400            // In fuzzing mode secret->public key derivation is different, so
401            // hard-code the expected result.
402            let (pk, _parity) = kp.x_only_public_key();
403            pk
404        };
405        #[cfg(secp256k1_fuzz)]
406        let pk = XOnlyPublicKey::from_slice(&[
407            0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92,
408            0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe,
409            0x91, 0xdd, 0xd1, 0x66,
410        ])
411        .expect("pk");
412
413        assert_eq!(
414            pk.to_string(),
415            "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
416        );
417        assert_eq!(
418            XOnlyPublicKey::from_str(
419                "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
420            )
421            .unwrap(),
422            pk
423        );
424
425        assert!(XOnlyPublicKey::from_str(
426            "00000000000000000000000000000000000000000000000000000000000000000"
427        )
428        .is_err());
429        assert!(XOnlyPublicKey::from_str(
430            "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16601"
431        )
432        .is_err());
433        assert!(XOnlyPublicKey::from_str(
434            "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16"
435        )
436        .is_err());
437        assert!(XOnlyPublicKey::from_str(
438            "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1"
439        )
440        .is_err());
441        assert!(XOnlyPublicKey::from_str(
442            "xx18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1"
443        )
444        .is_err());
445
446        let long_str: String = "a".repeat(1024 * 1024);
447        assert!(XOnlyPublicKey::from_str(&long_str).is_err());
448    }
449
450    #[test]
451    // In fuzzing mode secret->public key derivation is different, so
452    // this test will never correctly derive the static pubkey.
453    #[cfg(not(secp256k1_fuzz))]
454    #[cfg(all(feature = "rand", feature = "alloc"))]
455    fn test_pubkey_serialize() {
456        use rand::rngs::mock::StepRng;
457        let secp = Secp256k1::new();
458        let kp = Keypair::new(&secp, &mut StepRng::new(1, 1));
459        let (pk, _parity) = kp.x_only_public_key();
460        assert_eq!(
461            &pk.serialize()[..],
462            &[
463                124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9,
464                181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229
465            ][..]
466        );
467    }
468
469    #[cfg(not(secp256k1_fuzz))] // fixed sig vectors can't work with fuzz-sigs
470    #[test]
471    #[cfg(all(feature = "serde", feature = "alloc"))]
472    fn test_serde() {
473        use serde_test::{assert_tokens, Configure, Token};
474
475        let s = Secp256k1::new();
476
477        let msg = [1; 32];
478        let keypair = Keypair::from_seckey_byte_array(&s, [2; 32]).unwrap();
479        let aux = [3u8; 32];
480        let sig = s.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
481        static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [
482            0x14, 0xd0, 0xbf, 0x1a, 0x89, 0x53, 0x50, 0x6f, 0xb4, 0x60, 0xf5, 0x8b, 0xe1, 0x41,
483            0xaf, 0x76, 0x7f, 0xd1, 0x12, 0x53, 0x5f, 0xb3, 0x92, 0x2e, 0xf2, 0x17, 0x30, 0x8e,
484            0x2c, 0x26, 0x70, 0x6f, 0x1e, 0xeb, 0x43, 0x2b, 0x3d, 0xba, 0x9a, 0x01, 0x08, 0x2f,
485            0x9e, 0x4d, 0x4e, 0xf5, 0x67, 0x8a, 0xd0, 0xd9, 0xd5, 0x32, 0xc0, 0xdf, 0xa9, 0x07,
486            0xb5, 0x68, 0x72, 0x2d, 0x0b, 0x01, 0x19, 0xba,
487        ];
488        static SIG_STR: &str = "\
489            14d0bf1a8953506fb460f58be141af767fd112535fb3922ef217308e2c26706f1eeb432b3dba9a01082f9e4d4ef5678ad0d9d532c0dfa907b568722d0b0119ba\
490        ";
491
492        static PK_BYTES: [u8; 32] = [
493            24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127, 48,
494            170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102,
495        ];
496        static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
497        let pk = XOnlyPublicKey::from_byte_array(PK_BYTES).unwrap();
498
499        assert_tokens(&sig.compact(), &[Token::BorrowedBytes(&SIG_BYTES[..])]);
500        assert_tokens(&sig.compact(), &[Token::Bytes(&SIG_BYTES[..])]);
501        assert_tokens(&sig.compact(), &[Token::ByteBuf(&SIG_BYTES[..])]);
502
503        assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
504        assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
505        assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
506
507        #[rustfmt::skip]
508        assert_tokens(&pk.compact(), &[
509            Token::Tuple{ len: 32 },
510            Token::U8(24), Token::U8(132), Token::U8(87), Token::U8(129), Token::U8(246), Token::U8(49), Token::U8(196), Token::U8(143),
511            Token::U8(28), Token::U8(151), Token::U8(9), Token::U8(226), Token::U8(48), Token::U8(146), Token::U8(6), Token::U8(125),
512            Token::U8(6), Token::U8(131), Token::U8(127), Token::U8(48), Token::U8(170), Token::U8(12), Token::U8(208), Token::U8(84),
513            Token::U8(74), Token::U8(200), Token::U8(135), Token::U8(254), Token::U8(145), Token::U8(221), Token::U8(209), Token::U8(102),
514            Token::TupleEnd
515        ]);
516
517        assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]);
518        assert_tokens(&pk.readable(), &[Token::Str(PK_STR)]);
519        assert_tokens(&pk.readable(), &[Token::String(PK_STR)]);
520    }
521
522    #[test]
523    #[cfg(feature = "alloc")]
524    #[cfg(not(secp256k1_fuzz))] // fixed sig vectors can't work with fuzz-sigs
525    fn bip340_test_vectors() {
526        struct TestVector {
527            secret_key: Option<[u8; 32]>,
528            public_key: [u8; 32],
529            aux_rand: Option<[u8; 32]>,
530            message: Vec<u8>,
531            signature: [u8; 64],
532            should_fail_verify: bool,
533        }
534        fn hex_arr<T: From<[u8; N]>, const N: usize>(s: &str) -> T {
535            let mut out = [0; N];
536            from_hex(s, &mut out).unwrap();
537            out.into()
538        }
539        let hex_vec = |s: &str| {
540            let mut v = vec![0u8; s.len() / 2];
541            from_hex(s, v.as_mut_slice()).unwrap();
542            v
543        };
544
545        let vectors = [
546            TestVector {
547                secret_key: hex_arr("0000000000000000000000000000000000000000000000000000000000000003"),
548                public_key: hex_arr("F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9"),
549                aux_rand: hex_arr("0000000000000000000000000000000000000000000000000000000000000000"),
550                message: hex_vec("0000000000000000000000000000000000000000000000000000000000000000"),
551                signature: hex_arr("E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0"),
552                should_fail_verify: false,
553            },
554            TestVector {
555                secret_key: hex_arr("B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF"),
556                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
557                aux_rand: hex_arr("0000000000000000000000000000000000000000000000000000000000000001"),
558                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
559                signature: hex_arr("6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A"),
560                should_fail_verify: false,
561            },
562            TestVector {
563                secret_key: hex_arr("C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9"),
564                public_key: hex_arr("DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8"),
565                aux_rand: hex_arr("C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906"),
566                message: hex_vec("7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C"),
567                signature: hex_arr("5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB745879A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7"),
568                should_fail_verify: false,
569            },
570            TestVector {
571                secret_key: hex_arr("0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710"),
572                public_key: hex_arr("25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517"),
573                aux_rand: hex_arr("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
574                message: hex_vec("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
575                signature: hex_arr("7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3"),
576                should_fail_verify: false,
577            },
578            TestVector {
579                secret_key: None,
580                public_key: hex_arr("D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9"),
581                aux_rand: None,
582                message: hex_vec("4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703"),
583                signature: hex_arr("00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB1548AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4"),
584                should_fail_verify: false,
585            },
586            TestVector {
587                secret_key: None,
588                public_key: hex_arr("EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34"),
589                aux_rand: None,
590                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
591                signature: hex_arr("6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B"),
592                should_fail_verify: true,
593            },
594            TestVector {
595                secret_key: None,
596                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
597                aux_rand: None,
598                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
599                signature: hex_arr("FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC27944640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2"),
600                should_fail_verify: true,
601            },
602            TestVector {
603                secret_key: None,
604                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
605                aux_rand: None,
606                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
607                signature: hex_arr("1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD"),
608                should_fail_verify: true,
609            },
610            TestVector {
611                secret_key: None,
612                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
613                aux_rand: None,
614                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
615                signature: hex_arr("6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6"),
616                should_fail_verify: true,
617            },
618            TestVector {
619                secret_key: None,
620                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
621                aux_rand: None,
622                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
623                signature: hex_arr("0000000000000000000000000000000000000000000000000000000000000000123DDA8328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051"),
624                should_fail_verify: true,
625            },
626            TestVector {
627                secret_key: None,
628                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
629                aux_rand: None,
630                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
631                signature: hex_arr("00000000000000000000000000000000000000000000000000000000000000017615FBAF5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197"),
632                should_fail_verify: true,
633            },
634            TestVector {
635                secret_key: None,
636                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
637                aux_rand: None,
638                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
639                signature: hex_arr("4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B"),
640                should_fail_verify: true,
641            },
642            TestVector {
643                secret_key: None,
644                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
645                aux_rand: None,
646                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
647                signature: hex_arr("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B"),
648                should_fail_verify: true,
649            },
650            TestVector {
651                secret_key: None,
652                public_key: hex_arr("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"),
653                aux_rand: None,
654                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
655                signature: hex_arr("6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"),
656                should_fail_verify: true,
657            },
658            TestVector {
659                secret_key: None,
660                public_key: hex_arr("778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117"),
661                aux_rand: None,
662                message: hex_vec("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"),
663                signature: hex_arr("6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B"),
664                should_fail_verify: true,
665            },
666            TestVector {
667                secret_key: hex_arr("0340034003400340034003400340034003400340034003400340034003400340"),
668                public_key: hex_arr("778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117"),
669                aux_rand: hex_arr("0000000000000000000000000000000000000000000000000000000000000000"),
670                message: hex_vec(""),
671                signature: hex_arr("71535DB165ECD9FBBC046E5FFAEA61186BB6AD436732FCCC25291A55895464CF6069CE26BF03466228F19A3A62DB8A649F2D560FAC652827D1AF0574E427AB63"),
672                should_fail_verify: false,
673            },
674              TestVector {
675                secret_key: hex_arr("0340034003400340034003400340034003400340034003400340034003400340"),
676                public_key: hex_arr("778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117"),
677                aux_rand: hex_arr("0000000000000000000000000000000000000000000000000000000000000000"),
678                message: hex_vec("11"),
679                signature: hex_arr("08A20A0AFEF64124649232E0693C583AB1B9934AE63B4C3511F3AE1134C6A303EA3173BFEA6683BD101FA5AA5DBC1996FE7CACFC5A577D33EC14564CEC2BACBF"),
680                should_fail_verify: false,
681            },
682            TestVector {
683                secret_key: hex_arr("0340034003400340034003400340034003400340034003400340034003400340"),
684                public_key: hex_arr("778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117"),
685                aux_rand: hex_arr("0000000000000000000000000000000000000000000000000000000000000000"),
686                message: hex_vec("0102030405060708090A0B0C0D0E0F1011"),
687                signature: hex_arr("5130F39A4059B43BC7CAC09A19ECE52B5D8699D1A71E3C52DA9AFDB6B50AC370C4A482B77BF960F8681540E25B6771ECE1E5A37FD80E5A51897C5566A97EA5A5"),
688                should_fail_verify: false,
689            },
690            TestVector {
691                secret_key: hex_arr("0340034003400340034003400340034003400340034003400340034003400340"),
692                public_key: hex_arr("778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117"),
693                aux_rand: hex_arr("0000000000000000000000000000000000000000000000000000000000000000"),
694                message: hex_vec("99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"),
695                signature: hex_arr("403B12B0D8555A344175EA7EC746566303321E5DBFA8BE6F091635163ECA79A8585ED3E3170807E7C03B720FC54C7B23897FCBA0E9D0B4A06894CFD249F22367"),
696                should_fail_verify: false,
697            },
698        ];
699        let secp = Secp256k1::new();
700
701        for TestVector {
702            secret_key,
703            public_key,
704            aux_rand,
705            message,
706            signature,
707            should_fail_verify,
708        } in vectors
709        {
710            if let (Some(secret_key), Some(aux_rand)) = (secret_key, aux_rand) {
711                let keypair = Keypair::from_seckey_byte_array(&secp, secret_key).unwrap();
712                assert_eq!(keypair.x_only_public_key().0.serialize(), public_key);
713                let sig = secp.sign_schnorr_with_aux_rand(&message, &keypair, &aux_rand);
714                assert_eq!(sig.to_byte_array(), signature);
715            }
716            let sig = Signature::from_byte_array(signature);
717            let is_verified = if let Ok(pubkey) = XOnlyPublicKey::from_byte_array(public_key) {
718                secp.verify_schnorr(&sig, &message, &pubkey).is_ok()
719            } else {
720                false
721            };
722            assert_eq!(is_verified, !should_fail_verify);
723        }
724    }
725}