1use rand_core::CryptoRng;
7
8use crate::{Decoy, KeyPair, RandomSecretKey};
9
10#[cfg(feature = "dalek-x25519")]
12#[derive(Debug, Clone)]
13pub struct DalekX25519 {}
14
15#[cfg(feature = "dalek-x25519")]
16pub(crate) mod dalek_x25519 {
17 use super::*;
18
19 use typenum::U32;
20
21 type PublicKey = x25519_dalek::PublicKey;
22 type StaticSecret = x25519_dalek::StaticSecret;
23
24 impl KeyPair for DalekX25519 {
25 type SecretKey = StaticSecret;
26 type PublicKey = PublicKey;
27 type PublicKeySize = U32;
28 }
29
30 impl Decoy for PublicKey {
31 fn random_decoy(csprng: &mut impl CryptoRng) -> Self {
32 let secret = StaticSecret::random_from_rng(csprng);
33
34 PublicKey::from(&secret)
35 }
36 }
37
38 impl RandomSecretKey for StaticSecret {
39 fn random_secret_key(csprng: &mut impl CryptoRng) -> Self {
40 StaticSecret::random_from_rng(csprng)
41 }
42 }
43}
44
45#[cfg(feature = "dalek-ristretto255")]
47#[derive(Debug, Clone)]
48pub struct DalekRistretto255 {}
49
50#[cfg(feature = "dalek-ristretto255")]
51pub mod dalek_ristretto255 {
53 use super::*;
54
55 use curve25519_dalek::{RistrettoPoint, traits::IsIdentity};
56 use hybrid_array::Array;
57 use typenum::U32;
58 #[cfg(feature = "zeroize")]
59 use zeroize::Zeroize;
60
61 #[cfg_attr(feature = "zeroize", derive(Zeroize))]
63 pub struct StaticSecret(pub(crate) curve25519_dalek::Scalar);
64
65 impl StaticSecret {
66 pub fn random_from_rng(csprng: &mut impl CryptoRng) -> Self {
68 StaticSecret(curve25519_dalek::Scalar::random(csprng))
69 }
70
71 pub fn diffie_hellman(&self, their_public: &PublicKey) -> SharedSecret {
74 SharedSecret(self.0 * their_public.0)
75 }
76
77 pub fn to_bytes(&self) -> [u8; 32] {
79 self.0.to_bytes()
80 }
81
82 pub fn as_bytes(&self) -> &[u8; 32] {
84 self.0.as_bytes()
85 }
86 }
87
88 impl From<[u8; 32]> for StaticSecret {
89 fn from(bytes: [u8; 32]) -> Self {
90 StaticSecret(curve25519_dalek::Scalar::from_bytes_mod_order(bytes))
91 }
92 }
93
94 #[cfg_attr(feature = "zeroize", derive(Zeroize))]
96 pub struct SharedSecret(pub(crate) RistrettoPoint);
97
98 impl SharedSecret {
99 pub fn to_bytes(&self) -> Array<u8, U32> {
101 Array::from(self.0.compress().to_bytes())
102 }
103 }
104
105 #[derive(Debug, Clone)]
107 #[cfg_attr(feature = "zeroize", derive(Zeroize))]
108 pub struct PublicKey(pub(crate) RistrettoPoint);
109
110 impl PublicKey {
111 pub fn to_bytes(&self) -> [u8; 32] {
113 self.0.compress().to_bytes()
114 }
115 }
116
117 impl From<&StaticSecret> for PublicKey {
118 fn from(value: &StaticSecret) -> Self {
119 PublicKey(RistrettoPoint::mul_base(&value.0))
120 }
121 }
122
123 impl Decoy for PublicKey {
124 fn random_decoy(csprng: &mut impl CryptoRng) -> Self {
125 #[allow(unsafe_code)]
126 unsafe {
127 std::iter::repeat_with(|| RistrettoPoint::random(csprng))
129 .find(|p| !p.is_identity())
130 .map(PublicKey)
131 .unwrap_unchecked()
132 }
133 }
134 }
135
136 impl KeyPair for DalekRistretto255 {
137 type SecretKey = StaticSecret;
138 type PublicKey = PublicKey;
139 type PublicKeySize = U32;
140 }
141
142 impl RandomSecretKey for StaticSecret {
143 fn random_secret_key(csprng: &mut impl CryptoRng) -> Self {
144 StaticSecret::random_from_rng(csprng)
145 }
146 }
147}
148
149#[cfg(feature = "rustcrypto-ec")]
151#[derive(Debug, Clone)]
152pub struct EllipticCurve<C> {
153 marker: std::marker::PhantomData<C>,
154}
155
156#[cfg(feature = "rustcrypto-ec")]
157mod rustcrypto_ec {
158 use super::*;
159
160 use elliptic_curve::{
161 Curve, CurveArithmetic, Generate, ProjectivePoint, PublicKey, SecretKey,
162 point::NonIdentity,
163 sec1::{CompressedPointSize, ModulusSize},
164 };
165
166 impl<C: CurveArithmetic> KeyPair for EllipticCurve<C>
167 where
168 <C as Curve>::FieldBytesSize: ModulusSize,
169 {
170 type SecretKey = SecretKey<C>;
171 type PublicKey = PublicKey<C>;
172 type PublicKeySize = CompressedPointSize<C>;
173 }
174
175 impl<C: CurveArithmetic> Decoy for PublicKey<C> {
176 fn random_decoy(csprng: &mut impl CryptoRng) -> Self {
177 PublicKey::<C>::from(NonIdentity::<ProjectivePoint<C>>::generate_from_rng(
178 &mut *csprng,
179 ))
180 }
181 }
182
183 impl<C: CurveArithmetic> RandomSecretKey for SecretKey<C> {
184 fn random_secret_key(csprng: &mut impl CryptoRng) -> Self {
185 SecretKey::<C>::generate_from_rng(csprng)
186 }
187 }
188}