pg_core/client/web/
mod.rs1#[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;
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)]
65struct MessageAndSignature {
66 message: Vec<u8>,
67 sig: SignatureExt,
68}
69
70impl<'r, R: RngCore + CryptoRng> Sealer<'r, R, SealerMemoryConfig> {
71 pub fn new(
73 mpk: &PublicKey<CGWKV>,
74 policies: &EncryptionPolicy,
75 pub_sign_key: &SigningKeyExt,
76 rng: &'r mut R,
77 ) -> Result<Self, Error> {
78 let (header, ss) = Header::new(mpk, policies, rng)?;
79 let Algorithm::Aes128Gcm(iv) = header.algo;
80
81 let mut key = [0u8; KEY_SIZE];
82 let mut nonce = [0u8; IV_SIZE];
83 key.copy_from_slice(&ss.0[..KEY_SIZE]);
84 nonce.copy_from_slice(&iv.0[..IV_SIZE]);
85
86 Ok(Self {
87 rng,
88 header,
89 pub_sign_key: pub_sign_key.clone(),
90 priv_sign_key: None,
91 config: SealerMemoryConfig { key, nonce },
92 })
93 }
94
95 pub async fn seal(mut self, message: &Uint8Array) -> Result<Uint8Array, Error> {
97 let mut out = Vec::with_capacity(message.byte_length() as usize + 1024);
98
99 out.extend_from_slice(&PRELUDE);
100 out.extend_from_slice(&VERSION_V3.to_be_bytes());
101 self.header = self.header.with_mode(Mode::InMemory {
102 size: message.byte_length(),
103 });
104
105 let header_buf = bincode::serialize(&self.header)?;
106 out.extend_from_slice(&(header_buf.len() as u32).to_be_bytes());
107 out.extend_from_slice(&header_buf);
108
109 let signer = Signer::new().chain(header_buf);
110 let h_sig = signer.clone().sign(&self.pub_sign_key.key.0, self.rng);
111
112 let h_sig_ext = SignatureExt {
113 sig: h_sig,
114 pol: self.pub_sign_key.policy.clone(),
115 };
116
117 let h_sig_ext_bytes = bincode::serialize(&h_sig_ext)?;
118 out.extend_from_slice(&(h_sig_ext_bytes.len() as u32).to_be_bytes());
119 out.extend_from_slice(&h_sig_ext_bytes);
120
121 let m = message.to_vec();
122 let m_sig_key = self.priv_sign_key.unwrap_or(self.pub_sign_key);
123 let m_sig = signer.chain(&m).sign(&m_sig_key.key.0, self.rng);
124
125 let input = bincode::serialize(&MessageAndSignature {
126 message: m,
127 sig: SignatureExt {
128 sig: m_sig,
129 pol: m_sig_key.policy.clone(),
130 },
131 })?;
132
133 let key = get_key(&self.config.key).await?;
134 let ciphertext = encrypt(
135 &key,
136 &self.config.nonce,
137 &Uint8Array::new_with_length(0),
138 &Uint8Array::from(input.as_slice()),
139 )
140 .await?;
141
142 out.extend_from_slice(&ciphertext.to_vec());
143
144 Ok(Uint8Array::from(out.as_slice()))
145 }
146}
147
148impl Unsealer<Uint8Array, UnsealerMemoryConfig> {
149 pub fn new(input: &Uint8Array, vk: &VerifyingKey) -> Result<Self, Error> {
151 let b = input.to_vec();
152 let (preamble_bytes, b) = b.split_at(PREAMBLE_SIZE);
153 let (version, header_len) = preamble_checked(preamble_bytes)?;
154
155 let (header_bytes, b) = b.split_at(header_len);
156 let (h_sig_len_bytes, b) = b.split_at(SIG_SIZE_SIZE);
157 let h_sig_len = u32::from_be_bytes(h_sig_len_bytes.try_into()?);
158 let (h_sig_bytes, ct) = b.split_at(h_sig_len as usize);
159
160 let h_sig_ext: SignatureExt = bincode::deserialize(h_sig_bytes)?;
161 let id = h_sig_ext.pol.derive_ibs()?;
162
163 let verifier = Verifier::default().chain(&header_bytes);
164
165 if !verifier.clone().verify(&vk.0, &h_sig_ext.sig, &id) {
166 return Err(Error::IncorrectSignature.into());
167 }
168
169 let header: Header = bincode::deserialize(header_bytes)?;
170 let message_len = match header.mode {
171 Mode::InMemory { size } => size as usize,
172 _ => return Err(Error::ModeNotSupported(header.mode).into()),
173 };
174
175 Ok(Self {
176 version,
177 header,
178 pub_id: h_sig_ext.pol,
179 r: Uint8Array::from(ct),
180 verifier,
181 vk: vk.clone(),
182 config: UnsealerMemoryConfig { message_len },
183 })
184 }
185
186 pub async fn unseal(
188 self,
189 ident: &str,
190 usk: &UserSecretKey<CGWKV>,
191 ) -> Result<(Uint8Array, VerificationResult), Error> {
192 let rec_info = self
193 .header
194 .recipients
195 .get(ident)
196 .ok_or_else(|| Error::UnknownIdentifier(ident.to_string()))?;
197
198 let ss = rec_info.decaps(usk)?;
199 let key = get_key(&ss.0[..KEY_SIZE]).await?;
200
201 let Algorithm::Aes128Gcm(iv) = self.header.algo;
202
203 let plain = decrypt(&key, &iv.0, &Uint8Array::new_with_length(0), &self.r)
204 .await?
205 .to_vec();
206
207 let msg: MessageAndSignature = bincode::deserialize(&plain).map_err(Into::<Error>::into)?;
208 let id = msg.sig.pol.derive_ibs()?;
209 let verified = self
210 .verifier
211 .chain(&msg.message)
212 .verify(&self.vk.0, &msg.sig.sig, &id);
213
214 if !verified {
215 return Err(Error::IncorrectSignature.into());
216 }
217
218 debug_assert_eq!(self.config.message_len, msg.message.len());
219
220 let res = Uint8Array::from(msg.message.as_slice());
221
222 let private = if self.pub_id == msg.sig.pol {
223 None
224 } else {
225 Some(msg.sig.pol)
226 };
227
228 Ok((
229 res,
230 VerificationResult {
231 public: self.pub_id,
232 private,
233 },
234 ))
235 }
236}
237
238impl From<Error> for JsValue {
239 fn from(err: Error) -> Self {
240 JsError::new(&err.to_string()).into()
241 }
242}
243
244impl From<JsValue> for Error {
245 fn from(e: JsValue) -> Self {
246 Error::JavaScript(e)
247 }
248}