use std::{
string::String,
ops::Neg
};
use rabe_bn::{Group, Gt, G1, G2, Fr, pairing};
use rand::Rng;
use utils::{
tools::*,
secretsharing::*,
aes::*,
hash::sha3_hash
};
use utils::policy::pest::{PolicyLanguage, parse, PolicyType};
use crate::error::RabeError;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11PublicKey {
pub g1: G1,
pub g2: G2,
pub g1_a: G1,
pub g2_a: G2,
pub e_gg_alpha: Gt,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11MasterKey {
pub g2_alpha: G2,
pub pk: Ghw11PublicKey,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11SecretKey {
pub k: G2,
pub l: G2,
pub attr_key: Vec<Ghw11Attribute>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11Attribute {
pub string: String,
pub k_x: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11TransformKey {
pub k_z: G2,
pub l_z: G2,
pub attr_key_z: Vec<Ghw11Attribute>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11RetrieveKey {
pub z: Fr,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11Ciphertext {
pub policy: (String, PolicyLanguage),
pub c : Gt,
pub c1: G1,
pub ci_di: Vec<(String, G1, G1)>,
pub data: Vec<u8>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Ghw11TransformCiphertext {
pub c : Gt,
pub t : Gt,
}
pub fn setup() -> (Ghw11PublicKey, Ghw11MasterKey) {
let mut rng = rand::thread_rng();
let g1:G1 = rng.gen();
let g2:G2 = rng.gen();
let a:Fr = rng.gen();
let g1_a = g1 * a;
let g2_a = g2 * a;
let alpha:Fr = rng.gen();
let e_gg_alpha = pairing(g1, g2).pow(alpha);
let g2_alpha = g2 * alpha;
let pk = Ghw11PublicKey { g1, g1_a, g2, g2_a, e_gg_alpha};
(
pk.clone(),
Ghw11MasterKey { g2_alpha, pk },
)
}
pub fn keygen(
pk: &Ghw11PublicKey,
msk: &Ghw11MasterKey,
attributes: &[String],
) -> Option<Ghw11SecretKey> {
if attributes.is_empty() || attributes.len() == 0 {
return None;
}
let mut rng = rand::thread_rng();
let r:Fr = rng.gen();
let g2_r = pk.g2 * r;
let k = msk.g2_alpha + pk.g2_a * r;
let mut k_x: Vec<Ghw11Attribute> = Vec::new();
for j in attributes {
k_x.push(Ghw11Attribute {
string: j.to_string(), k_x: (sha3_hash(pk.g2, j.as_str()).expect("could not hash _j") * r), });
}
return Some(Ghw11SecretKey { k, l: g2_r, attr_key: k_x });
}
pub fn tkgen(
sk: Ghw11SecretKey,
) -> Option<(Ghw11TransformKey, Ghw11RetrieveKey)> {
let mut rng = rand::thread_rng();
let z:Fr = rng.gen();
let z_inverse = z.inverse().unwrap();
let k_z = sk.k * z_inverse;
let l_z = sk.l * z_inverse;
let mut attr_key_z: Vec<Ghw11Attribute> = Vec::new();
for k_i in sk.attr_key.iter() {
attr_key_z.push(Ghw11Attribute {
string: k_i.string.clone(), k_x: k_i.k_x * z_inverse,
});
}
return Some((Ghw11TransformKey { k_z, l_z, attr_key_z }, Ghw11RetrieveKey{z}));
}
pub fn encrypt(
pk: &Ghw11PublicKey,
policy: &str,
language: PolicyLanguage,
plaintext: &[u8],
) -> Result<Ghw11Ciphertext, RabeError> {
if plaintext.is_empty() || policy.is_empty() {
RabeError::new("Error in bsw/encrypt: data or policy is empty.");
}
let mut rng = rand::thread_rng();
let secret:Fr = rng.gen();
let msg: Gt = rng.gen();
match parse(policy, language) {
Ok(policy_value) => {
let shares: Vec<(String, Fr)> = gen_shares_policy(secret, &policy_value, None).unwrap();
let c = pk.e_gg_alpha.pow(secret) * msg;
let c1 = pk.g1 * secret;
let mut ci_di: Vec<(String, G1, G1)> = Vec::new();
for (node, i_val) in shares.clone() {
let t_i:Fr = rng.gen();
let j = remove_index(&node);
ci_di.push((node.clone(), pk.g1_a * i_val + sha3_hash(pk.g1, &j).unwrap() * (t_i.neg()), pk.g1 * t_i));
}
match encrypt_symmetric(msg, &plaintext.to_vec()) {
Ok(data) => Ok(Ghw11Ciphertext { policy: (policy.to_string(), language), c, c1, ci_di, data }),
Err(e) => Err(e)
}
}
Err(e) => Err(e)
}
}
pub fn transform(
ct: Ghw11Ciphertext,
tk: Ghw11TransformKey,
) -> Result<Ghw11TransformCiphertext, RabeError> {
let str_attr: Vec<String> = tk
.attr_key_z
.iter()
.map(|_values| {
_values.clone().string
})
.collect::<Vec<_>>();
return match parse(ct.policy.0.as_ref(), ct.policy.1) {
Ok(pol) => {
return if traverse_policy(&str_attr, &pol, PolicyType::Leaf) == false {
Err(RabeError::new("Error: attributes in tk do not match policy in ct."))
} else {
let _pruned = calc_pruned(&str_attr, &pol, None);
match _pruned {
Err(e) => Err(e),
Ok(_p) => {
let (_match, _list) = _p;
let mut coeff_list: Vec<(String, Fr)> = Vec::new();
coeff_list = calc_coefficients(&pol, Some(Fr::one()), coeff_list,None).unwrap();
if _match {
let mut t = Gt::one();
let mut ci_wi = G1::zero();
for _current in _list.iter() {
let _coeff = coeff_list
.iter()
.filter(|_c| _c.0 == _current.1.to_string())
.map(|_c| _c.1)
.nth(0)
.unwrap();
let _tk_attr = tk
.attr_key_z
.iter()
.filter(|_attr| _attr.string == _current.0.to_string())
.nth(0)
.unwrap();
let _ct_attr = ct
.ci_di
.iter()
.filter(|_attr| _attr.0 == _current.1.to_string())
.nth(0)
.unwrap();
ci_wi = ci_wi + _ct_attr.1 * _coeff;
t = t * pairing(_ct_attr.2 * _coeff, _tk_attr.k_x);
}
t = t * pairing(ci_wi, tk.l_z);
t = pairing(ct.c1, tk.k_z) * t.inverse();
Ok(Ghw11TransformCiphertext{c: ct.c, t})
} else {
Err(RabeError::new("Error in Ghw11/decrypt: attributes in sk do not match policy in ct."))
}
}
}
}
},
Err(e) => Err(e)
}
}
pub fn decrypt_out(
pct: Ghw11TransformCiphertext,
rk: Ghw11RetrieveKey,
data: Vec<u8>,
) -> Result<Vec<u8>, RabeError> {
let msg = pct.c * (pct.t.pow(rk.z)).inverse();
decrypt_symmetric(msg, &data)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn or() {
let (pk, msk) = setup();
let mut att_matching = Vec::new();
att_matching.push(String::from("D"));
att_matching.push(String::from("B"));
let mut att_not_matching = Vec::new();
att_not_matching.push(String::from("C"));
att_not_matching.push(String::from("D"));
let match_sk = keygen(&pk, &msk, &att_matching).unwrap();
let not_match_sk = keygen(&pk, &msk, &att_not_matching).unwrap();
let plaintext = String::from("dance like no one's watching, encrypt like everyone is!")
.into_bytes();
let policy = String::from(r#"{"name": "or", "children": [{"name": "A"}, {"name": "B"}]}"#);
let ct_cp = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let (match_tk, match_rk) = tkgen(match_sk).unwrap();
let (not_match_tk, _not_match_rk) = tkgen(not_match_sk).unwrap();
let transform_ct = transform(ct_cp.clone(), match_tk).unwrap();
let not_match_transform_ct = transform(ct_cp.clone(), not_match_tk);
assert_eq!(not_match_transform_ct.is_ok(), false);
let _match = decrypt_out(transform_ct, match_rk, ct_cp.data.clone());
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
}
#[test]
fn and2() -> (){
let (pk, msk) = setup();
let att_bob = vec![String::from("attr0"),String::from("attr1")];
let bob_sk = keygen(&pk, &msk, &att_bob).unwrap();
let plaintext =
String::from("ghw11 OABE").into_bytes();
let policy = String::from(r#"{"name": "and", "children": [{"name": "attr0"}, {"name": "attr1"}]}"#);
let ct_cp = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let (tk, rk) = tkgen(bob_sk).unwrap();
let transform_ct = transform(ct_cp.clone(), tk).unwrap();
let _matching = decrypt_out(transform_ct, rk, ct_cp.data).unwrap();
assert_eq!(_matching, plaintext);
let decrypt_plaintext = String::from_utf8(_matching).unwrap();
println!("decrypt plaintext:{:?}", decrypt_plaintext);
}
#[test]
fn and10() {
let (pk, msk) = setup();
let mut att_matching: Vec<String> = Vec::new();
for n in 1..11 {
att_matching.push(["attr".to_string(), n.to_string()].concat());
}
let mut att_not_matching: Vec<String> = Vec::new();
att_not_matching.push(String::from("attr201"));
att_not_matching.push(String::from("attr200"));
let match_sk = keygen(&pk, &msk, &att_matching).unwrap();
let not_match_sk = keygen(&pk, &msk, &att_not_matching).unwrap();
let plaintext = String::from("dance like no one's watching, encrypt like everyone is!")
.into_bytes();
let mut _policy = String::from("{\"name\": \"and\", \"children\": [");
for n in 1..11 {
let mut _current = String::from("{\"name\": \"attr");
if n < 10 {
_current.push_str(&n.to_string());
_current.push_str(&String::from("\"}, "));
} else {
_current.push_str(&n.to_string());
_current.push_str(&String::from("\"}]"));
}
_policy.push_str(&_current);
}
_policy.push_str(&String::from("}"));
let ct_cp = encrypt(&pk, &_policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let (match_tk, match_rk) = tkgen(match_sk).unwrap();
let (not_match_tk, _not_match_rk) = tkgen(not_match_sk).unwrap();
let transform_ct = transform(ct_cp.clone(), match_tk).unwrap();
let not_match_transform_ct = transform(ct_cp.clone(), not_match_tk);
assert_eq!(not_match_transform_ct.is_ok(), false);
let _match = decrypt_out(transform_ct, match_rk, ct_cp.data.clone());
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
}
}