1#![deny(
6 unused_import_braces,
7 unused_imports,
8 unused_comparisons,
9 unused_must_use,
10 unused_variables,
11 non_shorthand_field_patterns,
12 unreachable_code,
13 unused_parens
14)]
15#![cfg_attr(not(feature = "std"), no_std)]
16
17pub use libsecp256k1_core::*;
18
19use arrayref::{array_mut_ref, array_ref};
20use core::convert::TryFrom;
21use digest::{generic_array::GenericArray, Digest};
22use rand::Rng;
23
24#[cfg(feature = "std")]
25use core::fmt;
26#[cfg(feature = "hmac")]
27use hmac_drbg::HmacDRBG;
28#[cfg(feature = "std")]
29use serde::{de, ser::Serializer, Deserialize, Serialize};
30#[cfg(feature = "hmac")]
31use sha2::Sha256;
32#[cfg(feature = "hmac")]
33use typenum::U32;
34
35use crate::{
36 curve::{Affine, ECMultContext, ECMultGenContext, Field, Jacobian, Scalar},
37 util::{Decoder, SignatureArray},
38};
39
40#[cfg(feature = "lazy-static-context")]
41lazy_static::lazy_static! {
42 pub static ref ECMULT_CONTEXT: Box<ECMultContext> = ECMultContext::new_boxed();
44
45 pub static ref ECMULT_GEN_CONTEXT: Box<ECMultGenContext> = ECMultGenContext::new_boxed();
47}
48
49#[cfg(all(feature = "static-context", not(feature = "lazy-static-context")))]
50pub static ECMULT_CONTEXT: ECMultContext =
53 unsafe { ECMultContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const.rs"))) };
54
55#[cfg(all(feature = "static-context", not(feature = "lazy-static-context")))]
56pub static ECMULT_GEN_CONTEXT: ECMultGenContext =
59 unsafe { ECMultGenContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const_gen.rs"))) };
60
61#[derive(Debug, Clone, Copy, Eq, PartialEq)]
62pub struct PublicKey(Affine);
64
65#[derive(Debug, Clone, Copy, Eq, PartialEq)]
66pub struct SecretKey(Scalar);
68
69#[derive(Debug, Clone, Copy, Eq, PartialEq)]
70pub struct Signature {
72 pub r: Scalar,
73 pub s: Scalar,
74}
75
76#[derive(Debug, Clone, Copy, Eq, PartialEq)]
77pub struct RecoveryId(u8);
79
80#[derive(Debug, Clone, Copy, Eq, PartialEq)]
81pub struct Message(pub Scalar);
83
84#[derive(Debug, Clone, Eq, PartialEq)]
85pub struct SharedSecret<D: Digest>(GenericArray<u8, D::OutputSize>);
87
88impl<D> Copy for SharedSecret<D>
89where
90 D: Copy + Digest,
91 GenericArray<u8, D::OutputSize>: Copy,
92{
93}
94
95pub enum PublicKeyFormat {
97 Compressed,
99 Full,
101 Raw,
103}
104
105impl PublicKey {
106 pub fn from_secret_key_with_context(
107 seckey: &SecretKey,
108 context: &ECMultGenContext,
109 ) -> PublicKey {
110 let mut pj = Jacobian::default();
111 context.ecmult_gen(&mut pj, &seckey.0);
112 let mut p = Affine::default();
113 p.set_gej(&pj);
114 PublicKey(p)
115 }
116
117 #[cfg(any(feature = "static-context", feature = "lazy-static-context"))]
118 pub fn from_secret_key(seckey: &SecretKey) -> PublicKey {
119 Self::from_secret_key_with_context(seckey, &ECMULT_GEN_CONTEXT)
120 }
121
122 pub fn parse_slice(p: &[u8], format: Option<PublicKeyFormat>) -> Result<PublicKey, Error> {
123 let format = match (p.len(), format) {
124 (util::FULL_PUBLIC_KEY_SIZE, None)
125 | (util::FULL_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Full)) => PublicKeyFormat::Full,
126 (util::COMPRESSED_PUBLIC_KEY_SIZE, None)
127 | (util::COMPRESSED_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Compressed)) => {
128 PublicKeyFormat::Compressed
129 }
130 (util::RAW_PUBLIC_KEY_SIZE, None)
131 | (util::RAW_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Raw)) => PublicKeyFormat::Raw,
132 _ => return Err(Error::InvalidInputLength),
133 };
134
135 match format {
136 PublicKeyFormat::Full => {
137 let mut a = [0; util::FULL_PUBLIC_KEY_SIZE];
138 a.copy_from_slice(p);
139 Self::parse(&a)
140 }
141 PublicKeyFormat::Raw => {
142 use util::TAG_PUBKEY_FULL;
143
144 let mut a = [0; util::FULL_PUBLIC_KEY_SIZE];
145 a[0] = TAG_PUBKEY_FULL;
146 a[1..].copy_from_slice(p);
147 Self::parse(&a)
148 }
149 PublicKeyFormat::Compressed => {
150 let mut a = [0; util::COMPRESSED_PUBLIC_KEY_SIZE];
151 a.copy_from_slice(p);
152 Self::parse_compressed(&a)
153 }
154 }
155 }
156
157 pub fn parse(p: &[u8; util::FULL_PUBLIC_KEY_SIZE]) -> Result<PublicKey, Error> {
158 use util::{TAG_PUBKEY_FULL, TAG_PUBKEY_HYBRID_EVEN, TAG_PUBKEY_HYBRID_ODD};
159
160 if !(p[0] == TAG_PUBKEY_FULL
161 || p[0] == TAG_PUBKEY_HYBRID_EVEN
162 || p[0] == TAG_PUBKEY_HYBRID_ODD)
163 {
164 return Err(Error::InvalidPublicKey);
165 }
166 let mut x = Field::default();
167 let mut y = Field::default();
168 if !x.set_b32(array_ref!(p, 1, 32)) {
169 return Err(Error::InvalidPublicKey);
170 }
171 if !y.set_b32(array_ref!(p, 33, 32)) {
172 return Err(Error::InvalidPublicKey);
173 }
174 let mut elem = Affine::default();
175 elem.set_xy(&x, &y);
176 if (p[0] == TAG_PUBKEY_HYBRID_EVEN || p[0] == TAG_PUBKEY_HYBRID_ODD)
177 && (y.is_odd() != (p[0] == TAG_PUBKEY_HYBRID_ODD))
178 {
179 return Err(Error::InvalidPublicKey);
180 }
181 if elem.is_infinity() {
182 return Err(Error::InvalidPublicKey);
183 }
184 if elem.is_valid_var() {
185 Ok(PublicKey(elem))
186 } else {
187 Err(Error::InvalidPublicKey)
188 }
189 }
190
191 pub fn parse_compressed(
192 p: &[u8; util::COMPRESSED_PUBLIC_KEY_SIZE],
193 ) -> Result<PublicKey, Error> {
194 use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD};
195
196 if !(p[0] == TAG_PUBKEY_EVEN || p[0] == TAG_PUBKEY_ODD) {
197 return Err(Error::InvalidPublicKey);
198 }
199 let mut x = Field::default();
200 if !x.set_b32(array_ref!(p, 1, 32)) {
201 return Err(Error::InvalidPublicKey);
202 }
203 let mut elem = Affine::default();
204 elem.set_xo_var(&x, p[0] == TAG_PUBKEY_ODD);
205 if elem.is_infinity() {
206 return Err(Error::InvalidPublicKey);
207 }
208 if elem.is_valid_var() {
209 Ok(PublicKey(elem))
210 } else {
211 Err(Error::InvalidPublicKey)
212 }
213 }
214
215 pub fn serialize(&self) -> [u8; util::FULL_PUBLIC_KEY_SIZE] {
216 use util::TAG_PUBKEY_FULL;
217
218 debug_assert!(!self.0.is_infinity());
219
220 let mut ret = [0u8; 65];
221 let mut elem = self.0;
222
223 elem.x.normalize_var();
224 elem.y.normalize_var();
225 elem.x.fill_b32(array_mut_ref!(ret, 1, 32));
226 elem.y.fill_b32(array_mut_ref!(ret, 33, 32));
227 ret[0] = TAG_PUBKEY_FULL;
228
229 ret
230 }
231
232 pub fn serialize_compressed(&self) -> [u8; util::COMPRESSED_PUBLIC_KEY_SIZE] {
233 use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD};
234
235 debug_assert!(!self.0.is_infinity());
236
237 let mut ret = [0u8; 33];
238 let mut elem = self.0;
239
240 elem.x.normalize_var();
241 elem.y.normalize_var();
242 elem.x.fill_b32(array_mut_ref!(ret, 1, 32));
243 ret[0] = if elem.y.is_odd() {
244 TAG_PUBKEY_ODD
245 } else {
246 TAG_PUBKEY_EVEN
247 };
248
249 ret
250 }
251
252 pub fn tweak_add_assign_with_context(
253 &mut self,
254 tweak: &SecretKey,
255 context: &ECMultContext,
256 ) -> Result<(), Error> {
257 let mut r = Jacobian::default();
258 let a = Jacobian::from_ge(&self.0);
259 let one = Scalar::from_int(1);
260 context.ecmult(&mut r, &a, &one, &tweak.0);
261
262 if r.is_infinity() {
263 return Err(Error::TweakOutOfRange);
264 }
265
266 self.0.set_gej(&r);
267 Ok(())
268 }
269
270 #[cfg(any(feature = "static-context", feature = "lazy-static-context"))]
271 pub fn tweak_add_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
272 self.tweak_add_assign_with_context(tweak, &ECMULT_CONTEXT)
273 }
274
275 pub fn tweak_mul_assign_with_context(
276 &mut self,
277 tweak: &SecretKey,
278 context: &ECMultContext,
279 ) -> Result<(), Error> {
280 if tweak.0.is_zero() {
281 return Err(Error::TweakOutOfRange);
282 }
283
284 let mut r = Jacobian::default();
285 let zero = Scalar::from_int(0);
286 let pt = Jacobian::from_ge(&self.0);
287 context.ecmult(&mut r, &pt, &tweak.0, &zero);
288
289 self.0.set_gej(&r);
290 Ok(())
291 }
292
293 #[cfg(any(feature = "static-context", feature = "lazy-static-context"))]
294 pub fn tweak_mul_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
295 self.tweak_mul_assign_with_context(tweak, &ECMULT_CONTEXT)
296 }
297
298 pub fn combine(keys: &[PublicKey]) -> Result<Self, Error> {
299 let mut qj = Jacobian::default();
300 qj.set_infinity();
301
302 for key in keys {
303 qj = qj.add_ge(&key.0);
304 }
305
306 if qj.is_infinity() {
307 return Err(Error::InvalidPublicKey);
308 }
309
310 let q = Affine::from_gej(&qj);
311 Ok(PublicKey(q))
312 }
313}
314
315impl Into<Affine> for PublicKey {
316 fn into(self) -> Affine {
317 self.0
318 }
319}
320
321impl TryFrom<Affine> for PublicKey {
322 type Error = Error;
323
324 fn try_from(value: Affine) -> Result<Self, Self::Error> {
325 if value.is_infinity() || !value.is_valid_var() {
326 Err(Error::InvalidAffine)
327 } else {
328 Ok(PublicKey(value))
329 }
330 }
331}
332
333#[cfg(feature = "std")]
334impl Serialize for PublicKey {
335 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
336 where
337 S: Serializer,
338 {
339 if serializer.is_human_readable() {
340 serializer.serialize_str(&base64::encode(&self.serialize()[..]))
341 } else {
342 serializer.serialize_bytes(&self.serialize())
343 }
344 }
345}
346
347#[cfg(feature = "std")]
348struct PublicKeyStrVisitor;
349
350#[cfg(feature = "std")]
351impl<'de> de::Visitor<'de> for PublicKeyStrVisitor {
352 type Value = PublicKey;
353
354 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
355 formatter
356 .write_str("a bytestring of either 33 (compressed), 64 (raw), or 65 bytes in length")
357 }
358
359 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
360 where
361 E: de::Error,
362 {
363 let value: &[u8] = &base64::decode(value).map_err(|e| E::custom(e))?;
364 let key_format = match value.len() {
365 33 => PublicKeyFormat::Compressed,
366 64 => PublicKeyFormat::Raw,
367 65 => PublicKeyFormat::Full,
368 _ => return Err(E::custom(Error::InvalidInputLength)),
369 };
370 PublicKey::parse_slice(value, Some(key_format))
371 .map_err(|_e| E::custom(Error::InvalidPublicKey))
372 }
373}
374
375#[cfg(feature = "std")]
376struct PublicKeyBytesVisitor;
377
378#[cfg(feature = "std")]
379impl<'de> de::Visitor<'de> for PublicKeyBytesVisitor {
380 type Value = PublicKey;
381
382 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
383 formatter.write_str(
384 "a byte slice that is either 33 (compressed), 64 (raw), or 65 bytes in length",
385 )
386 }
387
388 fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
389 where
390 E: de::Error,
391 {
392 PublicKey::parse_slice(value, None).map_err(|_e| E::custom(Error::InvalidPublicKey))
393 }
394}
395
396#[cfg(feature = "std")]
397impl<'de> Deserialize<'de> for PublicKey {
398 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
399 where
400 D: de::Deserializer<'de>,
401 {
402 if deserializer.is_human_readable() {
403 deserializer.deserialize_str(PublicKeyStrVisitor)
404 } else {
405 deserializer.deserialize_bytes(PublicKeyBytesVisitor)
406 }
407 }
408}
409
410impl SecretKey {
411 pub fn parse(p: &[u8; util::SECRET_KEY_SIZE]) -> Result<SecretKey, Error> {
412 let mut elem = Scalar::default();
413 if !bool::from(elem.set_b32(p)) {
414 Self::try_from(elem)
415 } else {
416 Err(Error::InvalidSecretKey)
417 }
418 }
419
420 pub fn parse_slice(p: &[u8]) -> Result<SecretKey, Error> {
421 if p.len() != util::SECRET_KEY_SIZE {
422 return Err(Error::InvalidInputLength);
423 }
424
425 let mut a = [0; 32];
426 a.copy_from_slice(p);
427 Self::parse(&a)
428 }
429
430 pub fn random<R: Rng>(rng: &mut R) -> SecretKey {
431 loop {
432 let mut ret = [0u8; util::SECRET_KEY_SIZE];
433 rng.fill_bytes(&mut ret);
434
435 if let Ok(key) = Self::parse(&ret) {
436 return key;
437 }
438 }
439 }
440
441 pub fn serialize(&self) -> [u8; util::SECRET_KEY_SIZE] {
442 self.0.b32()
443 }
444
445 pub fn tweak_add_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
446 let v = self.0 + tweak.0;
447 if v.is_zero() {
448 return Err(Error::TweakOutOfRange);
449 }
450 self.0 = v;
451 Ok(())
452 }
453
454 pub fn tweak_mul_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
455 if tweak.0.is_zero() {
456 return Err(Error::TweakOutOfRange);
457 }
458
459 self.0 *= &tweak.0;
460 Ok(())
461 }
462
463 pub fn inv(&self) -> Self {
464 SecretKey(self.0.inv())
465 }
466}
467
468impl Default for SecretKey {
469 fn default() -> SecretKey {
470 let mut elem = Scalar::default();
471 let overflowed = bool::from(elem.set_b32(&[
472 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
474 0x00, 0x00, 0x00, 0x01,
475 ]));
476 debug_assert!(!overflowed);
477 debug_assert!(!elem.is_zero());
478 SecretKey(elem)
479 }
480}
481
482impl Into<Scalar> for SecretKey {
483 fn into(self) -> Scalar {
484 self.0
485 }
486}
487
488impl TryFrom<Scalar> for SecretKey {
489 type Error = Error;
490
491 fn try_from(scalar: Scalar) -> Result<Self, Error> {
492 if scalar.is_zero() {
493 Err(Error::InvalidSecretKey)
494 } else {
495 Ok(Self(scalar))
496 }
497 }
498}
499
500impl core::fmt::LowerHex for SecretKey {
501 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
502 let scalar = self.0;
503
504 write!(f, "{:x}", scalar)
505 }
506}
507
508impl Signature {
509 pub fn parse_overflowing(p: &[u8; util::SIGNATURE_SIZE]) -> Signature {
520 let mut r = Scalar::default();
521 let mut s = Scalar::default();
522
523 let _ = r.set_b32(array_ref!(p, 0, 32));
525 let _ = s.set_b32(array_ref!(p, 32, 32));
526
527 Signature { r, s }
528 }
529
530 pub fn parse_standard(p: &[u8; util::SIGNATURE_SIZE]) -> Result<Signature, Error> {
533 let mut r = Scalar::default();
534 let mut s = Scalar::default();
535
536 let overflowed_r = r.set_b32(array_ref!(p, 0, 32));
538 let overflowed_s = s.set_b32(array_ref!(p, 32, 32));
539
540 if bool::from(overflowed_r | overflowed_s) {
541 return Err(Error::InvalidSignature);
542 }
543
544 Ok(Signature { r, s })
545 }
546
547 pub fn parse_overflowing_slice(p: &[u8]) -> Result<Signature, Error> {
553 if p.len() != util::SIGNATURE_SIZE {
554 return Err(Error::InvalidInputLength);
555 }
556
557 let mut a = [0; util::SIGNATURE_SIZE];
558 a.copy_from_slice(p);
559 Ok(Self::parse_overflowing(&a))
560 }
561
562 pub fn parse_standard_slice(p: &[u8]) -> Result<Signature, Error> {
564 if p.len() != util::SIGNATURE_SIZE {
565 return Err(Error::InvalidInputLength);
566 }
567
568 let mut a = [0; util::SIGNATURE_SIZE];
569 a.copy_from_slice(p);
570 Ok(Self::parse_standard(&a)?)
571 }
572
573 pub fn parse_der(p: &[u8]) -> Result<Signature, Error> {
575 let mut decoder = Decoder::new(p);
576
577 decoder.read_constructed_sequence()?;
578 let rlen = decoder.read_len()?;
579
580 if rlen != decoder.remaining_len() {
581 return Err(Error::InvalidSignature);
582 }
583
584 let r = decoder.read_integer()?;
585 let s = decoder.read_integer()?;
586
587 if decoder.remaining_len() != 0 {
588 return Err(Error::InvalidSignature);
589 }
590
591 Ok(Signature { r, s })
592 }
593
594 pub fn parse_der_lax(p: &[u8]) -> Result<Signature, Error> {
599 let mut decoder = Decoder::new(p);
600
601 decoder.read_constructed_sequence()?;
602 decoder.read_seq_len_lax()?;
603
604 let r = decoder.read_integer_lax()?;
605 let s = decoder.read_integer_lax()?;
606
607 Ok(Signature { r, s })
608 }
609
610 pub fn normalize_s(&mut self) {
628 if self.s.is_high() {
629 self.s = -self.s;
630 }
631 }
632
633 pub fn serialize(&self) -> [u8; util::SIGNATURE_SIZE] {
636 let mut ret = [0u8; 64];
637 self.r.fill_b32(array_mut_ref!(ret, 0, 32));
638 self.s.fill_b32(array_mut_ref!(ret, 32, 32));
639 ret
640 }
641
642 pub fn serialize_der(&self) -> SignatureArray {
645 fn fill_scalar_with_leading_zero(scalar: &Scalar) -> [u8; 33] {
646 let mut ret = [0u8; 33];
647 scalar.fill_b32(array_mut_ref!(ret, 1, 32));
648 ret
649 }
650
651 let r_full = fill_scalar_with_leading_zero(&self.r);
652 let s_full = fill_scalar_with_leading_zero(&self.s);
653
654 fn integer_slice(full: &[u8; 33]) -> &[u8] {
655 let mut len = 33;
656 while len > 1 && full[full.len() - len] == 0 && full[full.len() - len + 1] < 0x80 {
657 len -= 1;
658 }
659 &full[(full.len() - len)..]
660 }
661
662 let r = integer_slice(&r_full);
663 let s = integer_slice(&s_full);
664
665 let mut ret = SignatureArray::new(6 + r.len() + s.len());
666 {
667 let l = ret.as_mut();
668 l[0] = 0x30;
669 l[1] = 4 + r.len() as u8 + s.len() as u8;
670 l[2] = 0x02;
671 l[3] = r.len() as u8;
672 l[4..(4 + r.len())].copy_from_slice(r);
673 l[4 + r.len()] = 0x02;
674 l[5 + r.len()] = s.len() as u8;
675 l[(6 + r.len())..(6 + r.len() + s.len())].copy_from_slice(s);
676 }
677
678 ret
679 }
680}
681
682impl Message {
683 pub fn parse(p: &[u8; util::MESSAGE_SIZE]) -> Message {
684 let mut m = Scalar::default();
685
686 let _ = m.set_b32(p);
688
689 Message(m)
690 }
691
692 pub fn parse_slice(p: &[u8]) -> Result<Message, Error> {
693 if p.len() != util::MESSAGE_SIZE {
694 return Err(Error::InvalidInputLength);
695 }
696
697 let mut a = [0; util::MESSAGE_SIZE];
698 a.copy_from_slice(p);
699 Ok(Self::parse(&a))
700 }
701
702 pub fn serialize(&self) -> [u8; util::MESSAGE_SIZE] {
703 self.0.b32()
704 }
705}
706
707impl RecoveryId {
708 pub fn parse(p: u8) -> Result<RecoveryId, Error> {
710 if p < 4 {
711 Ok(RecoveryId(p))
712 } else {
713 Err(Error::InvalidRecoveryId)
714 }
715 }
716
717 pub fn parse_rpc(p: u8) -> Result<RecoveryId, Error> {
719 if p >= 27 && p < 27 + 4 {
720 RecoveryId::parse(p - 27)
721 } else {
722 Err(Error::InvalidRecoveryId)
723 }
724 }
725
726 pub fn serialize(&self) -> u8 {
727 self.0
728 }
729}
730
731impl Into<u8> for RecoveryId {
732 fn into(self) -> u8 {
733 self.0
734 }
735}
736
737impl Into<i32> for RecoveryId {
738 fn into(self) -> i32 {
739 self.0 as i32
740 }
741}
742
743impl<D: Digest + Default> SharedSecret<D> {
744 pub fn new_with_context(
745 pubkey: &PublicKey,
746 seckey: &SecretKey,
747 context: &ECMultContext,
748 ) -> Result<SharedSecret<D>, Error> {
749 let inner = match context.ecdh_raw::<D>(&pubkey.0, &seckey.0) {
750 Some(val) => val,
751 None => return Err(Error::InvalidSecretKey),
752 };
753
754 Ok(SharedSecret(inner))
755 }
756
757 #[cfg(any(feature = "static-context", feature = "lazy-static-context"))]
758 pub fn new(pubkey: &PublicKey, seckey: &SecretKey) -> Result<SharedSecret<D>, Error> {
759 Self::new_with_context(pubkey, seckey, &ECMULT_CONTEXT)
760 }
761}
762
763impl<D: Digest> AsRef<[u8]> for SharedSecret<D> {
764 fn as_ref(&self) -> &[u8] {
765 &self.0.as_ref()
766 }
767}
768
769pub fn verify_with_context(
771 message: &Message,
772 signature: &Signature,
773 pubkey: &PublicKey,
774 context: &ECMultContext,
775) -> bool {
776 context.verify_raw(&signature.r, &signature.s, &pubkey.0, &message.0)
777}
778
779#[cfg(any(feature = "static-context", feature = "lazy-static-context"))]
780pub fn verify(message: &Message, signature: &Signature, pubkey: &PublicKey) -> bool {
782 verify_with_context(message, signature, pubkey, &ECMULT_CONTEXT)
783}
784
785pub fn recover_with_context(
787 message: &Message,
788 signature: &Signature,
789 recovery_id: &RecoveryId,
790 context: &ECMultContext,
791) -> Result<PublicKey, Error> {
792 context
793 .recover_raw(&signature.r, &signature.s, recovery_id.0, &message.0)
794 .map(PublicKey)
795}
796
797#[cfg(any(feature = "static-context", feature = "lazy-static-context"))]
798pub fn recover(
800 message: &Message,
801 signature: &Signature,
802 recovery_id: &RecoveryId,
803) -> Result<PublicKey, Error> {
804 recover_with_context(message, signature, recovery_id, &ECMULT_CONTEXT)
805}
806
807#[cfg(feature = "hmac")]
808pub fn sign_with_context(
810 message: &Message,
811 seckey: &SecretKey,
812 context: &ECMultGenContext,
813) -> (Signature, RecoveryId) {
814 let seckey_b32 = seckey.0.b32();
815 let message_b32 = message.0.b32();
816
817 let mut drbg = HmacDRBG::<Sha256>::new(&seckey_b32, &message_b32, &[]);
818 let mut nonce = Scalar::default();
819 let mut overflow;
820
821 let result;
822 loop {
823 let generated = drbg.generate::<U32>(None);
824 overflow = bool::from(nonce.set_b32(array_ref!(generated, 0, 32)));
825
826 if !overflow && !nonce.is_zero() {
827 if let Ok(val) = context.sign_raw(&seckey.0, &message.0, &nonce) {
828 result = val;
829 break;
830 }
831 }
832 }
833
834 #[allow(unused_assignments)]
835 {
836 nonce = Scalar::default();
837 }
838 let (sigr, sigs, recid) = result;
839
840 (Signature { r: sigr, s: sigs }, RecoveryId(recid))
841}
842
843#[cfg(all(
844 feature = "hmac",
845 any(feature = "static-context", feature = "lazy-static-context")
846))]
847pub fn sign(message: &Message, seckey: &SecretKey) -> (Signature, RecoveryId) {
849 sign_with_context(message, seckey, &ECMULT_GEN_CONTEXT)
850}
851
852#[cfg(test)]
853mod tests {
854 use crate::SecretKey;
855 use hex_literal::hex;
856
857 #[test]
858 fn secret_key_inverse_is_sane() {
859 let sk = SecretKey::parse(&[1; 32]).unwrap();
860 let inv = sk.inv();
861 let invinv = inv.inv();
862 assert_eq!(sk, invinv);
863 assert_eq!(
865 inv,
866 SecretKey::parse(&hex!(
867 "1536f1d756d1abf83aaf173bc5ee3fc487c93010f18624d80bd6d4038fadd59e"
868 ))
869 .unwrap()
870 )
871 }
872}