1use 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#[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 #[inline]
76 pub fn from_byte_array(sig: [u8; constants::SCHNORR_SIGNATURE_SIZE]) -> Self { Self(sig) }
77
78 #[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 #[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 #[inline]
98 pub fn to_byte_array(self) -> [u8; constants::SCHNORR_SIGNATURE_SIZE] { self.0 }
99
100 #[inline]
102 pub fn as_byte_array(&self) -> &[u8; constants::SCHNORR_SIGNATURE_SIZE] { &self.0 }
103
104 #[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#[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
143pub fn sign_no_aux_rand(msg: &[u8], keypair: &Keypair) -> Signature {
145 sign_helper(msg, keypair, ptr::null())
146}
147
148pub 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#[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
162pub 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 #[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 #[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 #[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 #[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 #[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"))] 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))] 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))] #[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 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 assert_eq!(
372 XOnlyPublicKey::from_slice(&[0xff; constants::SCHNORR_PUBLIC_KEY_SIZE]),
373 Err(InvalidPublicKey)
374 );
375 #[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 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 #[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))] #[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))] 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}