#![allow(non_upper_case_globals)]
use cosmian_cover_crypt::{
abe_policy::AccessPolicy, Covercrypt, EncryptedHeader, MasterPublicKey, UserSecretKey,
};
use cosmian_crypto_core::{
bytes_ser_de::{Deserializer, Serializable, Serializer},
Aes256Gcm, FixedSizeCBytes, SymmetricKey,
};
use js_sys::{Object, Reflect, Uint8Array};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn webassembly_encrypt_hybrid_header(
policy_bytes: Vec<u8>,
access_policy: String,
public_key_bytes: Uint8Array,
header_metadata: Uint8Array,
authentication_data: Uint8Array,
) -> Result<Uint8Array, JsValue> {
let policy = wasm_unwrap!(
serde_json::from_slice(&policy_bytes),
"Error deserializing policy"
);
let access_policy = wasm_unwrap!(
AccessPolicy::from_boolean_expression(&access_policy),
"Error reading access policy"
);
let public_key = wasm_unwrap!(
MasterPublicKey::deserialize(&public_key_bytes.to_vec()),
"Error deserializing public key"
);
let header_metadata = if header_metadata.is_null() {
None
} else {
Some(header_metadata.to_vec())
};
let authentication_data = if authentication_data.is_null() {
None
} else {
Some(authentication_data.to_vec())
};
let (symmetric_key, encrypted_header) = wasm_unwrap!(
EncryptedHeader::generate(
&Covercrypt::default(),
&policy,
&public_key,
&access_policy,
header_metadata.as_deref(),
authentication_data.as_deref(),
),
"Error encrypting header"
);
let symmetric_key_bytes = symmetric_key.to_bytes();
let encrypted_header_bytes = wasm_unwrap!(
encrypted_header.serialize(),
"Error serializing encrypted header"
);
let mut res = Vec::with_capacity(symmetric_key_bytes.len() + encrypted_header_bytes.len());
res.extend_from_slice(&symmetric_key_bytes);
res.extend_from_slice(&encrypted_header_bytes);
Ok(Uint8Array::from(res.as_slice()))
}
#[wasm_bindgen]
pub fn webassembly_decrypt_hybrid_header(
usk_bytes: Uint8Array,
encrypted_header_bytes: Uint8Array,
authentication_data: Uint8Array,
) -> Result<Uint8Array, JsValue> {
let usk = wasm_unwrap!(
UserSecretKey::deserialize(usk_bytes.to_vec().as_slice()),
"Error deserializing user decryption key"
);
let authentication_data = if authentication_data.is_null() {
None
} else {
Some(authentication_data.to_vec())
};
let encrypted_header = wasm_unwrap!(
EncryptedHeader::deserialize(encrypted_header_bytes.to_vec().as_slice(),),
"Error deserializing encrypted header"
);
let cleartext_header = wasm_unwrap!(
encrypted_header.decrypt(&Covercrypt::default(), &usk, authentication_data.as_deref(),),
"Error decrypting header"
);
Ok(Uint8Array::from(
wasm_unwrap!(
cleartext_header.serialize(),
"Error serializing decrypted header"
)
.as_slice(),
))
}
#[wasm_bindgen]
pub fn webassembly_encrypt_symmetric_block(
symmetric_key_bytes: Uint8Array,
plaintext_bytes: Uint8Array,
authentication_data: Uint8Array,
) -> Result<Uint8Array, JsValue> {
if plaintext_bytes.length() == 0 {
return Err(JsValue::from_str("Plaintext value is empty"));
}
let symmetric_key_fixed: [u8; Aes256Gcm::KEY_LENGTH] = wasm_unwrap!(
symmetric_key_bytes.to_vec().try_into(),
"Error converting symmetric key"
);
let symmetric_key = wasm_unwrap!(
SymmetricKey::try_from_bytes(symmetric_key_fixed),
"Error parsing symmetric key"
);
let authentication_data = if authentication_data.is_null() {
None
} else {
Some(authentication_data.to_vec())
};
let ciphertext = wasm_unwrap!(
Covercrypt::default().encrypt(
&symmetric_key,
&plaintext_bytes.to_vec(),
authentication_data.as_deref(),
),
"Error encrypting block"
);
Ok(Uint8Array::from(&ciphertext[..]))
}
#[wasm_bindgen]
pub fn webassembly_decrypt_symmetric_block(
symmetric_key_bytes: Uint8Array,
encrypted_bytes: Uint8Array,
authentication_data: Uint8Array,
) -> Result<Uint8Array, JsValue> {
let symmetric_key_fixed: [u8; Aes256Gcm::KEY_LENGTH] = wasm_unwrap!(
symmetric_key_bytes.to_vec().try_into(),
"Error converting symmetric key"
);
let symmetric_key = wasm_unwrap!(
SymmetricKey::try_from_bytes(symmetric_key_fixed),
"Error parsing symmetric key"
);
let authentication_data = if authentication_data.is_null() {
None
} else {
Some(authentication_data.to_vec())
};
let cleartext = wasm_unwrap!(
Covercrypt::default().decrypt(
&symmetric_key,
&encrypted_bytes.to_vec(),
authentication_data.as_deref(),
),
"Error decrypting block"
);
Ok(Uint8Array::from(&cleartext[..]))
}
#[wasm_bindgen]
pub fn webassembly_hybrid_encrypt(
policy_bytes: Vec<u8>,
access_policy: String,
pk: Uint8Array,
plaintext: Uint8Array,
header_metadata: Uint8Array,
authentication_data: Uint8Array,
) -> Result<Uint8Array, JsValue> {
let policy = wasm_unwrap!(
serde_json::from_slice(&policy_bytes),
"Error parsing policy"
);
let access_policy = wasm_unwrap!(
AccessPolicy::from_boolean_expression(&access_policy),
"Error reading access policy"
);
let pk = wasm_unwrap!(
MasterPublicKey::deserialize(&pk.to_vec()),
"Error parsing public key"
);
let header_metadata = if header_metadata.is_null() {
None
} else {
Some(header_metadata.to_vec())
};
let authentication_data = if authentication_data.is_null() {
None
} else {
Some(authentication_data.to_vec())
};
let cover_crypt = Covercrypt::default();
let (symmetric_key, encrypted_header) = wasm_unwrap!(
EncryptedHeader::generate(
&cover_crypt,
&policy,
&pk,
&access_policy,
header_metadata.as_deref(),
authentication_data.as_deref(),
),
"Error encrypting header"
);
let ciphertext = wasm_unwrap!(
cover_crypt.encrypt(
&symmetric_key,
&plaintext.to_vec(),
authentication_data.as_deref(),
),
"Error encrypting symmetric plaintext"
);
let mut ser = Serializer::with_capacity(encrypted_header.length() + ciphertext.len());
wasm_unwrap!(
ser.write(&encrypted_header),
"Error serializing encrypted header"
);
wasm_unwrap!(ser.write_array(&ciphertext), "Error writing ciphertext");
Ok(Uint8Array::from(ser.finalize().as_slice()))
}
#[wasm_bindgen]
pub fn webassembly_hybrid_decrypt(
usk_bytes: Uint8Array,
encrypted_bytes: Uint8Array,
authentication_data: Uint8Array,
) -> Result<Uint8Array, JsValue> {
let encrypted_bytes = encrypted_bytes.to_vec();
let mut de = Deserializer::new(&encrypted_bytes);
let header = wasm_unwrap!(
de.read::<EncryptedHeader>(),
"Error deserializing encrypted header"
);
let ciphertext = de.finalize();
let usk = wasm_unwrap!(
UserSecretKey::deserialize(usk_bytes.to_vec().as_slice()),
"Error deserializing user secret key"
);
let authentication_data = if authentication_data.is_null() {
None
} else {
Some(authentication_data.to_vec())
};
let cover_crypt = Covercrypt::default();
let cleartext_header = wasm_unwrap!(
header.decrypt(&cover_crypt, &usk, authentication_data.as_deref()),
"Error decrypting header"
);
let cleartext = wasm_unwrap!(
cover_crypt.decrypt(
&cleartext_header.symmetric_key,
ciphertext.as_slice(),
authentication_data.as_deref(),
),
"Error decrypting ciphertext"
);
let mut ser = Serializer::new();
wasm_unwrap!(
ser.write_vec(cleartext_header.metadata.unwrap_or_default().as_slice()),
"Cannot serialize the decrypted header metadata into response"
);
wasm_unwrap!(
ser.write_array(cleartext.as_slice()),
"Cannot serialize the cleartext into response"
);
Ok(Uint8Array::from(ser.finalize().as_slice()))
}
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "{ encryptedHeader: Uint8Array, ciphertext: Uint8Array }")]
pub type EncryptedHeaderCiphertext;
}
#[wasm_bindgen]
pub fn webassembly_split_encrypted_header(
encrypted_bytes: Uint8Array,
) -> Result<EncryptedHeaderCiphertext, JsValue> {
let encrypted_bytes = encrypted_bytes.to_vec();
let mut de = Deserializer::new(&encrypted_bytes);
let header = wasm_unwrap!(
de.read::<EncryptedHeader>(),
"Error deserializing encrypted header"
);
let ciphertext = de.finalize();
let obj = Object::new();
Reflect::set(
&obj,
&JsValue::from_str("encryptedHeader"),
&Uint8Array::from(
wasm_unwrap!(header.serialize(), "Cannot serialize encrypted header")
.to_vec()
.as_slice(),
),
)?;
Reflect::set(
&obj,
&JsValue::from_str("ciphertext"),
&Uint8Array::from(ciphertext.as_slice()),
)?;
Ok(EncryptedHeaderCiphertext::from(JsValue::from(obj)))
}