1#[cfg(not(any(target_arch = "wasm32", docsrs)))]
19compile_error!("\"web\" feature should only be enabled on wasm32 targets");
20
21mod aesgcm;
22
23#[cfg(feature = "stream")]
24pub mod stream;
25
26use super::web::aesgcm::encrypt;
27use super::web::aesgcm::{decrypt, get_key};
28
29use crate::artifacts::{PublicKey, UserSecretKey};
30use crate::client::*;
31use crate::error::Error;
32use crate::identity::{EncryptionPolicy, Policy};
33
34use ibe::kem::cgw_kv::CGWKV;
35use ibs::gg::Signer;
36
37use js_sys::Error as JsError;
38use js_sys::Uint8Array;
39use rand::{CryptoRng, RngCore};
40use wasm_bindgen::JsValue;
41
42use alloc::string::ToString;
43use alloc::vec::Vec;
44
45#[derive(Debug)]
47pub struct SealerMemoryConfig {
48 key: [u8; KEY_SIZE],
49 nonce: [u8; IV_SIZE],
50}
51
52#[derive(Debug)]
54pub struct UnsealerMemoryConfig {
55 message_len: usize,
56}
57
58impl SealerConfig for SealerMemoryConfig {}
59impl super::sealed::SealerConfig for SealerMemoryConfig {}
60
61impl UnsealerConfig for UnsealerMemoryConfig {}
62impl super::sealed::UnsealerConfig for UnsealerMemoryConfig {}
63
64#[derive(Debug, Serialize, Deserialize)]
77struct MessageAndSignature {
78 message: Vec<u8>,
79 sig: SignatureExt,
80 pub_pol: Policy,
81}
82
83#[derive(Debug, Serialize, Deserialize)]
90struct MessageAndSignaturePrefix {
91 message: Vec<u8>,
92 sig: SignatureExt,
93}
94
95impl<'r, R: RngCore + CryptoRng> Sealer<'r, R, SealerMemoryConfig> {
96 pub fn new(
98 mpk: &PublicKey<CGWKV>,
99 policies: &EncryptionPolicy,
100 pub_sign_key: &SigningKeyExt,
101 rng: &'r mut R,
102 ) -> Result<Self, Error> {
103 let (header, ss) = Header::new(mpk, policies, rng)?;
104 let Algorithm::Aes128Gcm(iv) = header.algo;
105
106 let mut key = [0u8; KEY_SIZE];
107 let mut nonce = [0u8; IV_SIZE];
108 key.copy_from_slice(&ss.0[..KEY_SIZE]);
109 nonce.copy_from_slice(&iv.0[..IV_SIZE]);
110
111 Ok(Self {
112 rng,
113 header,
114 pub_sign_key: crate::client::canonical_signing_key(pub_sign_key),
115 priv_sign_key: None,
116 config: SealerMemoryConfig { key, nonce },
117 })
118 }
119
120 pub async fn seal(mut self, message: &Uint8Array) -> Result<Uint8Array, Error> {
122 let mut out = Vec::with_capacity(message.byte_length() as usize + 1024);
123
124 out.extend_from_slice(&PRELUDE);
125 out.extend_from_slice(&VERSION_2.to_be_bytes());
126 self.header = self.header.with_mode(Mode::InMemory {
127 size: message.byte_length(),
128 });
129
130 let header_buf = crate::bincode_compat::serialize(&self.header)?;
131 out.extend_from_slice(&(header_buf.len() as u32).to_be_bytes());
132 out.extend_from_slice(&header_buf);
133
134 let signer = Signer::new().chain(header_buf);
135 let h_sig = signer.clone().sign(&self.pub_sign_key.key.0, self.rng);
136
137 let h_sig_ext = SignatureExt {
138 sig: h_sig,
139 pol: self.pub_sign_key.policy.clone(),
140 };
141
142 let h_sig_ext_bytes = crate::bincode_compat::serialize(&h_sig_ext)?;
143 out.extend_from_slice(&(h_sig_ext_bytes.len() as u32).to_be_bytes());
144 out.extend_from_slice(&h_sig_ext_bytes);
145
146 let m = message.to_vec();
147 let pub_pol = self.pub_sign_key.policy.clone();
148 let m_sig_key = self.priv_sign_key.unwrap_or(self.pub_sign_key);
149 let m_sig = signer.chain(&m).sign(&m_sig_key.key.0, self.rng);
150
151 let input = crate::bincode_compat::serialize(&MessageAndSignature {
152 message: m,
153 sig: SignatureExt {
154 sig: m_sig,
155 pol: m_sig_key.policy.clone(),
156 },
157 pub_pol,
158 })?;
159
160 let key = get_key(&self.config.key).await?;
161 let ciphertext = encrypt(
162 &key,
163 &self.config.nonce,
164 &Uint8Array::new_with_length(0),
165 &Uint8Array::from(input.as_slice()),
166 )
167 .await?;
168
169 out.extend_from_slice(&ciphertext.to_vec());
170
171 Ok(Uint8Array::from(out.as_slice()))
172 }
173}
174
175impl Unsealer<Uint8Array, UnsealerMemoryConfig> {
176 pub fn new(input: &Uint8Array, vk: &VerifyingKey) -> Result<Self, Error> {
178 let b = input.to_vec();
179 let (preamble_bytes, b) = try_split_at(&b, PREAMBLE_SIZE, "preamble")?;
180 let (version, header_len) = preamble_checked(preamble_bytes)?;
181
182 let (header_bytes, b) = try_split_at(b, header_len, "header")?;
183 let (h_sig_len_bytes, b) = try_split_at(b, SIG_SIZE_SIZE, "header signature length")?;
184 let h_sig_len = u32::from_be_bytes(h_sig_len_bytes.try_into()?);
185 let (h_sig_bytes, ct) = try_split_at(b, h_sig_len as usize, "header signature")?;
186
187 let h_sig_ext: SignatureExt = crate::bincode_compat::deserialize(h_sig_bytes)?;
188 let id = h_sig_ext.pol.derive_ibs()?;
189
190 let verifier = Verifier::default().chain(&header_bytes);
191
192 if !verifier.clone().verify(&vk.0, &h_sig_ext.sig, &id) {
193 return Err(Error::IncorrectSignature.into());
194 }
195
196 let header: Header = crate::bincode_compat::deserialize(header_bytes)?;
197 let message_len = match header.mode {
198 Mode::InMemory { size } => size as usize,
199 _ => return Err(Error::ModeNotSupported(header.mode).into()),
200 };
201
202 Ok(Self {
203 version,
204 header,
205 pub_id: h_sig_ext.pol,
206 r: Uint8Array::from(ct),
207 verifier,
208 vk: vk.clone(),
209 config: UnsealerMemoryConfig { message_len },
210 })
211 }
212
213 pub async fn unseal(
215 self,
216 ident: &str,
217 usk: &UserSecretKey<CGWKV>,
218 ) -> Result<(Uint8Array, VerificationResult), Error> {
219 let rec_info = self
220 .header
221 .recipients
222 .get(ident)
223 .ok_or_else(|| Error::UnknownIdentifier(ident.to_string()))?;
224
225 let ss = rec_info.decaps(usk)?;
226 let key = get_key(&ss.0[..KEY_SIZE]).await?;
227
228 let Algorithm::Aes128Gcm(iv) = self.header.algo;
229
230 let plain = decrypt(&key, &iv.0, &Uint8Array::new_with_length(0), &self.r)
231 .await?
232 .to_vec();
233
234 let (msg, read): (MessageAndSignaturePrefix, usize) =
235 crate::bincode_compat::deserialize_with_len(&plain).map_err(Into::<Error>::into)?;
236
237 if let Some(trailing) = plain.get(read..).filter(|t| !t.is_empty()) {
245 let sealed_pub_pol: Policy =
246 crate::bincode_compat::deserialize(trailing).map_err(Into::<Error>::into)?;
247
248 if sealed_pub_pol != self.pub_id {
249 return Err(Error::IncorrectSignature);
250 }
251 }
252
253 let id = msg.sig.pol.derive_ibs()?;
254 let verified = self
255 .verifier
256 .chain(&msg.message)
257 .verify(&self.vk.0, &msg.sig.sig, &id);
258
259 if !verified {
260 return Err(Error::IncorrectSignature.into());
261 }
262
263 debug_assert_eq!(self.config.message_len, msg.message.len());
264
265 let res = Uint8Array::from(msg.message.as_slice());
266
267 let private = if self.pub_id == msg.sig.pol {
268 None
269 } else {
270 Some(msg.sig.pol)
271 };
272
273 Ok((
274 res,
275 VerificationResult {
276 public: self.pub_id,
277 private,
278 },
279 ))
280 }
281}
282
283impl From<Error> for JsValue {
284 fn from(err: Error) -> Self {
285 JsError::new(&err.to_string()).into()
286 }
287}
288
289impl From<JsValue> for Error {
290 fn from(e: JsValue) -> Self {
291 Error::JavaScript(e)
292 }
293}