1use etf_crypto_primitives::{
2 proofs::{dleq::DLEQProof, verifier::DleqVerifier},
3 ibe::fullident::Ibe,
4 client::etf_client::{EtfClient, AesIbeCt},
5};
6
7use rand_chacha::ChaCha20Rng;
8use ark_std::rand::SeedableRng;
9use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
10
11#[derive(Debug)]
12pub enum Error {
13 EncryptionError,
14 DecryptionError,
15}
16
17pub trait EtfApi<D: DleqVerifier, I: Ibe, E: EtfClient<I>> {
19
20 fn verify(
22 id: Vec<u8>,
23 dleq_proof: DLEQProof,
24 extras: Vec<u8>,
25 ) -> bool;
26
27 fn encrypt(
29 ibe_pp_bytes: Vec<u8>,
30 p_pub: Vec<u8>,
31 message: &[u8],
32 slot_ids: Vec<Vec<u8>>,
33 t: u8,
34 seed: &[u8],
35 ) -> Result<AesIbeCt, Error>;
36
37 fn decrypt(
39 ibe_pp_bytes: Vec<u8>,
40 ciphertext: Vec<u8>,
41 nonce: Vec<u8>,
42 capsule: Vec<Vec<u8>>,
43 sks: Vec<Vec<u8>>,
44 ) -> Result<Vec<u8>, Error>;
45}
46
47#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
50pub struct DefaultApi<D: DleqVerifier, I: Ibe, E: EtfClient<I>> {
52 _d: ark_std::marker::PhantomData<fn() -> D>,
54 _i: ark_std::marker::PhantomData<fn() -> I>,
55 _e: ark_std::marker::PhantomData<fn() -> E>,
56}
57
58impl<D: DleqVerifier, I: Ibe, E: EtfClient<I>> EtfApi<D, I, E> for DefaultApi<D, I, E> {
59
60 fn verify(
69 id: Vec<u8>,
70 proof: DLEQProof,
71 extras: Vec<u8>,
72 ) -> bool {
73 D::verify(id, proof, extras)
74 }
75
76 fn encrypt(
81 ibe_pp_bytes: Vec<u8>,
82 p_pub_bytes: Vec<u8>,
83 message: &[u8],
84 slot_ids: Vec<Vec<u8>>,
85 t: u8,
86 seed: &[u8],
87 ) -> Result<AesIbeCt, Error> {
88 let seed_hash = etf_crypto_primitives::utils::sha256
89 (&etf_crypto_primitives::utils::sha256(seed));
90 let rng = ChaCha20Rng::from_seed(seed_hash.try_into().expect("should be 32 bytes; qed"));
91 let res = E::encrypt(ibe_pp_bytes, p_pub_bytes, message, slot_ids, t, rng)
92 .map_err(|_| Error::EncryptionError)?;
93 Ok(res)
94 }
95
96 fn decrypt(
97 ibe_pp_bytes: Vec<u8>,
98 ciphertext: Vec<u8>,
99 nonce: Vec<u8>,
100 capsule: Vec<Vec<u8>>,
101 sks: Vec<Vec<u8>>,
102 ) -> Result<Vec<u8>, Error> {
103 let res = E::decrypt(ibe_pp_bytes, ciphertext, nonce, capsule, sks)
104 .map_err(|_| Error::DecryptionError)?;
105 Ok(res)
106 }
107}
108
109#[cfg(test)]
110pub mod tests {
111 use super::*;
112 use ark_std::{test_rng, UniformRand, ops::Mul, rand::{CryptoRng, Rng}};
113 use ark_bls12_381::{G1Affine as G1, G2Affine as G2, G1Projective, G2Projective, Fr};
114 use ark_ec::AffineRepr;
115 use ark_serialize::CanonicalSerialize;
116 use etf_crypto_primitives::{
117 utils::hash_to_g1,
118 client::etf_client::{AesIbeCt, ClientError},
119 ibe::fullident::{IbeCiphertext, Ibe},
120 encryption::aes::AESOutput,
121 utils::convert_to_bytes,
122 };
123
124
125 struct MockDleqVerifier;
127
128 impl DleqVerifier for MockDleqVerifier {
129 fn verify(_id: Vec<u8>, _proof: DLEQProof, _extras: Vec<u8>) -> bool {
131 true
132 }
133 }
134
135 struct MockEtfClient;
137
138 impl<I: Ibe> EtfClient<I> for MockEtfClient {
139 fn encrypt<R: Rng + CryptoRng + Sized>(
142 _p: Vec<u8>, _q: Vec<u8>, _m: &[u8], _ids: Vec<Vec<u8>>, _t: u8, _rng: R,
143 ) -> Result<AesIbeCt, ClientError> {
144 Ok(AesIbeCt {
145 aes_ct: AESOutput {
146 ciphertext: vec![1, 2, 3],
147 nonce: vec![2, 3, 4],
148 key: vec![3, 4, 5],
149 },
150 etf_ct: vec![vec![4], vec![5], vec![6]].into(),
151 })
152 }
153 fn decrypt(
154 _p: Vec<u8>,
155 _ct: Vec<u8>,
156 _nonce: Vec<u8>,
157 _capsule: Vec<Vec<u8>>,
158 _secrets: Vec<Vec<u8>>
159 ) -> Result<Vec<u8>, ClientError> {
160 Ok(vec![5, 6, 7])
161 }
162 }
163
164 struct MockIbe;
165
166 impl Ibe for MockIbe {
167 fn encrypt<R: Rng + Sized>(
168 ibe_pp: G2Projective,
169 _p_pub: G2Projective,
170 _message: &[u8;32],
171 _identity: &[u8],
172 _rng: R
173 ) -> IbeCiphertext {
174 IbeCiphertext{ u: ibe_pp, v: Vec::new(), w: Vec::new() }
175 }
176
177 fn decrypt(_ibe_pp: G2Projective, _ciphertext: IbeCiphertext, _sk: G1Projective) -> Vec<u8> {
178 Vec::new()
179 }
180 }
181
182 #[test]
183 fn default_api_can_verify() {
184 let x = Fr::rand(&mut test_rng());
185 let id = b"test";
186 let g = G1::generator();
187 let h = hash_to_g1(id);
188
189
190 let ibe_pp: G2 = G2::generator().into();
192 let s = Fr::rand(&mut test_rng());
193 let p_pub: G2 = ibe_pp.mul(s).into();
194
195 let mut ibe_pp_bytes = Vec::new();
196 ibe_pp.serialize_compressed(&mut ibe_pp_bytes).unwrap();
197
198 let mut p_pub_bytes = Vec::new();
199 p_pub.serialize_compressed(&mut p_pub_bytes).unwrap();
200
201 let proof = DLEQProof::new(x, g, h, vec![], test_rng());
202 assert!(
203 DefaultApi::<MockDleqVerifier, MockIbe, MockEtfClient>::verify(
204 id.to_vec(), proof, vec![]) == true);
205 }
206
207 #[test]
208 fn api_encryption_works() {
209 let message = b"this is a test";
210 let slot_ids = vec![b"sl1".to_vec(), b"sl2".to_vec(), b"sl3".to_vec()];
211 let t = 2;
212 let ibe_pp: G2 = G2::generator().into();
213 let s = Fr::rand(&mut test_rng());
214 let p_pub: G2 = ibe_pp.mul(s).into();
215
216 let ibe_pp_bytes = convert_to_bytes::<G2, 96>(ibe_pp);
217 let p_pub_bytes = convert_to_bytes::<G2, 96>(p_pub);
218
219 match DefaultApi::<MockDleqVerifier, MockIbe, MockEtfClient>::
220 encrypt(ibe_pp_bytes.to_vec(), p_pub_bytes.to_vec(), message, slot_ids, t, b"seed") {
221 Ok(_) => { },
222 Err(_) => { panic!("the encrypt call should work") },
223 }
224 }
225
226 #[test]
227 fn api_decryption_works() {
228 match DefaultApi::<MockDleqVerifier, MockIbe, MockEtfClient>::
229 decrypt(vec![], vec![], vec![], vec![vec![1]], vec![]) {
230 Ok(_) => { },
231 Err(_) => { panic!("the decrypt call should work") },
232 }
233 }
234}