decaf377/ark_curve/
encoding.rs

1#![allow(non_snake_case)]
2
3use core::convert::{TryFrom, TryInto};
4
5use ark_ec::twisted_edwards::TECurveConfig;
6use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, Write};
7
8use crate::ark_curve::{
9    constants::TWO, edwards::Decaf377EdwardsConfig, on_curve::OnCurve, EdwardsProjective, Element,
10};
11use crate::sign::Sign;
12use crate::{EncodingError, Fq};
13
14#[derive(Copy, Clone, Default, Eq, Ord, PartialOrd, PartialEq)]
15pub struct Encoding(pub [u8; 32]);
16
17impl core::fmt::Debug for Encoding {
18    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
19        f.write_fmt(format_args!(
20            "decaf377::Encoding({})",
21            hex::encode(&self.0[..])
22        ))
23    }
24}
25
26impl Encoding {
27    #[deprecated(note = "please use `vartime_decompress` instead")]
28    pub fn decompress(&self) -> Result<Element, EncodingError> {
29        self.vartime_decompress()
30    }
31
32    pub fn vartime_decompress(&self) -> Result<Element, EncodingError> {
33        // Top three bits of last byte should be zero
34        if self.0[31] >> 5 != 0u8 {
35            return Err(EncodingError::InvalidEncoding);
36        }
37
38        // This isn't a constant, only because traits don't have const methods
39        // yet and multiplication is only implemented as part of the Mul trait.
40        let D4: Fq = Decaf377EdwardsConfig::COEFF_D * Fq::from(4u32);
41
42        // 1/2. Reject unless s is canonically encoded and nonnegative.
43        let s =
44            Fq::deserialize_compressed(&self.0[..]).map_err(|_| EncodingError::InvalidEncoding)?;
45        if s.is_negative() {
46            return Err(EncodingError::InvalidEncoding);
47        }
48
49        // 3. u_1 <- 1 - s^2
50        let ss = s.square();
51        let u_1 = Fq::ONE - ss;
52
53        // 4. u_2 <- u_1^2 - 4d s^2
54        let u_2 = u_1.square() - D4 * ss;
55
56        // 5. sqrt
57        let (was_square, mut v) = Fq::sqrt_ratio_zeta(&Fq::ONE, &(u_2 * u_1.square()));
58        if !was_square {
59            return Err(EncodingError::InvalidEncoding);
60        }
61
62        // 6. sign check
63        let two_s_u_1 = *TWO * s * u_1;
64        let check = two_s_u_1 * v;
65        if check.is_negative() {
66            v = -v;
67        }
68
69        // 7. coordinates
70        let x = two_s_u_1 * v.square() * u_2;
71        let y = (Fq::ONE + ss) * v * u_1;
72        let z = Fq::ONE;
73        let t = x * y;
74
75        debug_assert!(
76            EdwardsProjective::new(x, y, t, z).is_on_curve(),
77            "resulting point must be on the curve",
78        );
79
80        Ok(Element {
81            inner: EdwardsProjective::new(x, y, t, z),
82        })
83    }
84}
85
86impl Element {
87    pub fn negate(&self) -> Element {
88        Element { inner: -self.inner }
89    }
90
91    pub fn vartime_compress_to_field(&self) -> Fq {
92        // This isn't a constant, only because traits don't have const methods
93        // yet and subtraction is only implemented as part of the Sub trait.
94        let A_MINUS_D = Decaf377EdwardsConfig::COEFF_A - Decaf377EdwardsConfig::COEFF_D;
95        let p = &self.inner;
96
97        // 1.
98        let u_1 = (p.x + p.t) * (p.x - p.t);
99
100        // 2. division by 0 occurs on the identity point, but since
101        // sqrt_ratio_zeta outputs v=0 it computes the right encoding anyway
102        let (_always_square, v) = Fq::sqrt_ratio_zeta(&Fq::ONE, &(u_1 * A_MINUS_D * p.x.square()));
103
104        // 3.
105        let u_2 = (v * u_1).abs();
106
107        // 4.
108        let u_3 = u_2 * p.z - p.t;
109
110        // 5.
111        let s = (A_MINUS_D * v * u_3 * p.x).abs();
112
113        s
114    }
115
116    pub fn vartime_compress(&self) -> Encoding {
117        let s = self.vartime_compress_to_field();
118
119        // Encode.
120        let mut bytes = [0u8; 32];
121        debug_assert_eq!(s.serialized_size(ark_serialize::Compress::Yes), 32);
122        s.serialize_compressed(&mut bytes[..])
123            .expect("serialization into array should be infallible");
124        // Set top three bits of last byte to zero
125        bytes[31] &= 0b00011111;
126
127        Encoding(bytes)
128    }
129}
130
131impl From<&Element> for Encoding {
132    fn from(point: &Element) -> Self {
133        point.vartime_compress()
134    }
135}
136
137impl From<Element> for Encoding {
138    fn from(point: Element) -> Self {
139        point.vartime_compress()
140    }
141}
142
143impl CanonicalSerialize for Encoding {
144    fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
145        match compress {
146            ark_serialize::Compress::Yes => 32,
147            ark_serialize::Compress::No => unimplemented!(),
148        }
149    }
150
151    fn serialize_with_mode<W: Write>(
152        &self,
153        mut writer: W,
154        _mode: ark_serialize::Compress,
155    ) -> Result<(), ark_serialize::SerializationError> {
156        writer.write_all(&self.0[..])?;
157        Ok(())
158    }
159}
160
161impl CanonicalSerialize for Element {
162    fn serialized_size(&self, compress: ark_serialize::Compress) -> usize {
163        match compress {
164            ark_serialize::Compress::Yes => 32,
165            ark_serialize::Compress::No => unimplemented!(),
166        }
167    }
168
169    fn serialize_with_mode<W: Write>(
170        &self,
171        writer: W,
172        mode: ark_serialize::Compress,
173    ) -> Result<(), ark_serialize::SerializationError> {
174        self.vartime_compress().serialize_with_mode(writer, mode)
175    }
176}
177
178impl TryFrom<&[u8]> for Encoding {
179    type Error = EncodingError;
180
181    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
182        if bytes.len() == 32 {
183            let mut arr = [0u8; 32];
184            arr.copy_from_slice(&bytes[0..32]);
185            Ok(Encoding(arr))
186        } else {
187            Err(EncodingError::InvalidSliceLength)
188        }
189    }
190}
191
192impl From<[u8; 32]> for Encoding {
193    fn from(bytes: [u8; 32]) -> Encoding {
194        Encoding(bytes)
195    }
196}
197
198impl From<Encoding> for [u8; 32] {
199    fn from(enc: Encoding) -> [u8; 32] {
200        enc.0
201    }
202}
203
204impl TryFrom<&Encoding> for Element {
205    type Error = EncodingError;
206    fn try_from(bytes: &Encoding) -> Result<Self, Self::Error> {
207        bytes.vartime_decompress()
208    }
209}
210
211impl TryFrom<Encoding> for Element {
212    type Error = EncodingError;
213    fn try_from(bytes: Encoding) -> Result<Self, Self::Error> {
214        bytes.vartime_decompress()
215    }
216}
217
218impl TryFrom<&[u8]> for Element {
219    type Error = EncodingError;
220
221    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
222        let b: [u8; 32] = bytes
223            .try_into()
224            .map_err(|_| EncodingError::InvalidSliceLength)?;
225
226        Encoding(b).try_into()
227    }
228}
229
230impl TryFrom<[u8; 32]> for Element {
231    type Error = EncodingError;
232
233    fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
234        let encoding = Encoding(bytes);
235        encoding.try_into()
236    }
237}
238
239impl From<Element> for [u8; 32] {
240    fn from(enc: Element) -> [u8; 32] {
241        enc.vartime_compress().0
242    }
243}
244
245impl ark_serialize::Valid for Encoding {
246    fn check(&self) -> Result<(), ark_serialize::SerializationError> {
247        // At this stage, validity just means the point has 32 bytes
248        // which is encoded in the type information.
249        Ok(())
250    }
251}
252
253impl CanonicalDeserialize for Encoding {
254    fn deserialize_with_mode<R: Read>(
255        mut reader: R,
256        compress: ark_serialize::Compress,
257        validate: ark_serialize::Validate,
258    ) -> Result<Self, ark_serialize::SerializationError> {
259        match compress {
260            ark_serialize::Compress::Yes => (),
261            ark_serialize::Compress::No => unimplemented!(),
262        }
263        match validate {
264            ark_serialize::Validate::Yes => (),
265            ark_serialize::Validate::No => unimplemented!(),
266        }
267        let mut bytes = [0u8; 32];
268        reader.read_exact(&mut bytes[..])?;
269        Ok(Self(bytes))
270    }
271}
272
273impl CanonicalDeserialize for Element {
274    fn deserialize_with_mode<R: Read>(
275        reader: R,
276        compress: ark_serialize::Compress,
277        validate: ark_serialize::Validate,
278    ) -> Result<Self, ark_serialize::SerializationError> {
279        match compress {
280            ark_serialize::Compress::Yes => (),
281            ark_serialize::Compress::No => unimplemented!(),
282        }
283        match validate {
284            ark_serialize::Validate::Yes => (),
285            ark_serialize::Validate::No => unimplemented!(),
286        }
287        let bytes = Encoding::deserialize_compressed(reader)?;
288        bytes
289            .try_into()
290            .map_err(|_| ark_serialize::SerializationError::InvalidData)
291    }
292}