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}