1use std::collections::HashMap;
6use wasm_bindgen::prelude::*;
7
8use crate::{
9 Algorithm, CompressionParameters, EncParameters, FormatFlags, KemParameters, PqcBinaryFormat,
10 PqcMetadata, SigParameters,
11};
12
13#[wasm_bindgen]
15pub struct WasmAlgorithm {
16 inner: Algorithm,
17}
18
19#[wasm_bindgen]
20impl WasmAlgorithm {
21 #[wasm_bindgen(constructor)]
23 pub fn new(name: &str) -> Result<WasmAlgorithm, JsValue> {
24 let inner = match name.to_lowercase().as_str() {
25 "classical" => Algorithm::Classical,
26 "hybrid" => Algorithm::Hybrid,
27 "post-quantum" | "postquantum" => Algorithm::PostQuantum,
28 "ml-kem-1024" | "mlkem1024" => Algorithm::MlKem1024,
29 "multi-algorithm" | "multialgorithm" => Algorithm::MultiAlgorithm,
30 "multi-kem" | "multikem" => Algorithm::MultiKem,
31 "multi-kem-triple" | "multikemtriple" => Algorithm::MultiKemTriple,
32 "quad-layer" | "quadlayer" => Algorithm::QuadLayer,
33 "pq3-stack" | "pq3stack" => Algorithm::Pq3Stack,
34 "lattice-code-hybrid" | "latticecodehybrid" => Algorithm::LatticeCodeHybrid,
35 _ => {
36 return Err(JsValue::from_str(&format!("Unknown algorithm: {}", name)));
37 }
38 };
39 Ok(Self { inner })
40 }
41
42 #[wasm_bindgen(getter)]
44 pub fn name(&self) -> String {
45 self.inner.name().to_string()
46 }
47
48 #[wasm_bindgen(getter)]
50 pub fn id(&self) -> u16 {
51 self.inner.as_id()
52 }
53
54 #[wasm_bindgen(js_name = supportedAlgorithms)]
56 pub fn supported_algorithms() -> Vec<JsValue> {
57 vec![
58 "classical",
59 "hybrid",
60 "post-quantum",
61 "ml-kem-1024",
62 "multi-algorithm",
63 "multi-kem",
64 "multi-kem-triple",
65 "quad-layer",
66 "pq3-stack",
67 "lattice-code-hybrid",
68 ]
69 .into_iter()
70 .map(JsValue::from_str)
71 .collect()
72 }
73}
74
75#[wasm_bindgen]
77pub struct WasmEncParameters {
78 inner: EncParameters,
79}
80
81#[wasm_bindgen]
82impl WasmEncParameters {
83 #[wasm_bindgen(constructor)]
85 pub fn new(iv: Vec<u8>, tag: Vec<u8>) -> Self {
86 Self {
87 inner: EncParameters {
88 iv,
89 tag,
90 params: HashMap::new(),
91 },
92 }
93 }
94
95 #[wasm_bindgen(getter)]
97 pub fn iv(&self) -> Vec<u8> {
98 self.inner.iv.clone()
99 }
100
101 #[wasm_bindgen(setter)]
103 pub fn set_iv(&mut self, iv: Vec<u8>) {
104 self.inner.iv = iv;
105 }
106
107 #[wasm_bindgen(getter)]
109 pub fn tag(&self) -> Vec<u8> {
110 self.inner.tag.clone()
111 }
112
113 #[wasm_bindgen(setter)]
115 pub fn set_tag(&mut self, tag: Vec<u8>) {
116 self.inner.tag = tag;
117 }
118}
119
120#[wasm_bindgen]
122pub struct WasmKemParameters {
123 inner: KemParameters,
124}
125
126#[wasm_bindgen]
127impl WasmKemParameters {
128 #[wasm_bindgen(constructor)]
130 pub fn new(public_key: Vec<u8>, ciphertext: Vec<u8>) -> Self {
131 Self {
132 inner: KemParameters {
133 public_key,
134 ciphertext,
135 params: HashMap::new(),
136 },
137 }
138 }
139
140 #[wasm_bindgen(getter)]
142 pub fn public_key(&self) -> Vec<u8> {
143 self.inner.public_key.clone()
144 }
145
146 #[wasm_bindgen(getter)]
148 pub fn ciphertext(&self) -> Vec<u8> {
149 self.inner.ciphertext.clone()
150 }
151}
152
153#[wasm_bindgen]
155pub struct WasmSigParameters {
156 inner: SigParameters,
157}
158
159#[wasm_bindgen]
160impl WasmSigParameters {
161 #[wasm_bindgen(constructor)]
163 pub fn new(public_key: Vec<u8>, signature: Vec<u8>) -> Self {
164 Self {
165 inner: SigParameters {
166 public_key,
167 signature,
168 params: HashMap::new(),
169 },
170 }
171 }
172
173 #[wasm_bindgen(getter)]
175 pub fn public_key(&self) -> Vec<u8> {
176 self.inner.public_key.clone()
177 }
178
179 #[wasm_bindgen(getter)]
181 pub fn signature(&self) -> Vec<u8> {
182 self.inner.signature.clone()
183 }
184}
185
186#[wasm_bindgen]
188pub struct WasmCompressionParameters {
189 inner: CompressionParameters,
190}
191
192#[wasm_bindgen]
193impl WasmCompressionParameters {
194 #[wasm_bindgen(constructor)]
196 pub fn new(algorithm: String, level: u8, original_size: u64) -> Self {
197 Self {
198 inner: CompressionParameters {
199 algorithm,
200 level,
201 original_size,
202 params: HashMap::new(),
203 },
204 }
205 }
206
207 #[wasm_bindgen(getter)]
209 pub fn algorithm(&self) -> String {
210 self.inner.algorithm.clone()
211 }
212
213 #[wasm_bindgen(getter)]
215 pub fn level(&self) -> u8 {
216 self.inner.level
217 }
218
219 #[wasm_bindgen(getter)]
221 pub fn original_size(&self) -> u64 {
222 self.inner.original_size
223 }
224}
225
226#[wasm_bindgen]
228pub struct WasmPqcMetadata {
229 enc_params: WasmEncParameters,
230 kem_params: Option<WasmKemParameters>,
231 sig_params: Option<WasmSigParameters>,
232 compression_params: Option<WasmCompressionParameters>,
233}
234
235#[wasm_bindgen]
236impl WasmPqcMetadata {
237 #[wasm_bindgen(constructor)]
239 pub fn new(enc_params: WasmEncParameters) -> Self {
240 Self {
241 enc_params,
242 kem_params: None,
243 sig_params: None,
244 compression_params: None,
245 }
246 }
247
248 #[wasm_bindgen(js_name = setKemParams)]
250 pub fn set_kem_params(&mut self, kem_params: WasmKemParameters) {
251 self.kem_params = Some(kem_params);
252 }
253
254 #[wasm_bindgen(js_name = setSigParams)]
256 pub fn set_sig_params(&mut self, sig_params: WasmSigParameters) {
257 self.sig_params = Some(sig_params);
258 }
259
260 #[wasm_bindgen(js_name = setCompressionParams)]
262 pub fn set_compression_params(&mut self, compression_params: WasmCompressionParameters) {
263 self.compression_params = Some(compression_params);
264 }
265
266 fn to_rust(&self) -> PqcMetadata {
267 PqcMetadata {
268 kem_params: self.kem_params.as_ref().map(|k| k.inner.clone()),
269 sig_params: self.sig_params.as_ref().map(|s| s.inner.clone()),
270 enc_params: self.enc_params.inner.clone(),
271 compression_params: self.compression_params.as_ref().map(|c| c.inner.clone()),
272 custom: HashMap::new(),
273 }
274 }
275}
276
277#[wasm_bindgen]
279pub struct WasmFormatFlags {
280 inner: FormatFlags,
281}
282
283#[wasm_bindgen]
284impl WasmFormatFlags {
285 #[wasm_bindgen(constructor)]
287 pub fn new() -> Self {
288 Self {
289 inner: FormatFlags::new(),
290 }
291 }
292
293 #[wasm_bindgen(js_name = withCompression)]
295 pub fn with_compression(&self) -> WasmFormatFlags {
296 Self {
297 inner: self.inner.with_compression(),
298 }
299 }
300
301 #[wasm_bindgen(js_name = withStreaming)]
303 pub fn with_streaming(&self) -> WasmFormatFlags {
304 Self {
305 inner: self.inner.with_streaming(),
306 }
307 }
308
309 #[wasm_bindgen(js_name = withAdditionalAuth)]
311 pub fn with_additional_auth(&self) -> WasmFormatFlags {
312 Self {
313 inner: self.inner.with_additional_auth(),
314 }
315 }
316
317 #[wasm_bindgen(js_name = withExperimental)]
319 pub fn with_experimental(&self) -> WasmFormatFlags {
320 Self {
321 inner: self.inner.with_experimental(),
322 }
323 }
324
325 #[wasm_bindgen(js_name = hasCompression)]
327 pub fn has_compression(&self) -> bool {
328 self.inner.has_compression()
329 }
330
331 #[wasm_bindgen(js_name = hasStreaming)]
333 pub fn has_streaming(&self) -> bool {
334 self.inner.has_streaming()
335 }
336
337 #[wasm_bindgen(js_name = hasAdditionalAuth)]
339 pub fn has_additional_auth(&self) -> bool {
340 self.inner.has_additional_auth()
341 }
342
343 #[wasm_bindgen(js_name = hasExperimental)]
345 pub fn has_experimental(&self) -> bool {
346 self.inner.has_experimental()
347 }
348}
349
350#[wasm_bindgen]
352pub struct WasmPqcBinaryFormat {
353 inner: PqcBinaryFormat,
354}
355
356#[wasm_bindgen]
357impl WasmPqcBinaryFormat {
358 #[wasm_bindgen(constructor)]
365 pub fn new(
366 algorithm: WasmAlgorithm,
367 metadata: WasmPqcMetadata,
368 data: Vec<u8>,
369 ) -> WasmPqcBinaryFormat {
370 let rust_metadata = metadata.to_rust();
371 let inner = PqcBinaryFormat::new(algorithm.inner, rust_metadata, data);
372 Self { inner }
373 }
374
375 #[wasm_bindgen(js_name = withFlags)]
383 pub fn with_flags(
384 algorithm: WasmAlgorithm,
385 flags: WasmFormatFlags,
386 metadata: WasmPqcMetadata,
387 data: Vec<u8>,
388 ) -> WasmPqcBinaryFormat {
389 let rust_metadata = metadata.to_rust();
390 let inner = PqcBinaryFormat::with_flags(algorithm.inner, flags.inner, rust_metadata, data);
391 Self { inner }
392 }
393
394 #[wasm_bindgen(js_name = toBytes)]
399 pub fn to_bytes(&self) -> Result<Vec<u8>, JsValue> {
400 self.inner
401 .to_bytes()
402 .map_err(|e| JsValue::from_str(&e.to_string()))
403 }
404
405 #[wasm_bindgen(js_name = fromBytes)]
411 pub fn from_bytes(data: &[u8]) -> Result<WasmPqcBinaryFormat, JsValue> {
412 let inner =
413 PqcBinaryFormat::from_bytes(data).map_err(|e| JsValue::from_str(&e.to_string()))?;
414 Ok(Self { inner })
415 }
416
417 pub fn validate(&self) -> Result<(), JsValue> {
421 self.inner
422 .validate()
423 .map_err(|e| JsValue::from_str(&e.to_string()))
424 }
425
426 #[wasm_bindgen(getter)]
430 pub fn algorithm(&self) -> WasmAlgorithm {
431 WasmAlgorithm {
432 inner: self.inner.algorithm(),
433 }
434 }
435
436 #[wasm_bindgen(getter)]
440 pub fn data(&self) -> Vec<u8> {
441 self.inner.data().to_vec()
442 }
443
444 #[wasm_bindgen(getter)]
448 pub fn flags(&self) -> WasmFormatFlags {
449 WasmFormatFlags {
450 inner: self.inner.flags(),
451 }
452 }
453
454 #[wasm_bindgen(js_name = totalSize)]
458 pub fn total_size(&self) -> usize {
459 self.inner.total_size()
460 }
461}
462
463#[wasm_bindgen(js_name = getVersion)]
465pub fn get_version() -> String {
466 crate::VERSION.to_string()
467}
468
469#[wasm_bindgen(js_name = getBinaryVersion)]
471pub fn get_binary_version() -> u8 {
472 crate::PQC_BINARY_VERSION
473}