elliptic_curve/
field.rs

1//! Field elements.
2
3use crate::{
4    bigint::{ArrayEncoding, ByteArray, Integer},
5    Curve,
6};
7use generic_array::{typenum::Unsigned, GenericArray};
8
9/// Size of serialized field elements of this elliptic curve.
10pub type FieldBytesSize<C> = <C as Curve>::FieldBytesSize;
11
12/// Byte representation of a base/scalar field element of a given curve.
13pub type FieldBytes<C> = GenericArray<u8, FieldBytesSize<C>>;
14
15/// Trait for decoding/encoding `Curve::Uint` from/to [`FieldBytes`] using
16/// curve-specific rules.
17///
18/// Namely a curve's modulus may be smaller than the big integer type used to
19/// internally represent field elements (since the latter are multiples of the
20/// limb size), such as in the case of curves like NIST P-224 and P-521, and so
21/// it may need to be padded/truncated to the right length.
22///
23/// Additionally, different curves have different endianness conventions, also
24/// captured here.
25pub trait FieldBytesEncoding<C>: ArrayEncoding + Integer
26where
27    C: Curve,
28{
29    /// Decode unsigned integer from serialized field element.
30    ///
31    /// The default implementation assumes a big endian encoding.
32    fn decode_field_bytes(field_bytes: &FieldBytes<C>) -> Self {
33        debug_assert!(field_bytes.len() <= Self::ByteSize::USIZE);
34        let mut byte_array = ByteArray::<Self>::default();
35        let offset = Self::ByteSize::USIZE.saturating_sub(field_bytes.len());
36        byte_array[offset..].copy_from_slice(field_bytes);
37        Self::from_be_byte_array(byte_array)
38    }
39
40    /// Encode unsigned integer into serialized field element.
41    ///
42    /// The default implementation assumes a big endian encoding.
43    fn encode_field_bytes(&self) -> FieldBytes<C> {
44        let mut field_bytes = FieldBytes::<C>::default();
45        debug_assert!(field_bytes.len() <= Self::ByteSize::USIZE);
46
47        let offset = Self::ByteSize::USIZE.saturating_sub(field_bytes.len());
48        field_bytes.copy_from_slice(&self.to_be_byte_array()[offset..]);
49        field_bytes
50    }
51}