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