secp256kfun/
macros.rs

1/// Scalar expression macro.
2///
3/// Like [`g!`] except that the output of the expression is a [`Scalar`] rather than a [`Point`].
4///
5/// [`Scalar`]: crate::Scalar
6/// [`Point`]: crate::Point
7/// [`g!`]: crate::g
8#[macro_export]
9macro_rules! s {
10    ($($t:tt)*) => {{
11        $crate::arithmetic_macros::gen_s!($crate $($t)*)
12    }}
13}
14
15/// Group operation expression macro.
16///
17/// The `g!` macro lets you express scalar multiplications and group operations conveniently
18/// following standard [order of operations]. This compiles down to operations from the [`op`]
19/// module. Apart from being far more readable, the idea is that `g!` will (or may in the future)
20/// compile to more efficient operations than if you were to manually call the functions from [`op`]
21/// yourself.
22///
23/// Note you can but often don't need to put a `&` in front of the terms in the expression.
24///
25/// # Syntax and operations
26///
27/// The expression supports the following operations:
28///
29/// - `<scalar> * <point>` multiplies the `point` by `scalar`
30/// - `<point> + <point>` adds two points
31/// - `<point> - <point>` subtracts one point from another
32/// - `<scalar_iter> .* <point_iter>` does a [dot product](https://en.wikipedia.org/wiki/Dot_product)
33///    between a list of points and scalars. If one list is shorter than the other then the excess
34///    points or scalars will be multiplied by 0. See [`op::point_scalar_dot_product`].
35///
36/// The terms of the expression can be any variable followed by simple method calls, attribute
37/// access etc. If your term involves more expressions (anything involving specifying types using
38/// `::`) then you can use `{..}` to surround arbitrary expressions. You can also use `(..)` to
39/// group arithmetic expressions to override the usual operation order.
40///
41/// # Examples
42///
43/// Simple scalar multiplication by [`G`] but will work with any [`Point`]
44/// ```
45/// use secp256kfun::{g, Scalar, G};
46/// let x = Scalar::random(&mut rand::thread_rng());
47/// let X = g!(x * G);
48/// ```
49///
50/// A more complicated set of expressions.
51/// ```
52/// # use secp256kfun::{g, Point, Scalar, G};
53/// let x = Scalar::random(&mut rand::thread_rng());
54/// let y = Scalar::random(&mut rand::thread_rng());
55/// let H = Point::random(&mut rand::thread_rng());
56/// let minus = g!(x * G - y * H);
57/// let plus = g!(x * G + y * H);
58/// assert_eq!(g!(plus + minus), g!(2 * x * G)); // this will do 2 * x first
59/// assert_eq!(g!(42 * (G + H)), g!((42 * G + 42 * H)));
60/// ```
61///
62/// You may access attributes and call methods:
63///
64/// ```
65/// # use secp256kfun::{g, Point, Scalar, G};
66/// struct DoMul {
67///     scalar: Scalar,
68///     point: Point,
69/// }
70///
71/// let mul = DoMul {
72///     scalar: Scalar::random(&mut rand::thread_rng()),
73///     point: Point::random(&mut rand::thread_rng()),
74/// };
75///
76/// let result = g!(mul.scalar * mul.point);
77/// assert_eq!(g!(mul.scalar.invert() * result), mul.point);
78/// ```
79///
80/// You can put an arbitrary expressions inside `{...}`
81///
82/// ```
83/// # use secp256kfun::{g, Point, Scalar, G};
84/// let random_point = g!({ Scalar::random(&mut rand::thread_rng()) } * G);
85/// ```
86///
87/// [`double_mul`]: crate::op::double_mul
88/// [`G`]: crate::G
89/// [`Point`]: crate::Point
90/// [`op`]: crate::op
91/// [order of operations]: https://en.wikipedia.org/wiki/Order_of_operations
92/// [`op::point_scalar_dot_product`]: crate::op::point_scalar_dot_product
93#[macro_export]
94macro_rules! g {
95    ($($t:tt)*) => {{
96        $crate::arithmetic_macros::gen_g!($crate $($t)*)
97    }}
98}
99
100/// Macro to make nonce derivation clear and explicit.
101///
102/// Nonce derivation is a sensitive action where mistakes can have catastrophic
103/// consequences. This macro helps to make it clear for which secret the nonce
104/// is being produced and what public input are being used to make sure no two
105/// nonce values are the same (even when using generating the nonce
106/// deterministically). For example, if you are implementing a signature scheme,
107/// then the message you are signing would go into `public` and the secret
108/// signign key would go into `secret`.
109///
110/// This macro compiles to a call to [`NonceGen::begin_derivation`].
111///
112/// # Examples
113///
114/// Derive a nonce deterministically. This example shouldn't be taken
115/// literally. What you actually pass here to `secret` and `public` is dependent
116/// on the cryptographic scheme and is crucial to get right.
117///
118/// ```
119/// use secp256kfun::{Scalar, derive_nonce, Tag, nonce};
120/// use sha2::Sha256;
121/// let secret_scalar = Scalar::random(&mut rand::thread_rng());
122/// let nonce_gen = nonce::Deterministic::<Sha256>::default().tag(b"my-protocol");
123/// let r = derive_nonce!(
124///     nonce_gen => nonce_gen,
125///     secret => &secret_scalar,
126///     public => [b"public-inputs-to-the-algorithm".as_ref()]
127/// );
128/// ```
129/// [`NonceGen::begin_derivation`]: crate::nonce::NonceGen::begin_derivation
130#[macro_export]
131macro_rules! derive_nonce {
132    (
133        nonce_gen => $nonce_gen:expr,
134        secret => $secret:expr,
135        public => [$($public:expr),+]$(,)?
136    ) => {{
137        use $crate::hash::HashAdd;
138        #[allow(unused_imports)]
139        use core::borrow::Borrow;
140        use $crate::nonce::NonceGen;
141        Scalar::from_hash(
142            $nonce_gen.begin_derivation($secret.borrow())$(.add($public))+
143        )
144    }}
145}
146
147/// Macro to derive a rng for producing multiple nonces.
148///
149/// This works like [`derive_nonce`] except that it produces an rng with the output rather than a
150/// scalar.
151///
152/// # Examples
153///
154/// ```
155/// use secp256kfun::{Scalar, derive_nonce_rng, Tag, nonce};
156/// use sha2::Sha256;
157/// let secret_scalar = Scalar::random(&mut rand::thread_rng());
158/// let nonce_gen = nonce::Deterministic::<Sha256>::default().tag(b"my-protocol");
159/// let mut rng = derive_nonce_rng!(
160///     nonce_gen => nonce_gen,
161///     secret => &secret_scalar,
162///     public => [b"public-inputs-to-the-algorithm".as_ref()],
163///     seedable_rng => rand::rngs::StdRng
164/// );
165/// let r1 = Scalar::random(&mut rng);
166/// let r2 = Scalar::random(&mut rng);
167/// ```
168///
169/// [`derive_nonce`]: crate::derive_nonce
170#[macro_export]
171macro_rules! derive_nonce_rng {
172    (
173        nonce_gen => $nonce_gen:expr,
174        secret => $secret:expr,
175        public => [$($public:expr),+],
176        seedable_rng => $rng:ty$(,)?
177    ) => {{
178        use $crate::hash::HashAdd;
179        use core::borrow::Borrow;
180        use $crate::nonce::NonceGen;
181        use $crate::rand_core::SeedableRng;
182        use $crate::digest::FixedOutput;
183
184        let hash = $nonce_gen.begin_derivation($secret.borrow())$(.add($public))+;
185        <$rng>::from_seed(hash.finalize_fixed().into())
186    }}
187}
188
189#[doc(hidden)]
190#[macro_export]
191macro_rules! impl_debug {
192    (fn to_bytes$(<$($tpl:ident  $(: $tcl:ident)?),*>)?($self:ident : &$type_name:ident$(<$($tpr:path),+>)?) -> $($tail:tt)*) => {
193        impl$(<$($tpl $(:$tcl)?),*>)? core::fmt::Debug for $type_name$(<$($tpr),+>)? {
194            /// Formats the type as hex and any markers on the type.
195            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
196                let $self = &self;
197                write!(f, "{}", stringify!($type_name))?;
198                $(
199                    write!(f, "<")?;
200                    $crate::impl_debug!(@recursive_print f, $(core::any::type_name::<$tpr>().rsplit("::").next().unwrap()),*);
201                    write!(f, ">")?;
202                )?
203                    write!(f, "(")?;
204                $crate::impl_debug!(@output f, $self, $($tail)*);
205                write!(f, ")")?;
206                Ok(())
207            }
208        }
209    };
210    (@output $f:ident, $self:ident, Result<$(&)?[u8;$len:literal], &str> $block:block) => {
211        let res: Result<[u8;$len], &str> = $block;
212        match res {
213            Ok(bytes) => {
214                for byte in bytes.iter() {
215                    write!($f, "{:02x}", byte)?
216                }
217            },
218            Err(string) => {
219                write!($f, "{}", string)?
220            }
221        }
222    };
223    (@output $f:ident, $self:ident, $(&)?[u8;$len:literal] $block:block) => {
224        let bytes = $block;
225        for byte in bytes.iter() {
226            write!($f, "{:02x}", byte)?
227        }
228    };
229    (@recursive_print $f:ident, $next:expr, $($tt:tt)+) => {
230        $f.write_str($next)?;
231        $f.write_str(",")?;
232        $crate::impl_debug!(@recursive_print $f, $($tt)+)
233    };
234    (@recursive_print $f:ident, $next:expr) => {
235        $f.write_str($next)?;
236    };
237}
238
239#[doc(hidden)]
240#[macro_export]
241macro_rules! impl_display {
242    (fn to_bytes$(<$($tpl:ident  $(: $tcl:ident)?),*>)?($self:ident : &$type:path) -> $(&)?[u8;$len:literal] $block:block) => {
243
244        impl$(<$($tpl $(:$tcl)?),*>)? core::fmt::Display for $type {
245            /// Displays as hex.
246            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
247                let $self = &self;
248                let bytes = $block;
249                for byte in bytes.iter() {
250                    write!(f, "{:02x}", byte)?
251                }
252                Ok(())
253            }
254        }
255    }
256}
257
258#[macro_export]
259#[doc(hidden)]
260macro_rules! impl_serialize {
261    (fn to_bytes$(<$($tpl:ident  $(: $tcl:ident)?),*>)?($self:ident : &$type:path) -> $(&)?[u8;$len:literal] $block:block) => {
262        #[cfg(feature = "serde")]
263        #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
264        impl$(<$($tpl $(:$tcl)?),*>)? $crate::serde::Serialize for $type {
265            fn serialize<Ser: $crate::serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
266                use $crate::serde::ser::SerializeTuple;
267                let $self = &self;
268                let bytes = $block;
269
270                #[cfg(feature = "alloc")]
271                {
272                    use $crate::hex;
273                    if serializer.is_human_readable() {
274                        return serializer.serialize_str(&hex::encode(&bytes[..]))
275                    }
276                }
277
278                //NOTE: idea taken from https://github.com/dalek-cryptography/curve25519-dalek/pull/297/files
279                let mut tup = serializer.serialize_tuple($len)?;
280                for byte in bytes.iter() {
281                    tup.serialize_element(byte)?;
282                }
283                tup.end()
284            }
285        }
286
287        #[cfg(feature = "bincode")]
288        #[cfg_attr(docsrs, doc(cfg(feature = "bincode")))]
289        impl$(<$($tpl $(:$tcl)?),*>)? $crate::bincode::Encode for $type {
290            fn encode<E: $crate::bincode::enc::Encoder>(&self, encoder: &mut E) -> Result<(), $crate::bincode::error::EncodeError> {
291                use $crate::bincode::enc::write::Writer;
292                let $self = &self;
293                let bytes = $block;
294                encoder.writer().write(bytes.as_ref())
295            }
296        }
297    }
298}
299
300#[macro_export]
301#[doc(hidden)]
302macro_rules! impl_display_serialize {
303    ($($tt:tt)+) => {
304        $crate::impl_serialize!($($tt)+);
305        $crate::impl_display!($($tt)+);
306    };
307}
308
309#[macro_export]
310#[doc(hidden)]
311macro_rules! impl_display_debug_serialize {
312    ($($tt:tt)+) => {
313        $crate::impl_display_serialize!($($tt)+);
314        $crate::impl_debug!($($tt)*);
315    };
316}
317
318/// Implements Display, FromStr, Serialize and Deserialize for something that
319/// can be represented as a fixed length byte array
320#[macro_export]
321#[doc(hidden)]
322macro_rules! impl_fromstr_deserialize {
323        (
324        name => $name:literal,
325        fn from_bytes$(<$($tpl:ident  $(: $tcl:ident)?),*>)?($input:ident : [u8;$len:literal]) ->  Option<$type:path> $block:block
326    ) => {
327        impl$(<$($tpl $(:$tcl)?),*>)? core::str::FromStr for $type  {
328            type Err = $crate::hex::HexError;
329
330            /// Parses the string as hex and interprets tries to convert the
331            /// resulting byte array into the desired value.
332            fn from_str(hex: &str) -> Result<$type , $crate::hex::HexError> {
333                use $crate::hex::hex_val;
334                if hex.len() % 2 == 1 {
335                    Err($crate::hex::HexError::InvalidHex)
336                } else if $len * 2 != hex.len() {
337                    Err($crate::hex::HexError::InvalidLength)
338                } else {
339                    let mut buf = [0u8; $len];
340
341                    for (i, hex_byte) in hex.as_bytes().chunks(2).enumerate() {
342                        buf[i] = hex_val(hex_byte[0])? << 4 | hex_val(hex_byte[1])?
343                    }
344
345                    let $input = buf;
346                    #[allow(clippy::redundant_closure_call)]
347                    let result = (|| -> Option<$type> {$block})();
348                    result.ok_or($crate::hex::HexError::InvalidEncoding)
349                }
350            }
351        }
352
353
354        #[cfg(feature = "serde")]
355        #[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
356        impl<'de, $($($tpl $(: $tcl)?),*)?> $crate::serde::Deserialize<'de> for $type  {
357            fn deserialize<Deser: $crate::serde::Deserializer<'de>>(
358                deserializer: Deser,
359            ) -> Result<$type , Deser::Error> {
360
361                #[cfg(feature = "alloc")]
362                {
363                    if deserializer.is_human_readable() {
364                        #[allow(unused_parens)]
365                        struct HexVisitor$(<$($tpl),*>)?$((core::marker::PhantomData<($($tpl),*)> ))?;
366                        impl<'de, $($($tpl $(: $tcl)?),*)?> $crate::serde::de::Visitor<'de> for HexVisitor$(<$($tpl),*>)? {
367                            type Value = $type ;
368                            fn expecting(
369                                &self,
370                                f: &mut core::fmt::Formatter,
371                            ) -> core::fmt::Result {
372                                write!(f, "a valid {}-byte hex encoded {}", $len, $name)?;
373                                Ok(())
374                            }
375
376                            fn visit_str<E: $crate::serde::de::Error>(self, v: &str) -> Result<$type , E> {
377                                use $crate::hex::HexError::*;
378                                <$type  as core::str::FromStr>::from_str(v).map_err(|e| match e {
379                                    InvalidLength => E::invalid_length(v.len() / 2, &self),
380                                    InvalidEncoding => E::invalid_value($crate::serde::de::Unexpected::Str(v), &self),
381                                    InvalidHex => E::custom("invalid hex")
382                                })
383                            }
384                        }
385
386                        #[allow(unused_parens)]
387                        return deserializer.deserialize_str(HexVisitor$((core::marker::PhantomData::<($($tpl),*)>))?);
388                    }
389                }
390
391                {
392                    #[allow(unused_parens)]
393                    struct BytesVisitor$(<$($tpl),*>)?$((core::marker::PhantomData<($($tpl),*)> ))?;
394
395                    impl<'de, $($($tpl $(: $tcl)?),*)?> $crate::serde::de::Visitor<'de> for BytesVisitor$(<$($tpl),*>)? {
396                        type Value = $type ;
397
398                        fn expecting(
399                            &self,
400                            f: &mut core::fmt::Formatter,
401                        ) -> core::fmt::Result {
402                            write!(f, "a valid {}-byte encoding of a {}", $len, $name)?;
403                            Ok(())
404                        }
405
406                        fn visit_seq<A>(self, mut seq: A) -> Result<$type , A::Error>
407                        where A: $crate::serde::de::SeqAccess<'de> {
408
409                            let mut $input = [0u8; $len];
410                            for i in 0..$len {
411                                $input[i] = seq.next_element()?
412                                               .ok_or_else(|| $crate::serde::de::Error::invalid_length(i, &self))?;
413                            }
414
415                            #[allow(clippy::redundant_closure_call)]
416                            let result = (|| -> Option<$type> { $block }());
417                            result.ok_or($crate::serde::de::Error::custom(format_args!("invalid byte encoding, expected {}", &self as &dyn $crate::serde::de::Expected)))
418                        }
419                    }
420
421                    #[allow(unused_parens)]
422                    deserializer.deserialize_tuple($len, BytesVisitor$((core::marker::PhantomData::<($($tpl),*)>))?)
423                }
424            }
425        }
426
427        #[cfg(feature = "bincode")]
428        #[cfg_attr(docsrs, doc(cfg(feature = "bincode")))]
429        impl$(<$($tpl $(:$tcl)?),*>)? $crate::bincode::de::Decode for $type {
430            fn decode<D: $crate::bincode::de::Decoder>(decoder: &mut D) -> Result<Self, $crate::bincode::error::DecodeError> {
431                use $crate::bincode::de::read::Reader;
432                let mut $input = [0u8; $len];
433                decoder.reader().read(&mut $input)?;
434                #[allow(clippy::redundant_closure_call)]
435                let result = (|| -> Option<$type> { $block }());
436                #[cfg(feature = "alloc")]
437                return result.ok_or($crate::bincode::error::DecodeError::OtherString(format!("Invalid {}-byte encoding of a {}", $len, $name)));
438                #[cfg(not(feature = "alloc"))]
439                return result.ok_or($crate::bincode::error::DecodeError::Other(stringify!(Invalid $len-byte encoding of a $name)))
440            }
441        }
442
443        #[cfg(feature = "bincode")]
444        #[cfg_attr(docsrs, doc(cfg(feature = "bincode")))]
445        impl<'de, $($($tpl $(:$tcl)?),*)?> $crate::bincode::BorrowDecode<'de> for $type {
446            fn borrow_decode<D: $crate::bincode::de::BorrowDecoder<'de>>(
447                decoder: &mut D,
448            ) -> core::result::Result<Self, $crate::bincode::error::DecodeError> {
449                $crate::bincode::Decode::decode(decoder)
450            }
451        }
452    };
453}