secp256k1/
key.rs

1// Bitcoin secp256k1 bindings
2// Written in 2014 by
3//   Dawid Ciężarkiewicz
4//   Andrew Poelstra
5//
6// To the extent possible under law, the author(s) have dedicated all
7// copyright and related and neighboring rights to this software to
8// the public domain worldwide. This software is distributed without
9// any warranty.
10//
11// You should have received a copy of the CC0 Public Domain Dedication
12// along with this software.
13// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
14//
15
16//! # Public and secret keys
17
18use arrayvec::ArrayVec;
19use rand::Rng;
20
21use super::{Secp256k1, ContextFlag};
22use super::Error::{self, IncapableContext, InvalidPublicKey, InvalidSecretKey};
23use constants;
24use ffi;
25
26/// Secret 256-bit key used as `x` in an ECDSA signature
27#[repr(C)]
28pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
29impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
30impl_pretty_debug!(SecretKey);
31
32impl From<[u8; constants::SECRET_KEY_SIZE]> for SecretKey {
33	fn from(raw: [u8; constants::SECRET_KEY_SIZE]) -> Self {
34		SecretKey(raw)
35	}
36}
37
38/// The number 1 encoded as a secret key
39/// Deprecated; `static` is not what I want; use `ONE_KEY` instead
40pub static ONE: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
41                                       0, 0, 0, 0, 0, 0, 0, 0,
42                                       0, 0, 0, 0, 0, 0, 0, 0,
43                                       0, 0, 0, 0, 0, 0, 0, 1]);
44
45/// The number 0 encoded as a secret key
46pub const ZERO_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
47                                           0, 0, 0, 0, 0, 0, 0, 0,
48                                           0, 0, 0, 0, 0, 0, 0, 0,
49                                           0, 0, 0, 0, 0, 0, 0, 0]);
50
51/// The number 1 encoded as a secret key
52pub const ONE_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
53                                          0, 0, 0, 0, 0, 0, 0, 0,
54                                          0, 0, 0, 0, 0, 0, 0, 0,
55                                          0, 0, 0, 0, 0, 0, 0, 1]);
56
57/// The number -1 encoded as a secret key
58pub const MINUS_ONE_KEY: SecretKey = SecretKey([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
59                                                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
60                                                0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
61                                                0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40]);
62
63/// A Secp256k1 public key, used for verification of signatures
64#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
65pub struct PublicKey(ffi::PublicKey);
66
67fn random_32_bytes<R: Rng>(rng: &mut R) -> [u8; 32] {
68    let mut ret = [0u8; 32];
69    rng.fill_bytes(&mut ret);
70    ret
71}
72
73impl SecretKey {
74    /// Creates a new random secret key
75    #[inline]
76    pub fn new<R: Rng>(secp: &Secp256k1, rng: &mut R) -> SecretKey {
77        let mut data = random_32_bytes(rng);
78        unsafe {
79            while ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 {
80                data = random_32_bytes(rng);
81            }
82        }
83        SecretKey(data)
84    }
85
86    /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
87    #[inline]
88    pub fn from_slice(secp: &Secp256k1, data: &[u8])
89                        -> Result<SecretKey, Error> {
90        match data.len() {
91            constants::SECRET_KEY_SIZE => {
92                let mut ret = [0; constants::SECRET_KEY_SIZE];
93                unsafe {
94                    if ffi::secp256k1_ec_seckey_verify(secp.ctx, data.as_ptr()) == 0 {
95                        return Err(InvalidSecretKey);
96                    }
97                }
98                ret[..].copy_from_slice(data);
99                Ok(SecretKey(ret))
100            }
101            _ => Err(InvalidSecretKey)
102        }
103    }
104
105    #[inline]
106    /// Adds one secret key to another, modulo the curve order
107    pub fn add_assign(&mut self, secp: &Secp256k1, other: &SecretKey)
108                     -> Result<(), Error> {
109        unsafe {
110            if ffi::secp256k1_ec_privkey_tweak_add(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 {
111                Err(InvalidSecretKey)
112            } else {
113                Ok(())
114            }
115        }
116    }
117
118    #[inline]
119    /// Multiplies one secret key by another, modulo the curve order
120    pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey)
121                     -> Result<(), Error> {
122        unsafe {
123            if ffi::secp256k1_ec_privkey_tweak_mul(secp.ctx, self.as_mut_ptr(), other.as_ptr()) != 1 {
124                Err(InvalidSecretKey)
125            } else {
126                Ok(())
127            }
128        }
129    }
130
131    #[inline]
132    /// Inverts (1 / self) this secret key.
133    pub fn inv_assign(&mut self, secp: &Secp256k1) -> Result<(), Error> {
134        let original = self.clone();
135        unsafe {
136            if ffi::secp256k1_ec_privkey_inverse(secp.ctx, self.as_mut_ptr(), original.as_ptr()) != 1 {
137                Err(InvalidSecretKey)
138            } else {
139                Ok(())
140            }
141        }
142    }
143}
144
145impl PublicKey {
146    /// Creates a new zeroed out public key
147    #[inline]
148    pub fn new() -> PublicKey {
149        PublicKey(ffi::PublicKey::new())
150    }
151
152    /// Determines whether a pubkey is valid
153    #[inline]
154    pub fn is_valid(&self) -> bool {
155        // The only invalid pubkey the API should be able to create is
156        // the zero one.
157        self.0[..].iter().any(|&x| x != 0)
158    }
159
160    /// Obtains a raw pointer suitable for use with FFI functions
161    #[inline]
162    pub fn as_ptr(&self) -> *const ffi::PublicKey {
163        &self.0 as *const _
164    }
165
166    /// Creates a new public key from a secret key.
167    #[inline]
168    pub fn from_secret_key(secp: &Secp256k1,
169                           sk: &SecretKey)
170                           -> Result<PublicKey, Error> {
171        if secp.caps == ContextFlag::VerifyOnly || secp.caps == ContextFlag::None {
172            return Err(IncapableContext);
173        }
174        let mut pk = unsafe { ffi::PublicKey::blank() };
175        unsafe {
176            // We can assume the return value because it's not possible to construct
177            // an invalid `SecretKey` without transmute trickery or something
178            let res = ffi::secp256k1_ec_pubkey_create(secp.ctx, &mut pk, sk.as_ptr());
179            debug_assert_eq!(res, 1);
180        }
181        Ok(PublicKey(pk))
182    }
183
184    /// Creates a public key directly from a slice
185    #[inline]
186    pub fn from_slice(secp: &Secp256k1, data: &[u8])
187                      -> Result<PublicKey, Error> {
188
189        let mut pk = unsafe { ffi::PublicKey::blank() };
190        unsafe {
191            if ffi::secp256k1_ec_pubkey_parse(secp.ctx, &mut pk, data.as_ptr(),
192                                              data.len() as usize) == 1 {
193                Ok(PublicKey(pk))
194            } else {
195                Err(InvalidPublicKey)
196            }
197        }
198    }
199
200    #[inline]
201    /// Serialize the key as a byte-encoded pair of values. In compressed form
202    /// the y-coordinate is represented by only a single bit, as x determines
203    /// it up to one bit.
204    pub fn serialize_vec(&self, secp: &Secp256k1, compressed: bool) -> ArrayVec<[u8; constants::PUBLIC_KEY_SIZE]> {
205        let mut ret = ArrayVec::new();
206
207        unsafe {
208            let mut ret_len = constants::PUBLIC_KEY_SIZE as usize;
209            let compressed = if compressed { ffi::SECP256K1_SER_COMPRESSED } else { ffi::SECP256K1_SER_UNCOMPRESSED };
210            let err = ffi::secp256k1_ec_pubkey_serialize(secp.ctx, ret.as_ptr(),
211                                                         &mut ret_len, self.as_ptr(),
212                                                         compressed);
213            debug_assert_eq!(err, 1);
214            ret.set_len(ret_len as usize);
215        }
216        ret
217    }
218
219    #[inline]
220    /// Adds the pk corresponding to `other` to the pk `self` in place
221    pub fn add_exp_assign(&mut self, secp: &Secp256k1, other: &SecretKey)
222                         -> Result<(), Error> {
223        if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None {
224            return Err(IncapableContext);
225        }
226        unsafe {
227            if ffi::secp256k1_ec_pubkey_tweak_add(secp.ctx, &mut self.0 as *mut _,
228                                                  other.as_ptr()) == 1 {
229                Ok(())
230            } else {
231                Err(InvalidSecretKey)
232            }
233        }
234    }
235
236    #[inline]
237    /// Adds another point on the curve in place
238    pub fn add_assign(&mut self, secp: &Secp256k1, other: &PublicKey) -> Result<(), Error> {
239        let mut public = ffi::PublicKey::new();
240        let res = unsafe {
241            if ffi::secp256k1_ec_pubkey_combine(
242                secp.ctx,
243                &mut public as *mut _,
244                [other.as_ptr(), self.as_ptr()].as_ptr(),
245                2) == 1
246            {
247                Ok(())
248            } else {
249                Err(InvalidSecretKey)
250            }
251        };
252        if res.is_ok() { self.0 = public }
253        res
254    }
255
256    #[inline]
257    /// Multiplies this point by `secret` scalar
258    pub fn mul_assign(&mut self, secp: &Secp256k1, other: &SecretKey) -> Result<(), Error> {
259        if secp.caps == ContextFlag::SignOnly || secp.caps == ContextFlag::None {
260            return Err(IncapableContext);
261        }
262        unsafe {
263            if ffi::secp256k1_ec_pubkey_tweak_mul(secp.ctx, &mut self.0 as *mut _,
264                                                  other.as_ptr()) == 1 {
265                Ok(())
266            } else {
267                Err(InvalidSecretKey)
268            }
269        }
270    }
271}
272
273/// Creates a new public key from a FFI public key
274impl From<ffi::PublicKey> for PublicKey {
275    #[inline]
276    fn from(pk: ffi::PublicKey) -> PublicKey {
277        PublicKey(pk)
278    }
279}
280
281#[cfg(test)]
282mod test {
283    use super::super::{Secp256k1, ContextFlag};
284    use super::super::Error::{InvalidPublicKey, InvalidSecretKey, IncapableContext};
285    use super::{PublicKey, SecretKey};
286    use super::super::constants;
287
288    use rand::{Rng, thread_rng};
289
290    #[test]
291    fn skey_from_slice() {
292        let s = Secp256k1::new();
293        let sk = SecretKey::from_slice(&s, &[1; 31]);
294        assert_eq!(sk, Err(InvalidSecretKey));
295
296        let sk = SecretKey::from_slice(&s, &[1; 32]);
297        assert!(sk.is_ok());
298    }
299
300    #[test]
301    fn pubkey_from_slice() {
302        let s = Secp256k1::new();
303        assert_eq!(PublicKey::from_slice(&s, &[]), Err(InvalidPublicKey));
304        assert_eq!(PublicKey::from_slice(&s, &[1, 2, 3]), Err(InvalidPublicKey));
305
306        let uncompressed = PublicKey::from_slice(&s, &[4, 54, 57, 149, 239, 162, 148, 175, 246, 254, 239, 75, 154, 152, 10, 82, 234, 224, 85, 220, 40, 100, 57, 121, 30, 162, 94, 156, 135, 67, 74, 49, 179, 57, 236, 53, 162, 124, 149, 144, 168, 77, 74, 30, 72, 211, 229, 110, 111, 55, 96, 193, 86, 227, 183, 152, 195, 155, 51, 247, 123, 113, 60, 228, 188]);
307        assert!(uncompressed.is_ok());
308
309        let compressed = PublicKey::from_slice(&s, &[3, 23, 183, 225, 206, 31, 159, 148, 195, 42, 67, 115, 146, 41, 248, 140, 11, 3, 51, 41, 111, 180, 110, 143, 114, 134, 88, 73, 198, 174, 52, 184, 78]);
310        assert!(compressed.is_ok());
311    }
312
313    #[test]
314    fn keypair_slice_round_trip() {
315        let s = Secp256k1::new();
316
317        let (sk1, pk1) = s.generate_keypair(&mut thread_rng()).unwrap();
318        assert_eq!(SecretKey::from_slice(&s, &sk1[..]), Ok(sk1));
319        assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, true)[..]), Ok(pk1));
320        assert_eq!(PublicKey::from_slice(&s, &pk1.serialize_vec(&s, false)[..]), Ok(pk1));
321    }
322
323    #[test]
324    fn invalid_secret_key() {
325        let s = Secp256k1::new();
326        // Zero
327        assert_eq!(SecretKey::from_slice(&s, &[0; 32]), Err(InvalidSecretKey));
328        // -1
329        assert_eq!(SecretKey::from_slice(&s, &[0xff; 32]), Err(InvalidSecretKey));
330        // Top of range
331        assert!(SecretKey::from_slice(&s,
332                                      &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
333                                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
334                                        0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
335                                        0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40]).is_ok());
336        // One past top of range
337        assert!(SecretKey::from_slice(&s,
338                                      &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
339                                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
340                                        0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
341                                        0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41]).is_err());
342    }
343
344    #[test]
345    fn test_pubkey_from_slice_bad_context() {
346        let s = Secp256k1::without_caps();
347        let sk = SecretKey::new(&s, &mut thread_rng());
348        assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext));
349
350        let s = Secp256k1::with_caps(ContextFlag::VerifyOnly);
351        assert_eq!(PublicKey::from_secret_key(&s, &sk), Err(IncapableContext));
352
353        let s = Secp256k1::with_caps(ContextFlag::SignOnly);
354        assert!(PublicKey::from_secret_key(&s, &sk).is_ok());
355
356        let s = Secp256k1::with_caps(ContextFlag::Full);
357        assert!(PublicKey::from_secret_key(&s, &sk).is_ok());
358    }
359
360    #[test]
361    fn test_add_exp_bad_context() {
362        let s = Secp256k1::with_caps(ContextFlag::Full);
363        let (sk, mut pk) = s.generate_keypair(&mut thread_rng()).unwrap();
364
365        assert!(pk.add_exp_assign(&s, &sk).is_ok());
366
367        let s = Secp256k1::with_caps(ContextFlag::VerifyOnly);
368        assert!(pk.add_exp_assign(&s, &sk).is_ok());
369
370        let s = Secp256k1::with_caps(ContextFlag::SignOnly);
371        assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext));
372
373        let s = Secp256k1::with_caps(ContextFlag::None);
374        assert_eq!(pk.add_exp_assign(&s, &sk), Err(IncapableContext));
375    }
376
377    #[test]
378    fn test_out_of_range() {
379
380        struct BadRng(u8);
381        impl Rng for BadRng {
382            fn next_u32(&mut self) -> u32 { unimplemented!() }
383            // This will set a secret key to a little over the
384            // group order, then decrement with repeated calls
385            // until it returns a valid key
386            fn fill_bytes(&mut self, data: &mut [u8]) {
387                let group_order: [u8; 32] = [
388                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
389                    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
390                    0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b,
391                    0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41];
392                assert_eq!(data.len(), 32);
393                data.copy_from_slice(&group_order[..]);
394                data[31] = self.0;
395                self.0 -= 1;
396            }
397        }
398
399        let s = Secp256k1::new();
400        s.generate_keypair(&mut BadRng(0xff)).unwrap();
401    }
402
403    #[test]
404    fn test_pubkey_from_bad_slice() {
405        let s = Secp256k1::new();
406        // Bad sizes
407        assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE - 1]),
408                   Err(InvalidPublicKey));
409        assert_eq!(PublicKey::from_slice(&s, &[0; constants::COMPRESSED_PUBLIC_KEY_SIZE + 1]),
410                   Err(InvalidPublicKey));
411        assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE - 1]),
412                   Err(InvalidPublicKey));
413        assert_eq!(PublicKey::from_slice(&s, &[0; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE + 1]),
414                   Err(InvalidPublicKey));
415
416        // Bad parse
417        assert_eq!(PublicKey::from_slice(&s, &[0xff; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
418                   Err(InvalidPublicKey));
419        assert_eq!(PublicKey::from_slice(&s, &[0x55; constants::COMPRESSED_PUBLIC_KEY_SIZE]),
420                   Err(InvalidPublicKey));
421    }
422
423    #[test]
424    fn test_debug_output() {
425        struct DumbRng(u32);
426        impl Rng for DumbRng {
427            fn next_u32(&mut self) -> u32 {
428                self.0 = self.0.wrapping_add(1);
429                self.0
430            }
431        }
432
433        let s = Secp256k1::new();
434        let (sk, _) = s.generate_keypair(&mut DumbRng(0)).unwrap();
435
436        assert_eq!(&format!("{:?}", sk),
437                   "SecretKey(0200000001000000040000000300000006000000050000000800000007000000)");
438    }
439
440    #[test]
441    fn test_pubkey_serialize() {
442        struct DumbRng(u32);
443        impl Rng for DumbRng {
444            fn next_u32(&mut self) -> u32 {
445                self.0 = self.0.wrapping_add(1);
446                self.0
447            }
448        }
449
450        let s = Secp256k1::new();
451        let (_, pk1) = s.generate_keypair(&mut DumbRng(0)).unwrap();
452        assert_eq!(&pk1.serialize_vec(&s, false)[..],
453                   &[4, 149, 16, 196, 140, 38, 92, 239, 179, 65, 59, 224, 230, 183, 91, 238, 240, 46, 186, 252, 175, 102, 52, 249, 98, 178, 123, 72, 50, 171, 196, 254, 236, 1, 189, 143, 242, 227, 16, 87, 247, 183, 162, 68, 237, 140, 92, 205, 151, 129, 166, 58, 111, 96, 123, 64, 180, 147, 51, 12, 209, 89, 236, 213, 206][..]);
454        assert_eq!(&pk1.serialize_vec(&s, true)[..],
455                   &[2, 149, 16, 196, 140, 38, 92, 239, 179, 65, 59, 224, 230, 183, 91, 238, 240, 46, 186, 252, 175, 102, 52, 249, 98, 178, 123, 72, 50, 171, 196, 254, 236][..]);
456    }
457
458    #[test]
459    fn test_addition() {
460        let s = Secp256k1::new();
461
462        let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap();
463        let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap();
464
465        assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1);
466        assert!(sk1.add_assign(&s, &sk2).is_ok());
467        assert!(pk1.add_exp_assign(&s, &sk2).is_ok());
468        assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1);
469
470        assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2);
471        assert!(sk2.add_assign(&s, &sk1).is_ok());
472        assert!(pk2.add_exp_assign(&s, &sk1).is_ok());
473        assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2);
474    }
475
476    #[test]
477    fn test_multiplication() {
478        let s = Secp256k1::new();
479
480        let (mut sk1, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap();
481        let (mut sk2, mut pk2) = s.generate_keypair(&mut thread_rng()).unwrap();
482
483        assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1);
484        assert!(sk1.mul_assign(&s, &sk2).is_ok());
485        assert!(pk1.mul_assign(&s, &sk2).is_ok());
486        assert_eq!(PublicKey::from_secret_key(&s, &sk1).unwrap(), pk1);
487
488        assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2);
489        assert!(sk2.mul_assign(&s, &sk1).is_ok());
490        assert!(pk2.mul_assign(&s, &sk1).is_ok());
491        assert_eq!(PublicKey::from_secret_key(&s, &sk2).unwrap(), pk2);
492    }
493
494    #[test]
495    fn pubkey_hash() {
496        use std::collections::hash_map::DefaultHasher;
497        use std::hash::{Hash, Hasher};
498        use std::collections::HashSet;
499
500        fn hash<T: Hash>(t: &T) -> u64 {
501            let mut s = DefaultHasher::new();
502            t.hash(&mut s);
503            s.finish()
504        }
505
506        let s = Secp256k1::new();
507        let mut set = HashSet::new();
508        const COUNT : usize = 1024;
509        let count = (0..COUNT).map(|_| {
510            let (_, pk) = s.generate_keypair(&mut thread_rng()).unwrap();
511            let hash = hash(&pk);
512            assert!(!set.contains(&hash));
513            set.insert(hash);
514        }).count();
515        assert_eq!(count, COUNT);
516    }
517
518    #[test]
519    fn pubkey_add() {
520        let s = Secp256k1::new();
521        let (_, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap();
522        let (_, pk2) = s.generate_keypair(&mut thread_rng()).unwrap();
523
524        let result = pk1.add_assign(&s, &pk2);
525
526        assert!(result.is_ok());
527    }
528
529    #[test]
530    fn pubkey_mul() {
531        let s = Secp256k1::new();
532        let (_, mut pk1) = s.generate_keypair(&mut thread_rng()).unwrap();
533        let (sk2, _) = s.generate_keypair(&mut thread_rng()).unwrap();
534
535        let result = pk1.mul_assign(&s, &sk2);
536
537        assert!(result.is_ok());
538    }
539
540    #[test]
541    fn skey_mul() {
542        let s = Secp256k1::new();
543        let (mut sk1, _) = s.generate_keypair(&mut thread_rng()).unwrap();
544        let (sk2, _) = s.generate_keypair(&mut thread_rng()).unwrap();
545
546        let result = sk1.mul_assign(&s, &sk2);
547
548        assert!(result.is_ok());
549    }
550
551    #[test]
552    fn skey_inv() {
553        let s = Secp256k1::new();
554        let (mut sk, _) = s.generate_keypair(&mut thread_rng()).unwrap();
555
556        let result = sk.inv_assign(&s);
557
558        assert!(result.is_ok());
559    }
560}
561
562