1use alloc::vec::Vec;
2use core::fmt;
3
4use rand::{CryptoRng, RngCore};
5
6use super::{IesError, IesScheme, crypto_box::CryptoBox, message::SealedMessage};
7use crate::{
8 Felt,
9 aead::{aead_rpo::AeadRpo, xchacha::XChaCha},
10 ecdh::{KeyAgreementScheme, k256::K256, x25519::X25519},
11 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
12};
13
14type K256XChaCha20Poly1305 = CryptoBox<K256, XChaCha>;
19type X25519XChaCha20Poly1305 = CryptoBox<X25519, XChaCha>;
21type K256AeadRpo = CryptoBox<K256, AeadRpo>;
23type X25519AeadRpo = CryptoBox<X25519, AeadRpo>;
25
26macro_rules! impl_seal_bytes_with_associated_data {
31 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
32 pub fn seal_bytes_with_associated_data<R: CryptoRng + RngCore>(
38 &self,
39 rng: &mut R,
40 plaintext: &[u8],
41 associated_data: &[u8],
42 ) -> Result<SealedMessage, IesError> {
43 match self {
44 $(
45 $variant(key) => {
46 let (ciphertext, ephemeral) = <$crypto_box>::seal_bytes_with_associated_data(
47 rng,
48 key,
49 plaintext,
50 associated_data,
51 )?;
52
53 Ok(SealedMessage {
54 ephemeral_key: $ephemeral_variant(ephemeral),
55 ciphertext,
56 })
57 }
58 )*
59 }
60 }
61 };
62}
63
64macro_rules! impl_seal_elements_with_associated_data {
66 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
67 pub fn seal_elements_with_associated_data<R: CryptoRng + RngCore>(
73 &self,
74 rng: &mut R,
75 plaintext: &[Felt],
76 associated_data: &[Felt],
77 ) -> Result<SealedMessage, IesError> {
78 match self {
79 $(
80 $variant(key) => {
81 let (ciphertext, ephemeral) = <$crypto_box>::seal_elements_with_associated_data(
82 rng,
83 key,
84 plaintext,
85 associated_data,
86 )?;
87
88 Ok(SealedMessage {
89 ephemeral_key: $ephemeral_variant(ephemeral),
90 ciphertext,
91 })
92 }
93 )*
94 }
95 }
96 };
97}
98
99macro_rules! impl_unseal_bytes_with_associated_data {
101 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
102 pub fn unseal_bytes_with_associated_data(
111 &self,
112 sealed_message: SealedMessage,
113 associated_data: &[u8],
114 ) -> Result<Vec<u8>, IesError> {
115 let self_algo = self.scheme() as u8;
117 let msg_algo = sealed_message.ephemeral_key.scheme() as u8;
118
119 let compatible = self_algo == msg_algo;
120 if !compatible {
121 return Err(IesError::SchemeMismatch);
122 }
123
124 let SealedMessage { ephemeral_key, ciphertext } = sealed_message;
125
126 match (self, ephemeral_key) {
127 $(
128 ($variant(key), $ephemeral_variant(ephemeral)) => {
129 <$crypto_box>::unseal_bytes_with_associated_data(key, &ephemeral, &ciphertext, associated_data)
130 }
131 )*
132 _ => Err(IesError::SchemeMismatch),
133 }
134 }
135 };
136}
137
138macro_rules! impl_unseal_elements_with_associated_data {
140 ($($variant:path => $crypto_box:ty, $ephemeral_variant:path;)*) => {
141 pub fn unseal_elements_with_associated_data(
150 &self,
151 sealed_message: SealedMessage,
152 associated_data: &[Felt],
153 ) -> Result<Vec<Felt>, IesError> {
154 let self_algo = self.scheme() as u8;
156 let msg_algo = sealed_message.ephemeral_key.scheme() as u8;
157
158 let compatible = self_algo == msg_algo;
159 if !compatible {
160 return Err(IesError::SchemeMismatch);
161 }
162
163 let SealedMessage { ephemeral_key, ciphertext } = sealed_message;
164
165 match (self, ephemeral_key) {
166 $(
167 ($variant(key), $ephemeral_variant(ephemeral)) => {
168 <$crypto_box>::unseal_elements_with_associated_data(key, &ephemeral, &ciphertext, associated_data)
169 }
170 )*
171 _ => Err(IesError::SchemeMismatch),
172 }
173 }
174 };
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
182pub enum SealingKey {
183 K256XChaCha20Poly1305(crate::dsa::ecdsa_k256_keccak::PublicKey),
184 X25519XChaCha20Poly1305(crate::dsa::eddsa_25519_sha512::PublicKey),
185 K256AeadRpo(crate::dsa::ecdsa_k256_keccak::PublicKey),
186 X25519AeadRpo(crate::dsa::eddsa_25519_sha512::PublicKey),
187}
188
189impl SealingKey {
190 pub fn scheme(&self) -> IesScheme {
192 match self {
193 SealingKey::K256XChaCha20Poly1305(_) => IesScheme::K256XChaCha20Poly1305,
194 SealingKey::X25519XChaCha20Poly1305(_) => IesScheme::X25519XChaCha20Poly1305,
195 SealingKey::K256AeadRpo(_) => IesScheme::K256AeadRpo,
196 SealingKey::X25519AeadRpo(_) => IesScheme::X25519AeadRpo,
197 }
198 }
199
200 pub fn seal_bytes<R: CryptoRng + RngCore>(
205 &self,
206 rng: &mut R,
207 plaintext: &[u8],
208 ) -> Result<SealedMessage, IesError> {
209 self.seal_bytes_with_associated_data(rng, plaintext, &[])
210 }
211
212 impl_seal_bytes_with_associated_data! {
213 SealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
214 SealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
215 SealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
216 SealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
217 }
218
219 pub fn seal_elements<R: CryptoRng + RngCore>(
224 &self,
225 rng: &mut R,
226 plaintext: &[Felt],
227 ) -> Result<SealedMessage, IesError> {
228 self.seal_elements_with_associated_data(rng, plaintext, &[])
229 }
230
231 impl_seal_elements_with_associated_data! {
232 SealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
233 SealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
234 SealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
235 SealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
236 }
237}
238
239impl fmt::Display for SealingKey {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 write!(f, "{} sealing key", self.scheme())
242 }
243}
244
245impl Serializable for SealingKey {
246 fn write_into<W: ByteWriter>(&self, target: &mut W) {
247 target.write_u8(self.scheme().into());
248
249 match self {
250 SealingKey::K256XChaCha20Poly1305(key) => key.write_into(target),
251 SealingKey::X25519XChaCha20Poly1305(key) => key.write_into(target),
252 SealingKey::K256AeadRpo(key) => key.write_into(target),
253 SealingKey::X25519AeadRpo(key) => key.write_into(target),
254 }
255 }
256}
257
258impl Deserializable for SealingKey {
259 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
260 let scheme = IesScheme::try_from(source.read_u8()?)
261 .map_err(|_| DeserializationError::InvalidValue("Unsupported IES scheme".into()))?;
262
263 match scheme {
264 IesScheme::K256XChaCha20Poly1305 => {
265 let key = crate::dsa::ecdsa_k256_keccak::PublicKey::read_from(source)?;
266 Ok(SealingKey::K256XChaCha20Poly1305(key))
267 },
268 IesScheme::X25519XChaCha20Poly1305 => {
269 let key = crate::dsa::eddsa_25519_sha512::PublicKey::read_from(source)?;
270 Ok(SealingKey::X25519XChaCha20Poly1305(key))
271 },
272 IesScheme::K256AeadRpo => {
273 let key = crate::dsa::ecdsa_k256_keccak::PublicKey::read_from(source)?;
274 Ok(SealingKey::K256AeadRpo(key))
275 },
276 IesScheme::X25519AeadRpo => {
277 let key = crate::dsa::eddsa_25519_sha512::PublicKey::read_from(source)?;
278 Ok(SealingKey::X25519AeadRpo(key))
279 },
280 }
281 }
282}
283
284pub enum UnsealingKey {
289 K256XChaCha20Poly1305(crate::dsa::ecdsa_k256_keccak::SecretKey),
290 X25519XChaCha20Poly1305(crate::dsa::eddsa_25519_sha512::SecretKey),
291 K256AeadRpo(crate::dsa::ecdsa_k256_keccak::SecretKey),
292 X25519AeadRpo(crate::dsa::eddsa_25519_sha512::SecretKey),
293}
294
295impl UnsealingKey {
296 pub fn scheme(&self) -> IesScheme {
298 match self {
299 UnsealingKey::K256XChaCha20Poly1305(_) => IesScheme::K256XChaCha20Poly1305,
300 UnsealingKey::X25519XChaCha20Poly1305(_) => IesScheme::X25519XChaCha20Poly1305,
301 UnsealingKey::K256AeadRpo(_) => IesScheme::K256AeadRpo,
302 UnsealingKey::X25519AeadRpo(_) => IesScheme::X25519AeadRpo,
303 }
304 }
305
306 pub fn scheme_name(&self) -> &'static str {
308 self.scheme().name()
309 }
310
311 pub fn unseal_bytes(&self, sealed_message: SealedMessage) -> Result<Vec<u8>, IesError> {
316 self.unseal_bytes_with_associated_data(sealed_message, &[])
317 }
318
319 impl_unseal_bytes_with_associated_data! {
320 UnsealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
321 UnsealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
322 UnsealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
323 UnsealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
324 }
325
326 pub fn unseal_elements(&self, sealed_message: SealedMessage) -> Result<Vec<Felt>, IesError> {
331 self.unseal_elements_with_associated_data(sealed_message, &[])
332 }
333
334 impl_unseal_elements_with_associated_data! {
335 UnsealingKey::K256XChaCha20Poly1305 => K256XChaCha20Poly1305, EphemeralPublicKey::K256XChaCha20Poly1305;
336 UnsealingKey::X25519XChaCha20Poly1305 => X25519XChaCha20Poly1305, EphemeralPublicKey::X25519XChaCha20Poly1305;
337 UnsealingKey::K256AeadRpo => K256AeadRpo, EphemeralPublicKey::K256AeadRpo;
338 UnsealingKey::X25519AeadRpo => X25519AeadRpo, EphemeralPublicKey::X25519AeadRpo;
339 }
340}
341
342impl fmt::Display for UnsealingKey {
343 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344 write!(f, "{} unsealing key", self.scheme())
345 }
346}
347
348impl Serializable for UnsealingKey {
349 fn write_into<W: ByteWriter>(&self, target: &mut W) {
350 target.write_u8(self.scheme().into());
351
352 match self {
353 UnsealingKey::K256XChaCha20Poly1305(key) => key.write_into(target),
354 UnsealingKey::X25519XChaCha20Poly1305(key) => key.write_into(target),
355 UnsealingKey::K256AeadRpo(key) => key.write_into(target),
356 UnsealingKey::X25519AeadRpo(key) => key.write_into(target),
357 }
358 }
359}
360
361impl Deserializable for UnsealingKey {
362 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
363 let scheme = IesScheme::try_from(source.read_u8()?)
364 .map_err(|_| DeserializationError::InvalidValue("Unsupported IES scheme".into()))?;
365
366 match scheme {
367 IesScheme::K256XChaCha20Poly1305 => {
368 let key = crate::dsa::ecdsa_k256_keccak::SecretKey::read_from(source)?;
369 Ok(UnsealingKey::K256XChaCha20Poly1305(key))
370 },
371 IesScheme::X25519XChaCha20Poly1305 => {
372 let key = crate::dsa::eddsa_25519_sha512::SecretKey::read_from(source)?;
373 Ok(UnsealingKey::X25519XChaCha20Poly1305(key))
374 },
375 IesScheme::K256AeadRpo => {
376 let key = crate::dsa::ecdsa_k256_keccak::SecretKey::read_from(source)?;
377 Ok(UnsealingKey::K256AeadRpo(key))
378 },
379 IesScheme::X25519AeadRpo => {
380 let key = crate::dsa::eddsa_25519_sha512::SecretKey::read_from(source)?;
381 Ok(UnsealingKey::X25519AeadRpo(key))
382 },
383 }
384 }
385}
386
387#[derive(Debug, Clone, PartialEq, Eq)]
392pub(super) enum EphemeralPublicKey {
393 K256XChaCha20Poly1305(crate::ecdh::k256::EphemeralPublicKey),
394 X25519XChaCha20Poly1305(crate::ecdh::x25519::EphemeralPublicKey),
395 K256AeadRpo(crate::ecdh::k256::EphemeralPublicKey),
396 X25519AeadRpo(crate::ecdh::x25519::EphemeralPublicKey),
397}
398
399impl EphemeralPublicKey {
400 pub fn scheme(&self) -> IesScheme {
402 match self {
403 EphemeralPublicKey::K256XChaCha20Poly1305(_) => IesScheme::K256XChaCha20Poly1305,
404 EphemeralPublicKey::X25519XChaCha20Poly1305(_) => IesScheme::X25519XChaCha20Poly1305,
405 EphemeralPublicKey::K256AeadRpo(_) => IesScheme::K256AeadRpo,
406 EphemeralPublicKey::X25519AeadRpo(_) => IesScheme::X25519AeadRpo,
407 }
408 }
409
410 pub fn to_bytes(&self) -> Vec<u8> {
412 match self {
413 EphemeralPublicKey::K256XChaCha20Poly1305(key) => key.to_bytes(),
414 EphemeralPublicKey::X25519XChaCha20Poly1305(key) => key.to_bytes(),
415 EphemeralPublicKey::K256AeadRpo(key) => key.to_bytes(),
416 EphemeralPublicKey::X25519AeadRpo(key) => key.to_bytes(),
417 }
418 }
419
420 pub fn from_bytes(scheme: IesScheme, bytes: &[u8]) -> Result<Self, IesError> {
422 match scheme {
423 IesScheme::K256XChaCha20Poly1305 => {
424 let key = <K256 as KeyAgreementScheme>::EphemeralPublicKey::read_from_bytes(bytes)
425 .map_err(|_| IesError::EphemeralPublicKeyDeserializationFailed)?;
426 Ok(EphemeralPublicKey::K256XChaCha20Poly1305(key))
427 },
428 IesScheme::K256AeadRpo => {
429 let key = <K256 as KeyAgreementScheme>::EphemeralPublicKey::read_from_bytes(bytes)
430 .map_err(|_| IesError::EphemeralPublicKeyDeserializationFailed)?;
431 Ok(EphemeralPublicKey::K256AeadRpo(key))
432 },
433 IesScheme::X25519XChaCha20Poly1305 => {
434 let key =
435 <X25519 as KeyAgreementScheme>::EphemeralPublicKey::read_from_bytes(bytes)
436 .map_err(|_| IesError::EphemeralPublicKeyDeserializationFailed)?;
437 Ok(EphemeralPublicKey::X25519XChaCha20Poly1305(key))
438 },
439 IesScheme::X25519AeadRpo => {
440 let key =
441 <X25519 as KeyAgreementScheme>::EphemeralPublicKey::read_from_bytes(bytes)
442 .map_err(|_| IesError::EphemeralPublicKeyDeserializationFailed)?;
443 Ok(EphemeralPublicKey::X25519AeadRpo(key))
444 },
445 }
446 }
447}