kyber_rs/encrypt/ecies/
ecies_impl.rs1use crate::{
3 dh::{DhError, AEAD, NONCE_SIZE},
4 encoding::{BinaryMarshaler, BinaryUnmarshaler, Marshaling, MarshallingError},
5 util::random::RandStream,
6 Group, Point, Scalar,
7};
8use thiserror::Error;
9
10pub fn encrypt<GROUP: Group>(
17 group: GROUP,
18 public: GROUP::POINT,
19 message: &[u8],
20) -> Result<Vec<u8>, EciesError> {
21 let r = group.scalar().pick(&mut RandStream::default());
23 let r_p = group.point().mul(&r, None);
24
25 let dh = group.point().mul(&r, Some(&public));
27
28 let len = 32 + NONCE_SIZE;
33 let buf = derive_key::<GROUP>(&dh, len)?;
34
35 let mut nonce = [0u8; NONCE_SIZE];
36 nonce.copy_from_slice(&buf[32..len]);
37
38 let gcm = AEAD::<GROUP>::new(r_p.clone(), &buf)?;
39
40 let c = gcm.seal(None, &nonce, message, None)?;
42
43 let mut ctx = Vec::new();
45 r_p.marshal_to(&mut ctx)?;
46 for v in c {
47 ctx.push(v);
48 }
49 Ok(ctx)
50}
51
52pub fn decrypt<GROUP: Group>(
59 group: GROUP,
60 private: <GROUP::POINT as Point>::SCALAR,
61 ctx: &[u8],
62) -> Result<Vec<u8>, EciesError> {
63 let mut r_p = group.point();
65 let l = group.point_len();
66 r_p.unmarshal_binary(&ctx[..l])?;
67
68 let dh = group.point().mul(&private, Some(&r_p));
70 let len = 32 + NONCE_SIZE;
71 let buf = derive_key::<GROUP>(&dh, len)?;
72
73 let mut nonce = [0u8; NONCE_SIZE];
74 nonce.copy_from_slice(&buf[32..len]);
75
76 let gcm = AEAD::<GROUP>::new(r_p.clone(), &buf)?;
78 Ok(gcm.open(None, &nonce, &ctx[l..], None)?)
79}
80
81fn derive_key<GROUP: Group>(dh: &GROUP::POINT, len: usize) -> Result<Vec<u8>, EciesError> {
82 let dhb = dh.marshal_binary()?;
83 let key = GROUP::hkdf(&dhb, &Vec::new(), Some(len))?;
84
85 if key.len() < len {
86 return Err(EciesError::KeyTooShort);
87 }
88 Ok(key)
89}
90
91#[derive(Debug, Error)]
92pub enum EciesError {
93 #[error("marshalling error")]
94 MarshalingError(#[from] MarshallingError),
95 #[error("dh error")]
96 DhError(#[from] DhError),
97 #[error("hkdf-derived key too short")]
98 KeyTooShort,
99}