1use alloc::vec::Vec;
2
3use rand::{CryptoRng, RngCore};
4
5use super::{IesError, IesScheme, crypto_box::CryptoBox, message::SealedMessage};
6use crate::{
7 Felt,
8 aead::{aead_rpo::AeadRpo, xchacha::XChaCha},
9 ecdh::{KeyAgreementScheme, k256::K256, x25519::X25519},
10 utils::{Deserializable, Serializable},
11};
12
13type K256XChaCha20Poly1305 = CryptoBox<K256, XChaCha>;
18type X25519XChaCha20Poly1305 = CryptoBox<X25519, XChaCha>;
20type K256AeadRpo = CryptoBox<K256, AeadRpo>;
22type X25519AeadRpo = CryptoBox<X25519, AeadRpo>;
24
25macro_rules! impl_seal_bytes_with_associated_data {
30 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
31 pub fn seal_bytes_with_associated_data<R: CryptoRng + RngCore>(
37 &self,
38 rng: &mut R,
39 plaintext: &[u8],
40 associated_data: &[u8],
41 ) -> Result<SealedMessage, IesError> {
42 match self {
43 $(
44 $variant(key) => {
45 let (ciphertext, ephemeral) = <$crypto_box>::seal_bytes_with_associated_data(
46 rng,
47 key,
48 plaintext,
49 associated_data,
50 )?;
51
52 Ok(SealedMessage {
53 ephemeral_key: $ephemeral_variant(ephemeral),
54 ciphertext,
55 })
56 }
57 )*
58 }
59 }
60 };
61}
62
63macro_rules! impl_seal_elements_with_associated_data {
65 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
66 pub fn seal_elements_with_associated_data<R: CryptoRng + RngCore>(
72 &self,
73 rng: &mut R,
74 plaintext: &[Felt],
75 associated_data: &[Felt],
76 ) -> Result<SealedMessage, IesError> {
77 match self {
78 $(
79 $variant(key) => {
80 let (ciphertext, ephemeral) = <$crypto_box>::seal_elements_with_associated_data(
81 rng,
82 key,
83 plaintext,
84 associated_data,
85 )?;
86
87 Ok(SealedMessage {
88 ephemeral_key: $ephemeral_variant(ephemeral),
89 ciphertext,
90 })
91 }
92 )*
93 }
94 }
95 };
96}
97
98macro_rules! impl_unseal_bytes_with_associated_data {
100 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
101 pub fn unseal_bytes_with_associated_data(
110 &self,
111 sealed_message: SealedMessage,
112 associated_data: &[u8],
113 ) -> Result<Vec<u8>, IesError> {
114 let self_algo = self.scheme() as u8;
116 let msg_algo = sealed_message.ephemeral_key.scheme() as u8;
117
118 let compatible = self_algo == msg_algo;
119 if !compatible {
120 return Err(IesError::SchemeMismatch);
121 }
122
123 let SealedMessage { ephemeral_key, ciphertext } = sealed_message;
124
125 match (self, ephemeral_key) {
126 $(
127 ($variant(key), $ephemeral_variant(ephemeral)) => {
128 <$crypto_box>::unseal_bytes_with_associated_data(key, &ephemeral, &ciphertext, associated_data)
129 }
130 )*
131 _ => Err(IesError::SchemeMismatch),
132 }
133 }
134 };
135}
136
137macro_rules! impl_unseal_elements_with_associated_data {
139 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
140 pub fn unseal_elements_with_associated_data(
149 &self,
150 sealed_message: SealedMessage,
151 associated_data: &[Felt],
152 ) -> Result<Vec<Felt>, IesError> {
153 let self_algo = self.scheme() as u8;
155 let msg_algo = sealed_message.ephemeral_key.scheme() as u8;
156
157 let compatible = self_algo == msg_algo;
158 if !compatible {
159 return Err(IesError::SchemeMismatch);
160 }
161
162 let SealedMessage { ephemeral_key, ciphertext } = sealed_message;
163
164 match (self, ephemeral_key) {
165 $(
166 ($variant(key), $ephemeral_variant(ephemeral)) => {
167 <$crypto_box>::unseal_elements_with_associated_data(key, &ephemeral, &ciphertext, associated_data)
168 }
169 )*
170 _ => Err(IesError::SchemeMismatch),
171 }
172 }
173 };
174}
175
176#[derive(Debug, Clone, PartialEq, Eq)]
181pub enum SealingKey {
182 K256XChaCha20Poly1305(crate::dsa::ecdsa_k256_keccak::PublicKey),
183 X25519XChaCha20Poly1305(crate::dsa::eddsa_25519::PublicKey),
184 K256AeadRpo(crate::dsa::ecdsa_k256_keccak::PublicKey),
185 X25519AeadRpo(crate::dsa::eddsa_25519::PublicKey),
186}
187
188impl SealingKey {
189 pub fn seal_bytes<R: CryptoRng + RngCore>(
194 &self,
195 rng: &mut R,
196 plaintext: &[u8],
197 ) -> Result<SealedMessage, IesError> {
198 self.seal_bytes_with_associated_data(rng, plaintext, &[])
199 }
200
201 impl_seal_bytes_with_associated_data! {
202 SealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
203 SealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
204 SealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
205 SealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
206 }
207
208 pub fn seal_elements<R: CryptoRng + RngCore>(
213 &self,
214 rng: &mut R,
215 plaintext: &[Felt],
216 ) -> Result<SealedMessage, IesError> {
217 self.seal_elements_with_associated_data(rng, plaintext, &[])
218 }
219
220 impl_seal_elements_with_associated_data! {
221 SealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
222 SealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
223 SealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
224 SealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
225 }
226}
227
228pub enum UnsealingKey {
233 K256XChaCha20Poly1305(crate::dsa::ecdsa_k256_keccak::SecretKey),
234 X25519XChaCha20Poly1305(crate::dsa::eddsa_25519::SecretKey),
235 K256AeadRpo(crate::dsa::ecdsa_k256_keccak::SecretKey),
236 X25519AeadRpo(crate::dsa::eddsa_25519::SecretKey),
237}
238
239impl UnsealingKey {
240 fn scheme(&self) -> IesScheme {
242 match self {
243 UnsealingKey::K256XChaCha20Poly1305(_) => IesScheme::K256XChaCha20Poly1305,
244 UnsealingKey::X25519XChaCha20Poly1305(_) => IesScheme::X25519XChaCha20Poly1305,
245 UnsealingKey::K256AeadRpo(_) => IesScheme::K256AeadRpo,
246 UnsealingKey::X25519AeadRpo(_) => IesScheme::X25519AeadRpo,
247 }
248 }
249
250 pub fn scheme_name(&self) -> &'static str {
252 self.scheme().name()
253 }
254
255 pub fn unseal_bytes(&self, sealed_message: SealedMessage) -> Result<Vec<u8>, IesError> {
260 self.unseal_bytes_with_associated_data(sealed_message, &[])
261 }
262
263 impl_unseal_bytes_with_associated_data! {
264 UnsealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
265 UnsealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
266 UnsealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
267 UnsealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
268 }
269
270 pub fn unseal_elements(&self, sealed_message: SealedMessage) -> Result<Vec<Felt>, IesError> {
275 self.unseal_elements_with_associated_data(sealed_message, &[])
276 }
277
278 impl_unseal_elements_with_associated_data! {
279 UnsealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
280 UnsealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
281 UnsealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
282 UnsealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
283 }
284}
285
286#[derive(Debug, Clone, PartialEq, Eq)]
291pub(super) enum EphemeralPublicKey {
292 K256XChaCha20Poly1305(crate::ecdh::k256::EphemeralPublicKey),
293 X25519XChaCha20Poly1305(crate::ecdh::x25519::EphemeralPublicKey),
294 K256AeadRpo(crate::ecdh::k256::EphemeralPublicKey),
295 X25519AeadRpo(crate::ecdh::x25519::EphemeralPublicKey),
296}
297
298impl EphemeralPublicKey {
299 pub fn scheme(&self) -> IesScheme {
301 match self {
302 EphemeralPublicKey::K256XChaCha20Poly1305(_) => IesScheme::K256XChaCha20Poly1305,
303 EphemeralPublicKey::X25519XChaCha20Poly1305(_) => IesScheme::X25519XChaCha20Poly1305,
304 EphemeralPublicKey::K256AeadRpo(_) => IesScheme::K256AeadRpo,
305 EphemeralPublicKey::X25519AeadRpo(_) => IesScheme::X25519AeadRpo,
306 }
307 }
308
309 pub fn to_bytes(&self) -> Vec<u8> {
311 match self {
312 EphemeralPublicKey::K256XChaCha20Poly1305(key) => key.to_bytes(),
313 EphemeralPublicKey::X25519XChaCha20Poly1305(key) => key.to_bytes(),
314 EphemeralPublicKey::K256AeadRpo(key) => key.to_bytes(),
315 EphemeralPublicKey::X25519AeadRpo(key) => key.to_bytes(),
316 }
317 }
318
319 pub fn from_bytes(scheme: IesScheme, bytes: &[u8]) -> Result<Self, IesError> {
321 match scheme {
322 IesScheme::K256XChaCha20Poly1305 | IesScheme::K256AeadRpo => {
323 let key = <K256 as KeyAgreementScheme>::EphemeralPublicKey::read_from_bytes(bytes)
324 .map_err(|_| IesError::EphemeralPublicKeyDeserializationFailed)?;
325 Ok(EphemeralPublicKey::K256XChaCha20Poly1305(key))
326 },
327 IesScheme::X25519XChaCha20Poly1305 | IesScheme::X25519AeadRpo => {
328 let key =
329 <X25519 as KeyAgreementScheme>::EphemeralPublicKey::read_from_bytes(bytes)
330 .map_err(|_| IesError::EphemeralPublicKeyDeserializationFailed)?;
331 Ok(EphemeralPublicKey::X25519XChaCha20Poly1305(key))
332 },
333 }
334 }
335}