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