Skip to main content

spongefish/drivers/
curve25519_dalek_impl.rs

1//! curve25519-dalek codec implementations
2use curve25519_dalek::{
3    edwards::{CompressedEdwardsY, EdwardsPoint},
4    ristretto::{CompressedRistretto, RistrettoPoint},
5    scalar::Scalar,
6};
7
8use crate::{
9    codecs::{Decoding, Encoding},
10    error::VerificationError,
11    io::NargDeserialize,
12    VerificationResult,
13};
14
15// Make curve25519-dalek Scalar a valid Unit type
16impl crate::Unit for Scalar {
17    const ZERO: Self = Self::ZERO;
18}
19
20// Implement Decoding for curve25519-dalek Scalar
21impl Decoding<[u8]> for Scalar {
22    type Repr = super::Array64;
23
24    fn decode(buf: Self::Repr) -> Self {
25        let mut le_bytes = buf.0;
26        le_bytes.reverse();
27        Self::from_bytes_mod_order_wide(&le_bytes)
28    }
29}
30
31impl Decoding<[u8]> for RistrettoPoint {
32    type Repr = super::Array64;
33
34    fn decode(buf: Self::Repr) -> Self {
35        Self::from_uniform_bytes(&buf.0)
36    }
37}
38
39// Implement Deserialize for curve25519-dalek Scalar using OS2IP (big-endian)
40impl NargDeserialize for Scalar {
41    fn deserialize_from_narg(buf: &mut &[u8]) -> VerificationResult<Self> {
42        const N: usize = 32;
43        if buf.len() < N {
44            return Err(VerificationError);
45        }
46
47        let be_bytes = &buf[..N];
48        let mut le_bytes = [0u8; N];
49        le_bytes.copy_from_slice(be_bytes);
50        le_bytes.reverse();
51        Self::from_canonical_bytes(le_bytes)
52            .into_option()
53            .inspect(|_| *buf = &buf[N..])
54            .ok_or(VerificationError)
55    }
56}
57
58// Implement Deserialize for EdwardsPoint
59impl NargDeserialize for EdwardsPoint {
60    fn deserialize_from_narg(buf: &mut &[u8]) -> VerificationResult<Self> {
61        if buf.len() < 32 {
62            return Err(VerificationError);
63        }
64        let point = CompressedEdwardsY(buf[..32].try_into().unwrap())
65            .decompress()
66            .ok_or(VerificationError)?;
67        *buf = &buf[32..];
68        Ok(point)
69    }
70}
71
72// Implement Deserialize for RistrettoPoint
73impl NargDeserialize for RistrettoPoint {
74    fn deserialize_from_narg(buf: &mut &[u8]) -> VerificationResult<Self> {
75        if buf.len() < 32 {
76            return Err(VerificationError);
77        }
78        let point = CompressedRistretto(buf[..32].try_into().unwrap())
79            .decompress()
80            .ok_or(VerificationError)?;
81        *buf = &buf[32..];
82        Ok(point)
83    }
84}
85
86// Implement Encoding for curve25519-dalek Scalar using I2OSP (big-endian)
87impl Encoding<[u8]> for Scalar {
88    fn encode(&self) -> impl AsRef<[u8]> {
89        let mut le_bytes = self.to_bytes();
90        le_bytes.reverse();
91
92        le_bytes
93    }
94}
95
96// Implement Encoding for EdwardsPoint
97impl Encoding<[u8]> for EdwardsPoint {
98    fn encode(&self) -> impl AsRef<[u8]> {
99        self.compress().to_bytes()
100    }
101}
102
103// Implement Encoding for RistrettoPoint
104impl Encoding<[u8]> for RistrettoPoint {
105    fn encode(&self) -> impl AsRef<[u8]> {
106        self.compress().to_bytes()
107    }
108}