1use wasm_bindgen::prelude::*;
2use ark_serialize::CanonicalDeserialize;
3use ark_std::{test_rng, UniformRand, ops::Mul};
4use ark_bls12_381::{Fr, G1Affine as G1, G2Affine as G2};
5use ark_ec::AffineRepr;
6use etf_crypto_primitives::{
7 ibe::fullident::BfIbe,
8 proofs::verifier::IbeDleqVerifier,
9 client::etf_client::DefaultEtfClient,
10 utils::{convert_to_bytes, hash_to_g1},
11};
12use serde::{Deserialize, Serialize};
13
14use crate::api::{
15 EtfApi, DefaultApi,
16};
17
18pub mod api;
19
20pub enum ApiError {
21 EncryptionError,
22 WasmBindError,
23}
24
25#[wasm_bindgen]
29pub struct EtfApiWrapper {
30 pps: (JsValue, JsValue),
31}
32
33#[wasm_bindgen]
34impl EtfApiWrapper {
35
36 #[wasm_bindgen(constructor)]
38 pub fn create(p: JsValue, q: JsValue) -> Self {
39 Self { pps: (p, q) }
41 }
42
43 #[wasm_bindgen]
44 pub fn version(&self) -> JsValue {
45 serde_wasm_bindgen::to_value(b"v0.0.3-dev").unwrap()
46 }
47
48 #[wasm_bindgen]
53 pub fn encrypt(
54 &self,
55 message_bytes: JsValue, slot_id_bytes: JsValue, t: u8,
58 seed_bytes: JsValue,
59 ) -> Result<JsValue, JsError> {
60 let ibe_pp : Vec<u8> = serde_wasm_bindgen::from_value(self.pps.0.clone())
62 .map_err(|_| JsError::new("could not decode ibe pp"))?;
63 let p_pub : Vec<u8> = serde_wasm_bindgen::from_value(self.pps.1.clone())
64 .map_err(|_| JsError::new("could not decode p pub"))?;
65 let message : Vec<u8> = serde_wasm_bindgen::from_value(message_bytes)
66 .map_err(|_| JsError::new("could not decode message"))?;
67 let slot_ids: Vec<Vec<u8>> = serde_wasm_bindgen::from_value(slot_id_bytes)
68 .map_err(|_| JsError::new("could not decode slot ids"))?;
69 let seed: Vec<u8> = serde_wasm_bindgen::from_value(seed_bytes)
70 .map_err(|_| JsError::new("could not decode seed"))?;
71 let out =
73 DefaultApi::<IbeDleqVerifier, BfIbe, DefaultEtfClient<BfIbe>>::encrypt(
74 ibe_pp, p_pub, &message, slot_ids, t, &seed)
75 .map_err(|_| JsError::new("encrypt failed"))?;
76 serde_wasm_bindgen::to_value(&out)
77 .map_err(|_| JsError::new("could not convert to JsValue"))
78 }
79
80 #[wasm_bindgen]
81 pub fn decrypt(
82 &self,
83 ciphertext_bytes: JsValue, nonce_bytes: JsValue, capsule_bytes: JsValue, sks_bytes: JsValue, ) -> Result<JsValue, JsError> {
88 let ibe_pp : Vec<u8> = serde_wasm_bindgen::from_value(self.pps.0.clone())
89 .map_err(|_| JsError::new("could not decode ibe pp"))?;
90 let ct: Vec<u8> = serde_wasm_bindgen::from_value(ciphertext_bytes)
91 .map_err(|_| JsError::new("could not decode the ciphertext"))?;
92 let nonce: Vec<u8> = serde_wasm_bindgen::from_value(nonce_bytes)
93 .map_err(|_| JsError::new("could not decode the nonce"))?;
94
95 let capsule: Vec<Vec<u8>> = serde_wasm_bindgen::from_value(capsule_bytes)
96 .map_err(|_| JsError::new("could not decode the capsule"))?;
97 let sks: Vec<Vec<u8>> = serde_wasm_bindgen::from_value(sks_bytes)
98 .map_err(|_| JsError::new("could not decode the secret keys"))?;
99 let out =
100 DefaultApi::<IbeDleqVerifier, BfIbe, DefaultEtfClient<BfIbe>>::decrypt(
101 ibe_pp, ct, nonce, capsule, sks)
102 .map_err(|_| JsError::new("decryption failed"))?;
103 serde_wasm_bindgen::to_value(&out)
104 .map_err(|_| JsError::new("could not convert to JsValue"))
105 }
106}
107
108#[derive(Debug, Serialize, Deserialize)]
109pub struct IbeTestParams {
110 pub p: Vec<u8>,
111 pub q: Vec<u8>,
112 pub s: Vec<u8>,
113}
114
115#[wasm_bindgen]
119pub fn random_ibe_params() -> Result<JsValue, JsError> {
120 let ibe_pp: G2 = G2::generator();
121 let s = Fr::rand(&mut test_rng());
122 let p_pub: G2 = ibe_pp.mul(s).into();
123
124 serde_wasm_bindgen::to_value(&IbeTestParams {
125 p: convert_to_bytes::<G2, 96>(ibe_pp).to_vec(),
126 q: convert_to_bytes::<G2, 96>(p_pub).to_vec(),
127 s: convert_to_bytes::<Fr, 32>(s).to_vec(),
128 }).map_err(|_| JsError::new("could not convert ibe test params to JsValue"))
129}
130
131#[wasm_bindgen]
133pub fn ibe_extract(x: JsValue, ids_bytes: JsValue) -> Result<JsValue, JsError> {
134 let ids: Vec<Vec<u8>> = serde_wasm_bindgen::from_value(ids_bytes)
135 .map_err(|_| JsError::new("could not decode ids"))?;
136 let sk_bytes: Vec<u8> = serde_wasm_bindgen::from_value(x)
137 .map_err(|_| JsError::new("could not decode secret x"))?;
138 let s = Fr::deserialize_compressed(&sk_bytes[..]).unwrap();
139 let mut secrets: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
140 for id in ids {
141 let pk = hash_to_g1(&id);
142 let sk = pk.mul(s);
143 let pk_bytes = convert_to_bytes::<G1, 48>(pk);
144 let sk_bytes = convert_to_bytes::<G1, 48>(sk.into());
145 secrets.push((sk_bytes.to_vec(), pk_bytes.to_vec()));
146 }
147
148 serde_wasm_bindgen::to_value(&secrets)
149 .map_err(|_| JsError::new("could not convert secrets to JsValue"))
150}
151
152#[cfg(test)]
153mod test {
154 use super::*;
155 use ark_std::test_rng;
156 use wasm_bindgen_test::*;
157
158 #[wasm_bindgen_test]
159 pub fn wrapper_setup_works() {
160 let x = serde_wasm_bindgen::to_value(&vec![1,2,3,4]).unwrap();
161 let etf = EtfApiWrapper::create(x.clone(), x);
162 let v = etf.version();
163 let version: Vec<u8> = serde_wasm_bindgen::from_value(v).unwrap();
164 assert_eq!(version, b"v0.0.3-dev".to_vec());
165 }
166
167 #[wasm_bindgen_test]
168 pub fn wrapper_can_encrypt() {
169 let message_js = serde_wasm_bindgen::to_value(b"test").unwrap();
170 let slot_ids = vec![vec![1,2,3], vec![2,3,4]];
171 let slot_ids_js = serde_wasm_bindgen::to_value(&slot_ids).unwrap();
172 let seed_js = serde_wasm_bindgen::to_value(b"seed").unwrap();
173
174 let s = Fr::rand(&mut test_rng());
175 let g = G2::rand(&mut test_rng());
176 let p: G2 = g.mul(s).into();
177 let g_bytes = convert_to_bytes::<G2, 96>(g).to_vec();
178 let p_bytes = convert_to_bytes::<G2, 96>(p).to_vec();
179 let x1 = serde_wasm_bindgen::to_value(&g_bytes).unwrap();
180 let x2 = serde_wasm_bindgen::to_value(&p_bytes).unwrap();
181 let etf = EtfApiWrapper::create(x1, x2);
182 match etf.encrypt(message_js, slot_ids_js, 3, seed_js) {
183 Ok(ct) => {
184 assert!(!ct.is_null());
185 },
186 Err(_) =>{
187 panic!("test should pass");
188 }
189 }
190 }
191
192 }