tiny_ec/
lib.rs

1//! Pure Rust implementation of the secp256k1 curve and fast ECDSA
2//! signatures. The secp256k1 curve is used extensively in Bitcoin and
3//! Ethereum-alike cryptocurrencies.
4
5#![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
17use curve::Field;
18pub use tiny_ec_core::*;
19
20use arrayref::{array_mut_ref, array_ref};
21use core::convert::TryFrom;
22
23use crate::curve::{Affine, ECMultContext, ECMultGenContext, Jacobian, Scalar};
24#[cfg(feature = "std")]
25#[cfg(all(feature = "static-context"))]
26/// A static ECMult context.
27// Correct `pre_g` values are fed into `ECMultContext::new_from_raw`, generated by build script.
28pub static ECMULT_CONTEXT: ECMultContext =
29    unsafe { ECMultContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const.rs"))) };
30
31#[cfg(all(feature = "static-context"))]
32/// A static ECMultGen context.
33// Correct `prec` values are fed into `ECMultGenContext::new_from_raw`, generated by build script.
34pub static ECMULT_GEN_CONTEXT: ECMultGenContext =
35    unsafe { ECMultGenContext::new_from_raw(include!(concat!(env!("OUT_DIR"), "/const_gen.rs"))) };
36
37use serde::{Deserialize, Serialize};
38
39#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
40/// Public key on a secp256k1 curve.
41pub struct PublicKey(Affine);
42
43#[derive(Debug, Clone, Copy, Eq, PartialEq)]
44/// Secret key (256-bit) on a secp256k1 curve.
45pub struct SecretKey(Scalar);
46
47#[derive(Debug, Clone, Copy, Eq, PartialEq)]
48/// An ECDSA signature.
49pub struct Signature {
50    pub r: Scalar,
51    pub s: Scalar,
52}
53
54#[derive(Debug, Clone, Copy, Eq, PartialEq)]
55/// Tag used for public key recovery from signatures.
56pub struct RecoveryId(u8);
57
58#[derive(Debug, Clone, Copy, Eq, PartialEq)]
59/// Hashed message input to an ECDSA signature.
60pub struct Message(pub Scalar);
61
62/// Format for public key parsing.
63pub enum PublicKeyFormat {
64    /// Compressed public key, 33 bytes.
65    Compressed,
66    /// Full length public key, 65 bytes.
67    Full,
68    /// Raw public key, 64 bytes.
69    Raw,
70}
71
72impl PublicKey {
73    pub fn from_secret_key_with_context(
74        seckey: &SecretKey,
75        context: &ECMultGenContext,
76    ) -> PublicKey {
77        let mut pj = Jacobian::default();
78        context.ecmult_gen(&mut pj, &seckey.0);
79        let mut p = Affine::default();
80        p.set_gej(&pj);
81        PublicKey(p)
82    }
83
84    #[cfg(any(feature = "static-context"))]
85    pub fn from_secret_key(seckey: &SecretKey) -> PublicKey {
86        Self::from_secret_key_with_context(seckey, &ECMULT_GEN_CONTEXT)
87    }
88
89    pub fn parse_slice(p: &[u8], format: Option<PublicKeyFormat>) -> Result<PublicKey, Error> {
90        let format = match (p.len(), format) {
91            (util::FULL_PUBLIC_KEY_SIZE, None)
92            | (util::FULL_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Full)) => PublicKeyFormat::Full,
93            (util::COMPRESSED_PUBLIC_KEY_SIZE, None)
94            | (util::COMPRESSED_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Compressed)) => {
95                PublicKeyFormat::Compressed
96            }
97            (util::RAW_PUBLIC_KEY_SIZE, None)
98            | (util::RAW_PUBLIC_KEY_SIZE, Some(PublicKeyFormat::Raw)) => PublicKeyFormat::Raw,
99            _ => return Err(Error::InvalidInputLength),
100        };
101
102        match format {
103            PublicKeyFormat::Full => {
104                let mut a = [0; util::FULL_PUBLIC_KEY_SIZE];
105                a.copy_from_slice(p);
106                Self::parse(&a)
107            }
108            PublicKeyFormat::Raw => {
109                use util::TAG_PUBKEY_FULL;
110
111                let mut a = [0; util::FULL_PUBLIC_KEY_SIZE];
112                a[0] = TAG_PUBKEY_FULL;
113                a[1..].copy_from_slice(p);
114                Self::parse(&a)
115            }
116            PublicKeyFormat::Compressed => {
117                let mut a = [0; util::COMPRESSED_PUBLIC_KEY_SIZE];
118                a.copy_from_slice(p);
119                Self::parse_compressed(&a)
120            }
121        }
122    }
123
124    pub fn parse(p: &[u8; util::FULL_PUBLIC_KEY_SIZE]) -> Result<PublicKey, Error> {
125        use util::{TAG_PUBKEY_FULL, TAG_PUBKEY_HYBRID_EVEN, TAG_PUBKEY_HYBRID_ODD};
126
127        if !(p[0] == TAG_PUBKEY_FULL
128            || p[0] == TAG_PUBKEY_HYBRID_EVEN
129            || p[0] == TAG_PUBKEY_HYBRID_ODD)
130        {
131            return Err(Error::InvalidPublicKey);
132        }
133        let mut x = Field::default();
134        let mut y = Field::default();
135        if !x.set_b32(array_ref!(p, 1, 32)) {
136            return Err(Error::InvalidPublicKey);
137        }
138        if !y.set_b32(array_ref!(p, 33, 32)) {
139            return Err(Error::InvalidPublicKey);
140        }
141        let mut elem = Affine::default();
142        elem.set_xy(&x, &y);
143        if (p[0] == TAG_PUBKEY_HYBRID_EVEN || p[0] == TAG_PUBKEY_HYBRID_ODD)
144            && (y.is_odd() != (p[0] == TAG_PUBKEY_HYBRID_ODD))
145        {
146            return Err(Error::InvalidPublicKey);
147        }
148        if elem.is_infinity() {
149            return Err(Error::InvalidPublicKey);
150        }
151        if elem.is_valid_var() {
152            Ok(PublicKey(elem))
153        } else {
154            Err(Error::InvalidPublicKey)
155        }
156    }
157
158    pub fn parse_compressed(
159        p: &[u8; util::COMPRESSED_PUBLIC_KEY_SIZE],
160    ) -> Result<PublicKey, Error> {
161        use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD};
162
163        if !(p[0] == TAG_PUBKEY_EVEN || p[0] == TAG_PUBKEY_ODD) {
164            return Err(Error::InvalidPublicKey);
165        }
166        let mut x = Field::default();
167        if !x.set_b32(array_ref!(p, 1, 32)) {
168            return Err(Error::InvalidPublicKey);
169        }
170        let mut elem = Affine::default();
171        elem.set_xo_var(&x, p[0] == TAG_PUBKEY_ODD);
172        if elem.is_infinity() {
173            return Err(Error::InvalidPublicKey);
174        }
175        if elem.is_valid_var() {
176            Ok(PublicKey(elem))
177        } else {
178            Err(Error::InvalidPublicKey)
179        }
180    }
181
182    pub fn serialize(&self) -> [u8; util::FULL_PUBLIC_KEY_SIZE] {
183        use util::TAG_PUBKEY_FULL;
184
185        debug_assert!(!self.0.is_infinity());
186
187        let mut ret = [0u8; 65];
188        let mut elem = self.0;
189
190        elem.x.normalize_var();
191        elem.y.normalize_var();
192        elem.x.fill_b32(array_mut_ref!(ret, 1, 32));
193        elem.y.fill_b32(array_mut_ref!(ret, 33, 32));
194        ret[0] = TAG_PUBKEY_FULL;
195
196        ret
197    }
198
199    pub fn serialize_compressed(&self) -> [u8; util::COMPRESSED_PUBLIC_KEY_SIZE] {
200        use util::{TAG_PUBKEY_EVEN, TAG_PUBKEY_ODD};
201
202        debug_assert!(!self.0.is_infinity());
203
204        let mut ret = [0u8; 33];
205        let mut elem = self.0;
206
207        elem.x.normalize_var();
208        elem.y.normalize_var();
209        elem.x.fill_b32(array_mut_ref!(ret, 1, 32));
210        ret[0] = if elem.y.is_odd() {
211            TAG_PUBKEY_ODD
212        } else {
213            TAG_PUBKEY_EVEN
214        };
215
216        ret
217    }
218}
219
220impl Into<Affine> for PublicKey {
221    fn into(self) -> Affine {
222        self.0
223    }
224}
225
226impl TryFrom<Affine> for PublicKey {
227    type Error = Error;
228
229    fn try_from(value: Affine) -> Result<Self, Self::Error> {
230        if value.is_infinity() || !value.is_valid_var() {
231            Err(Error::InvalidAffine)
232        } else {
233            Ok(PublicKey(value))
234        }
235    }
236}
237
238impl SecretKey {
239    pub fn parse(p: &[u8; util::SECRET_KEY_SIZE]) -> Result<SecretKey, Error> {
240        let mut elem = Scalar::default();
241        if !bool::from(elem.set_b32(p)) {
242            Self::try_from(elem)
243        } else {
244            Err(Error::InvalidSecretKey)
245        }
246    }
247
248    pub fn parse_slice(p: &[u8]) -> Result<SecretKey, Error> {
249        if p.len() != util::SECRET_KEY_SIZE {
250            return Err(Error::InvalidInputLength);
251        }
252
253        let mut a = [0; 32];
254        a.copy_from_slice(p);
255        Self::parse(&a)
256    }
257
258    pub fn serialize(&self) -> [u8; util::SECRET_KEY_SIZE] {
259        self.0.b32()
260    }
261
262    pub fn tweak_add_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
263        let v = self.0 + tweak.0;
264        if v.is_zero() {
265            return Err(Error::TweakOutOfRange);
266        }
267        self.0 = v;
268        Ok(())
269    }
270
271    pub fn tweak_mul_assign(&mut self, tweak: &SecretKey) -> Result<(), Error> {
272        if tweak.0.is_zero() {
273            return Err(Error::TweakOutOfRange);
274        }
275
276        self.0 *= &tweak.0;
277        Ok(())
278    }
279
280    pub fn inv(&self) -> Self {
281        SecretKey(self.0.inv())
282    }
283
284    pub fn clear(&mut self) {
285        self.0.clear();
286    }
287
288    pub fn is_zero(&self) -> bool {
289        self.0.is_zero()
290    }
291}
292
293impl Default for SecretKey {
294    fn default() -> SecretKey {
295        let mut elem = Scalar::default();
296        let overflowed = bool::from(elem.set_b32(&[
297            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299            0x00, 0x00, 0x00, 0x01,
300        ]));
301        debug_assert!(!overflowed);
302        debug_assert!(!elem.is_zero());
303        SecretKey(elem)
304    }
305}
306
307impl Into<Scalar> for SecretKey {
308    fn into(self) -> Scalar {
309        self.0
310    }
311}
312
313impl TryFrom<Scalar> for SecretKey {
314    type Error = Error;
315
316    fn try_from(scalar: Scalar) -> Result<Self, Error> {
317        if scalar.is_zero() {
318            Err(Error::InvalidSecretKey)
319        } else {
320            Ok(Self(scalar))
321        }
322    }
323}
324
325impl core::fmt::LowerHex for SecretKey {
326    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
327        let scalar = self.0;
328
329        write!(f, "{:x}", scalar)
330    }
331}
332
333#[cfg(test)]
334mod tests {
335    use crate::SecretKey;
336    use hex_literal::hex;
337
338    #[test]
339    fn secret_key_inverse_is_sane() {
340        let sk = SecretKey::parse(&[1; 32]).unwrap();
341        let inv = sk.inv();
342        let invinv = inv.inv();
343        assert_eq!(sk, invinv);
344        // Check that the inverse of `[1; 32]` is same as rust-secp256k1
345        assert_eq!(
346            inv,
347            SecretKey::parse(&hex!(
348                "1536f1d756d1abf83aaf173bc5ee3fc487c93010f18624d80bd6d4038fadd59e"
349            ))
350            .unwrap()
351        )
352    }
353
354    #[test]
355    fn secret_key_clear_is_correct() {
356        let mut sk = SecretKey::parse(&[1; 32]).unwrap();
357        sk.clear();
358        assert_eq!(sk.is_zero(), true);
359    }
360}