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