extern crate alloc;
use alloc::format;
use alloc::string::String;
use alloc::vec::Vec;
use lib_q_core::api::AeadOperations;
use lib_q_core::{
AeadKey,
Nonce,
};
use wasm_bindgen::prelude::*;
use crate::{
Algorithm,
AlgorithmCategory,
LibQAeadProvider,
};
fn js_err(msg: impl core::fmt::Display) -> JsValue {
lib_q_core::wasm_common::wasm_js_error("LIB_Q_AEAD", msg)
}
fn parse_algorithm(name: &str) -> Result<Algorithm, JsValue> {
let a = match name.trim() {
"Saturnin" | "saturnin" => Algorithm::Saturnin,
"DuplexSpongeAead" | "Duplex-Sponge-AEAD" | "duplex" => Algorithm::DuplexSpongeAead,
"RomulusN" | "Romulus-N" | "romulus-n" | "romulus" => Algorithm::RomulusN,
other => {
return Err(js_err(format!(
"unknown AEAD algorithm '{other}'; use Saturnin, DuplexSpongeAead, or RomulusN"
)));
}
};
if a.category() != AlgorithmCategory::Aead {
return Err(js_err("internal: parsed non-AEAD"));
}
Ok(a)
}
#[wasm_bindgen]
pub fn aead_encrypt(
algorithm: &str,
key: Vec<u8>,
nonce: Vec<u8>,
plaintext: Vec<u8>,
associated_data: Vec<u8>,
) -> Result<Vec<u8>, JsValue> {
let alg = parse_algorithm(algorithm)?;
let provider = LibQAeadProvider::new().map_err(js_err)?;
let k = AeadKey::new(key);
let n = Nonce::new(nonce);
let ad = if associated_data.is_empty() {
None
} else {
Some(associated_data.as_slice())
};
provider
.encrypt(alg, &k, &n, &plaintext, ad)
.map_err(js_err)
}
#[wasm_bindgen]
pub fn aead_decrypt(
algorithm: &str,
key: Vec<u8>,
nonce: Vec<u8>,
ciphertext: Vec<u8>,
associated_data: Vec<u8>,
) -> Result<Vec<u8>, JsValue> {
let alg = parse_algorithm(algorithm)?;
let provider = LibQAeadProvider::new().map_err(js_err)?;
let k = AeadKey::new(key);
let n = Nonce::new(nonce);
let ad = if associated_data.is_empty() {
None
} else {
Some(associated_data.as_slice())
};
provider
.decrypt(alg, &k, &n, &ciphertext, ad)
.map_err(js_err)
}
#[wasm_bindgen]
pub fn aead_available_algorithms() -> Result<JsValue, JsValue> {
let names: Vec<String> = crate::available_algorithms()
.into_iter()
.map(|a| format!("{a:?}"))
.collect();
serde_wasm_bindgen::to_value(&names).map_err(js_err)
}