1use core::{fmt, ptr, str};
7
8#[cfg(feature = "rand")]
9use rand::{CryptoRng, Rng};
10
11use crate::ffi::{self, CPtr};
12use crate::key::{Keypair, XOnlyPublicKey};
13#[cfg(feature = "global-context")]
14use crate::SECP256K1;
15use crate::{
16 constants, from_hex, impl_array_newtype, Error, Message, Secp256k1, Signing, Verification,
17};
18
19#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
21pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);
22impl_array_newtype!(Signature, u8, constants::SCHNORR_SIGNATURE_SIZE);
23impl_pretty_debug!(Signature);
24
25#[cfg(feature = "serde")]
26impl serde::Serialize for Signature {
27 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
28 if s.is_human_readable() {
29 s.collect_str(self)
30 } else {
31 s.serialize_bytes(&self[..])
32 }
33 }
34}
35
36#[cfg(feature = "serde")]
37impl<'de> serde::Deserialize<'de> for Signature {
38 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
39 if d.is_human_readable() {
40 d.deserialize_str(super::serde_util::FromStrVisitor::new(
41 "a hex string representing 64 byte schnorr signature",
42 ))
43 } else {
44 d.deserialize_bytes(super::serde_util::BytesVisitor::new(
45 "raw 64 bytes schnorr signature",
46 Signature::from_slice,
47 ))
48 }
49 }
50}
51
52impl fmt::LowerHex for Signature {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 for ch in &self.0[..] {
55 write!(f, "{:02x}", ch)?;
56 }
57 Ok(())
58 }
59}
60
61impl fmt::Display for Signature {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
63}
64
65impl str::FromStr for Signature {
66 type Err = Error;
67 fn from_str(s: &str) -> Result<Signature, Error> {
68 let mut res = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
69 match from_hex(s, &mut res) {
70 Ok(constants::SCHNORR_SIGNATURE_SIZE) =>
71 Signature::from_slice(&res[0..constants::SCHNORR_SIGNATURE_SIZE]),
72 _ => Err(Error::InvalidSignature),
73 }
74 }
75}
76
77impl Signature {
78 #[inline]
80 pub fn from_slice(data: &[u8]) -> Result<Signature, Error> {
81 match data.len() {
82 constants::SCHNORR_SIGNATURE_SIZE => {
83 let mut ret = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
84 ret[..].copy_from_slice(data);
85 Ok(Signature(ret))
86 }
87 _ => Err(Error::InvalidSignature),
88 }
89 }
90
91 #[inline]
93 pub fn serialize(&self) -> [u8; constants::SCHNORR_SIGNATURE_SIZE] { self.0 }
94
95 #[inline]
97 #[cfg(feature = "global-context")]
98 pub fn verify(&self, msg: &Message, pk: &XOnlyPublicKey) -> Result<(), Error> {
99 SECP256K1.verify_schnorr(self, msg, pk)
100 }
101}
102
103impl<C: Signing> Secp256k1<C> {
104 fn sign_schnorr_helper(
105 &self,
106 msg: &Message,
107 keypair: &Keypair,
108 nonce_data: *const ffi::types::c_uchar,
109 ) -> Signature {
110 unsafe {
111 let mut sig = [0u8; constants::SCHNORR_SIGNATURE_SIZE];
112 assert_eq!(
113 1,
114 ffi::secp256k1_schnorrsig_sign(
115 self.ctx.as_ptr(),
116 sig.as_mut_c_ptr(),
117 msg.as_c_ptr(),
118 keypair.as_c_ptr(),
119 nonce_data,
120 )
121 );
122
123 Signature(sig)
124 }
125 }
126
127 #[cfg(feature = "rand-std")]
130 pub fn sign_schnorr(&self, msg: &Message, keypair: &Keypair) -> Signature {
131 self.sign_schnorr_with_rng(msg, keypair, &mut rand::thread_rng())
132 }
133
134 pub fn sign_schnorr_no_aux_rand(&self, msg: &Message, keypair: &Keypair) -> Signature {
136 self.sign_schnorr_helper(msg, keypair, ptr::null())
137 }
138
139 pub fn sign_schnorr_with_aux_rand(
141 &self,
142 msg: &Message,
143 keypair: &Keypair,
144 aux_rand: &[u8; 32],
145 ) -> Signature {
146 self.sign_schnorr_helper(msg, keypair, aux_rand.as_c_ptr() as *const ffi::types::c_uchar)
147 }
148
149 #[cfg(feature = "rand")]
152 pub fn sign_schnorr_with_rng<R: Rng + CryptoRng>(
153 &self,
154 msg: &Message,
155 keypair: &Keypair,
156 rng: &mut R,
157 ) -> Signature {
158 let mut aux = [0u8; 32];
159 rng.fill_bytes(&mut aux);
160 self.sign_schnorr_helper(msg, keypair, aux.as_c_ptr() as *const ffi::types::c_uchar)
161 }
162}
163
164impl<C: Verification> Secp256k1<C> {
165 pub fn verify_schnorr(
167 &self,
168 sig: &Signature,
169 msg: &Message,
170 pubkey: &XOnlyPublicKey,
171 ) -> Result<(), Error> {
172 unsafe {
173 let ret = ffi::secp256k1_schnorrsig_verify(
174 self.ctx.as_ptr(),
175 sig.as_c_ptr(),
176 msg.as_c_ptr(),
177 32,
178 pubkey.as_c_ptr(),
179 );
180
181 if ret == 1 {
182 Ok(())
183 } else {
184 Err(Error::InvalidSignature)
185 }
186 }
187 }
188}
189
190#[cfg(test)]
191#[allow(unused_imports)]
192mod tests {
193 use core::str::FromStr;
194
195 #[cfg(feature = "rand-std")]
196 use rand::rngs::ThreadRng;
197 #[cfg(target_arch = "wasm32")]
198 use wasm_bindgen_test::wasm_bindgen_test as test;
199
200 use super::*;
201 use crate::schnorr::{Keypair, Signature, XOnlyPublicKey};
202 use crate::Error::InvalidPublicKey;
203 use crate::{constants, from_hex, Message, Secp256k1, SecretKey};
204
205 #[cfg(all(not(secp256k1_fuzz), feature = "alloc"))]
206 macro_rules! hex_32 {
207 ($hex:expr) => {{
208 let mut result = [0u8; 32];
209 from_hex($hex, &mut result).expect("valid hex string");
210 result
211 }};
212 }
213
214 #[test]
215 #[cfg(feature = "rand-std")]
216 fn schnorr_sign_with_aux_rand_verify() {
217 sign_helper(|secp, msg, seckey, rng| {
218 let aux_rand = crate::random_32_bytes(rng);
219 secp.sign_schnorr_with_aux_rand(msg, seckey, &aux_rand)
220 })
221 }
222
223 #[test]
224 #[cfg(feature = "rand-std")]
225 fn schnor_sign_with_rng_verify() {
226 sign_helper(|secp, msg, seckey, rng| secp.sign_schnorr_with_rng(msg, seckey, rng))
227 }
228
229 #[test]
230 #[cfg(feature = "rand-std")]
231 fn schnorr_sign_verify() { sign_helper(|secp, msg, seckey, _| secp.sign_schnorr(msg, seckey)) }
232
233 #[test]
234 #[cfg(feature = "rand-std")]
235 fn schnorr_sign_no_aux_rand_verify() {
236 sign_helper(|secp, msg, seckey, _| secp.sign_schnorr_no_aux_rand(msg, seckey))
237 }
238
239 #[cfg(feature = "rand-std")]
240 fn sign_helper(
241 sign: fn(&Secp256k1<crate::All>, &Message, &Keypair, &mut ThreadRng) -> Signature,
242 ) {
243 let secp = Secp256k1::new();
244
245 let mut rng = rand::thread_rng();
246 let kp = Keypair::new(&secp, &mut rng);
247 let (pk, _parity) = kp.x_only_public_key();
248
249 for _ in 0..100 {
250 let msg = crate::random_32_bytes(&mut rand::thread_rng());
251 let msg = Message::from_digest_slice(&msg).unwrap();
252
253 let sig = sign(&secp, &msg, &kp, &mut rng);
254
255 assert!(secp.verify_schnorr(&sig, &msg, &pk).is_ok());
256 }
257 }
258
259 #[test]
260 #[cfg(feature = "alloc")]
261 #[cfg(not(secp256k1_fuzz))] fn schnorr_sign() {
263 let secp = Secp256k1::new();
264
265 let hex_msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
266 let msg = Message::from_digest_slice(&hex_msg).unwrap();
267 let sk = Keypair::from_seckey_str(
268 &secp,
269 "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF",
270 )
271 .unwrap();
272 let aux_rand: [u8; 32] =
273 hex_32!("02CCE08E913F22A36C5648D6405A2C7C50106E7AA2F1649E381C7F09D16B80AB");
274 let expected_sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
275
276 let sig = secp.sign_schnorr_with_aux_rand(&msg, &sk, &aux_rand);
277
278 assert_eq!(expected_sig, sig);
279 }
280
281 #[test]
282 #[cfg(not(secp256k1_fuzz))] #[cfg(feature = "alloc")]
284 fn schnorr_verify() {
285 let secp = Secp256k1::new();
286
287 let hex_msg = hex_32!("E48441762FB75010B2AA31A512B62B4148AA3FB08EB0765D76B252559064A614");
288 let msg = Message::from_digest_slice(&hex_msg).unwrap();
289 let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
290 let pubkey = XOnlyPublicKey::from_str(
291 "B33CC9EDC096D0A83416964BD3C6247B8FECD256E4EFA7870D2C854BDEB33390",
292 )
293 .unwrap();
294
295 assert!(secp.verify_schnorr(&sig, &msg, &pubkey).is_ok());
296 }
297
298 #[test]
299 fn test_serialize() {
300 let sig = Signature::from_str("6470FD1303DDA4FDA717B9837153C24A6EAB377183FC438F939E0ED2B620E9EE5077C4A8B8DCA28963D772A94F5F0DDF598E1C47C137F91933274C7C3EDADCE8").unwrap();
301 let sig_bytes = sig.serialize();
302 let bytes = [
303 100, 112, 253, 19, 3, 221, 164, 253, 167, 23, 185, 131, 113, 83, 194, 74, 110, 171, 55,
304 113, 131, 252, 67, 143, 147, 158, 14, 210, 182, 32, 233, 238, 80, 119, 196, 168, 184,
305 220, 162, 137, 99, 215, 114, 169, 79, 95, 13, 223, 89, 142, 28, 71, 193, 55, 249, 25,
306 51, 39, 76, 124, 62, 218, 220, 232,
307 ];
308 assert_eq!(sig_bytes, bytes);
309 }
310
311 #[test]
312 fn test_pubkey_from_slice() {
313 assert_eq!(XOnlyPublicKey::from_slice(&[]), Err(InvalidPublicKey));
314 assert_eq!(XOnlyPublicKey::from_slice(&[1, 2, 3]), Err(InvalidPublicKey));
315 let pk = XOnlyPublicKey::from_slice(&[
316 0xB3, 0x3C, 0xC9, 0xED, 0xC0, 0x96, 0xD0, 0xA8, 0x34, 0x16, 0x96, 0x4B, 0xD3, 0xC6,
317 0x24, 0x7B, 0x8F, 0xEC, 0xD2, 0x56, 0xE4, 0xEF, 0xA7, 0x87, 0x0D, 0x2C, 0x85, 0x4B,
318 0xDE, 0xB3, 0x33, 0x90,
319 ]);
320 assert!(pk.is_ok());
321 }
322
323 #[test]
324 #[cfg(feature = "rand-std")]
325 fn test_pubkey_serialize_roundtrip() {
326 let secp = Secp256k1::new();
327 let kp = Keypair::new(&secp, &mut rand::thread_rng());
328 let (pk, _parity) = kp.x_only_public_key();
329
330 let ser = pk.serialize();
331 let pubkey2 = XOnlyPublicKey::from_slice(&ser).unwrap();
332 assert_eq!(pk, pubkey2);
333 }
334
335 #[test]
336 #[cfg(feature = "alloc")]
337 fn test_xonly_key_extraction() {
338 let secp = Secp256k1::new();
339 let sk_str = "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF";
340 let keypair = Keypair::from_seckey_str(&secp, sk_str).unwrap();
341 let sk = SecretKey::from_keypair(&keypair);
342 assert_eq!(SecretKey::from_str(sk_str).unwrap(), sk);
343 let pk = crate::key::PublicKey::from_keypair(&keypair);
344 assert_eq!(crate::key::PublicKey::from_secret_key(&secp, &sk), pk);
345 let (xpk, _parity) = keypair.x_only_public_key();
346 assert_eq!(XOnlyPublicKey::from(pk), xpk);
347 }
348
349 #[test]
350 fn test_pubkey_from_bad_slice() {
351 assert_eq!(
353 XOnlyPublicKey::from_slice(&[0; constants::SCHNORR_PUBLIC_KEY_SIZE - 1]),
354 Err(InvalidPublicKey)
355 );
356 assert_eq!(
357 XOnlyPublicKey::from_slice(&[0; constants::SCHNORR_PUBLIC_KEY_SIZE + 1]),
358 Err(InvalidPublicKey)
359 );
360
361 assert_eq!(
363 XOnlyPublicKey::from_slice(&[0xff; constants::SCHNORR_PUBLIC_KEY_SIZE]),
364 Err(InvalidPublicKey)
365 );
366 #[cfg(not(secp256k1_fuzz))]
369 assert_eq!(
370 XOnlyPublicKey::from_slice(&[0x55; constants::SCHNORR_PUBLIC_KEY_SIZE]),
371 Err(InvalidPublicKey)
372 );
373 assert_eq!(XOnlyPublicKey::from_slice(&[]), Err(InvalidPublicKey));
374 }
375
376 #[test]
377 #[cfg(feature = "std")]
378 fn test_pubkey_display_output() {
379 #[cfg(not(secp256k1_fuzz))]
380 let pk = {
381 let secp = Secp256k1::new();
382 static SK_BYTES: [u8; 32] = [
383 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
384 0x06, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63,
385 0x63, 0x63, 0x63, 0x63,
386 ];
387
388 let kp = Keypair::from_seckey_slice(&secp, &SK_BYTES).expect("sk");
389
390 let (pk, _parity) = kp.x_only_public_key();
393 pk
394 };
395 #[cfg(secp256k1_fuzz)]
396 let pk = XOnlyPublicKey::from_slice(&[
397 0x18, 0x84, 0x57, 0x81, 0xf6, 0x31, 0xc4, 0x8f, 0x1c, 0x97, 0x09, 0xe2, 0x30, 0x92,
398 0x06, 0x7d, 0x06, 0x83, 0x7f, 0x30, 0xaa, 0x0c, 0xd0, 0x54, 0x4a, 0xc8, 0x87, 0xfe,
399 0x91, 0xdd, 0xd1, 0x66,
400 ])
401 .expect("pk");
402
403 assert_eq!(
404 pk.to_string(),
405 "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
406 );
407 assert_eq!(
408 XOnlyPublicKey::from_str(
409 "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166"
410 )
411 .unwrap(),
412 pk
413 );
414
415 assert!(XOnlyPublicKey::from_str(
416 "00000000000000000000000000000000000000000000000000000000000000000"
417 )
418 .is_err());
419 assert!(XOnlyPublicKey::from_str(
420 "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16601"
421 )
422 .is_err());
423 assert!(XOnlyPublicKey::from_str(
424 "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd16"
425 )
426 .is_err());
427 assert!(XOnlyPublicKey::from_str(
428 "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1"
429 )
430 .is_err());
431 assert!(XOnlyPublicKey::from_str(
432 "xx18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd1"
433 )
434 .is_err());
435
436 let long_str: String = "a".repeat(1024 * 1024);
437 assert!(XOnlyPublicKey::from_str(&long_str).is_err());
438 }
439
440 #[test]
441 #[cfg(not(secp256k1_fuzz))]
444 #[cfg(all(feature = "rand", feature = "alloc"))]
445 fn test_pubkey_serialize() {
446 use rand::rngs::mock::StepRng;
447 let secp = Secp256k1::new();
448 let kp = Keypair::new(&secp, &mut StepRng::new(1, 1));
449 let (pk, _parity) = kp.x_only_public_key();
450 assert_eq!(
451 &pk.serialize()[..],
452 &[
453 124, 121, 49, 14, 253, 63, 197, 50, 39, 194, 107, 17, 193, 219, 108, 154, 126, 9,
454 181, 248, 2, 12, 149, 233, 198, 71, 149, 134, 250, 184, 154, 229
455 ][..]
456 );
457 }
458
459 #[cfg(not(secp256k1_fuzz))] #[test]
461 #[cfg(all(feature = "serde", feature = "alloc"))]
462 fn test_serde() {
463 use serde_test::{assert_tokens, Configure, Token};
464
465 let s = Secp256k1::new();
466
467 let msg = Message::from_digest_slice(&[1; 32]).unwrap();
468 let keypair = Keypair::from_seckey_slice(&s, &[2; 32]).unwrap();
469 let aux = [3u8; 32];
470 let sig = s.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
471 static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [
472 0x14, 0xd0, 0xbf, 0x1a, 0x89, 0x53, 0x50, 0x6f, 0xb4, 0x60, 0xf5, 0x8b, 0xe1, 0x41,
473 0xaf, 0x76, 0x7f, 0xd1, 0x12, 0x53, 0x5f, 0xb3, 0x92, 0x2e, 0xf2, 0x17, 0x30, 0x8e,
474 0x2c, 0x26, 0x70, 0x6f, 0x1e, 0xeb, 0x43, 0x2b, 0x3d, 0xba, 0x9a, 0x01, 0x08, 0x2f,
475 0x9e, 0x4d, 0x4e, 0xf5, 0x67, 0x8a, 0xd0, 0xd9, 0xd5, 0x32, 0xc0, 0xdf, 0xa9, 0x07,
476 0xb5, 0x68, 0x72, 0x2d, 0x0b, 0x01, 0x19, 0xba,
477 ];
478 static SIG_STR: &str = "\
479 14d0bf1a8953506fb460f58be141af767fd112535fb3922ef217308e2c26706f1eeb432b3dba9a01082f9e4d4ef5678ad0d9d532c0dfa907b568722d0b0119ba\
480 ";
481
482 static PK_BYTES: [u8; 32] = [
483 24, 132, 87, 129, 246, 49, 196, 143, 28, 151, 9, 226, 48, 146, 6, 125, 6, 131, 127, 48,
484 170, 12, 208, 84, 74, 200, 135, 254, 145, 221, 209, 102,
485 ];
486 static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
487 let pk = XOnlyPublicKey::from_slice(&PK_BYTES).unwrap();
488
489 assert_tokens(&sig.compact(), &[Token::BorrowedBytes(&SIG_BYTES[..])]);
490 assert_tokens(&sig.compact(), &[Token::Bytes(&SIG_BYTES[..])]);
491 assert_tokens(&sig.compact(), &[Token::ByteBuf(&SIG_BYTES[..])]);
492
493 assert_tokens(&sig.readable(), &[Token::BorrowedStr(SIG_STR)]);
494 assert_tokens(&sig.readable(), &[Token::Str(SIG_STR)]);
495 assert_tokens(&sig.readable(), &[Token::String(SIG_STR)]);
496
497 #[rustfmt::skip]
498 assert_tokens(&pk.compact(), &[
499 Token::Tuple{ len: 32 },
500 Token::U8(24), Token::U8(132), Token::U8(87), Token::U8(129), Token::U8(246), Token::U8(49), Token::U8(196), Token::U8(143),
501 Token::U8(28), Token::U8(151), Token::U8(9), Token::U8(226), Token::U8(48), Token::U8(146), Token::U8(6), Token::U8(125),
502 Token::U8(6), Token::U8(131), Token::U8(127), Token::U8(48), Token::U8(170), Token::U8(12), Token::U8(208), Token::U8(84),
503 Token::U8(74), Token::U8(200), Token::U8(135), Token::U8(254), Token::U8(145), Token::U8(221), Token::U8(209), Token::U8(102),
504 Token::TupleEnd
505 ]);
506
507 assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]);
508 assert_tokens(&pk.readable(), &[Token::Str(PK_STR)]);
509 assert_tokens(&pk.readable(), &[Token::String(PK_STR)]);
510 }
511}