use std::string::String;
use rand::Rng;
use rabe_bn::{Fr, G1, G2, Gt, pairing};
use utils::{
secretsharing::{
calc_coefficients,
calc_pruned
},
policy::msp::AbePolicy,
tools::*,
aes::*,
hash::sha3_hash
};
use utils::policy::pest::{PolicyLanguage, parse, PolicyType};
use utils::secretsharing::{gen_shares_policy, remove_index};
use crate::error::RabeError;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "borsh")]
use borsh::{BorshSerialize, BorshDeserialize};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Aw11GlobalKey {
pub g1: G1,
pub g2: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Aw11PublicKey {
pub attr: Vec<(String, Gt, G2)>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Aw11MasterKey {
pub attr: Vec<(String, Fr, Fr)>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Aw11Ciphertext {
pub policy: (String, PolicyLanguage),
pub c_0: Gt,
pub c: Vec<(String, Gt, G2, G2)>,
pub ct: Vec<u8>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Aw11SecretKey {
pub gid: String,
pub attr: Vec<(String, G1)>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Aw11GlobalContext {
pub key: Aw11GlobalKey,
}
pub fn setup() -> Aw11GlobalKey {
let mut rng = rand::thread_rng();
Aw11GlobalKey {
g1: rng.gen(),
g2: rng.gen(),
}
}
pub fn authgen(
gk: &Aw11GlobalKey,
attributes: &[&str],
) -> Option<(Aw11PublicKey, Aw11MasterKey)> {
if attributes.is_empty() {
return None;
}
let mut rng = rand::thread_rng();
let mut sk: Vec<(String, Fr, Fr)> = Vec::new(); let mut pk: Vec<(String, Gt, G2)> = Vec::new(); for attr in attributes {
let name = attr.to_string().to_uppercase();
let alpha_i:Fr = rng.gen();
let y_i:Fr = rng.gen();
sk.push((name.clone(), alpha_i, y_i));
pk.push((
name,
pairing(gk.g1, gk.g2).pow(alpha_i),
gk.g2 * y_i,
));
}
return Some((Aw11PublicKey { attr: pk }, Aw11MasterKey { attr: sk }));
}
pub fn keygen(
gk: &Aw11GlobalKey,
msk: &Aw11MasterKey,
name: &str,
attributes: &[&str],
) -> Result<Aw11SecretKey, RabeError> {
if attributes.is_empty() {
Err(RabeError::new("empty _attributes"))
}
else if name.is_empty() {
Err(RabeError::new("empty _name"))
}
else {
let mut _sk: Aw11SecretKey = Aw11SecretKey {
gid: name.to_string(),
attr: Vec::new(),
};
for _attribute in attributes {
if let Err(e) = add_to_attribute(gk, msk, _attribute, &mut _sk) {
return Err(e);
}
}
Ok(_sk)
}
}
pub fn add_to_attribute(
gk: &Aw11GlobalKey,
msk: &Aw11MasterKey,
attribute: &str,
sk: &mut Aw11SecretKey,
) -> Result<(), RabeError> {
if attribute.is_empty() {
Err(RabeError::new("empty _attributes"))
}
else if sk.gid.is_empty() {
Err(RabeError::new("empty _gid"))
}
else {
match sha3_hash(gk.g1, &sk.gid) {
Ok(hash) => {
let auth_attribute = msk
.attr
.iter()
.filter(|_attr| _attr.0 == attribute.to_string())
.nth(0)
.unwrap();
sk.attr.push((
auth_attribute.0.clone().to_uppercase(),
(gk.g1 * auth_attribute.1) + (hash * auth_attribute.2),
));
Ok(())
},
Err(e) => Err(e)
}
}
}
pub fn encrypt(
gk: &Aw11GlobalKey,
pks: &[&Aw11PublicKey],
policy: &str,
language: PolicyLanguage,
data: &[u8],
) -> Result<Aw11Ciphertext, RabeError> {
let mut _rng = rand::thread_rng();
match parse(policy, language) {
Ok(pol) => {
let msp: AbePolicy = AbePolicy::from_policy(&pol).unwrap();
let _num_cols = msp.m[0].len();
let _num_rows = msp.m.len();
let _s:Fr = _rng.gen();
let _s_shares = gen_shares_policy(_s, &pol, None).unwrap();
let _w_shares = gen_shares_policy(Fr::zero(), &pol, None).unwrap();
let _msg: Gt = _rng.gen();
let c_0 = _msg * pairing(gk.g1, gk.g2).pow(_s);
let mut c: Vec<(String, Gt, G2, G2)> = Vec::new();
for (_i, (_attr_name, _attr_share)) in _s_shares.into_iter().enumerate() {
let _r_x:Fr = _rng.gen();
let _pk_attr = find_pk_attr(pks, &remove_index(&_attr_name.to_uppercase()));
match _pk_attr {
None => {},
Some(_attr) => {
c.push((
_attr_name.clone().to_uppercase(),
pairing(gk.g1, gk.g2).pow(_attr_share) * _attr.1.pow(_r_x),
gk.g2 * _r_x,
(_attr.2 * _r_x) + (gk.g2 * _w_shares[_i].1),
));
}
}
}
match encrypt_symmetric(_msg, &data.to_vec()) {
Ok(ct) => Ok(Aw11Ciphertext { policy: (policy.to_string(), language), c_0, c, ct }),
Err(e) => Err(e)
}
},
Err(e) => Err(e)
}
}
pub fn decrypt(
gk: &Aw11GlobalKey,
sk: &Aw11SecretKey,
ct: &Aw11Ciphertext
) -> Result<Vec<u8>, RabeError> {
let str_attr = sk
.attr
.iter()
.map(|_values| {
let (_str, _g2) = _values.clone();
_str
})
.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 sk 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 {
match sha3_hash(gk.g1, &sk.gid) {
Ok(hash) => {
let mut _egg_s = Gt::one();
for _current in _list.iter() {
let _sk_attr = sk
.attr
.iter()
.filter(|_attr| _attr.0 == _current.0.to_string())
.nth(0)
.unwrap();
let _ct_attr = ct
.c
.iter()
.filter(|_attr| _attr.0 == _current.1.to_string())
.nth(0)
.unwrap();
let num = _ct_attr.1 * pairing(hash, _ct_attr.3);
let dem = pairing(_sk_attr.1, _ct_attr.2);
let _coeff = coeff_list
.iter()
.filter(|_c| _c.0 == _current.1.to_string())
.map(|_c| _c.1)
.nth(0)
.unwrap();
_egg_s = _egg_s * ((num * dem.inverse()).pow(_coeff));
}
let _msg = ct.c_0 * _egg_s.inverse();
decrypt_symmetric(_msg, &ct.ct)
},
Err(e) => Err(e)
}
} else {
Err(RabeError::new("Error in aw11/decrypt: attributes in sk do not match policy in ct."))
}
}
}
}
},
Err(e) => Err(e)
}
}
fn find_pk_attr(
pks: &[&Aw11PublicKey],
attr: &str
) -> Option<(String, Gt, G2)> {
for _pk in pks.into_iter() {
let _pk_attr = _pk
.attr
.clone()
.into_iter()
.filter(|_tuple| _tuple.0 == attr.to_string())
.nth(0);
if _pk_attr.is_some() {
return _pk_attr;
}
}
return None;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn and() {
let _gp = setup();
let att_authority1: Vec<&str> = vec!["A","B","C"];
let (_auth1_pk, _auth1_msk) = authgen(&_gp, &att_authority1).unwrap();
let att_authority2: Vec<&str> = vec!["D","E","F"];
let (_auth2_pk, _auth2_msk) = authgen(&_gp, &att_authority2).unwrap();
let att_authority3: Vec<&str> = vec!["G","H","I"];
let (_auth3_pk, _auth3_msk) = authgen(&_gp, &att_authority3).unwrap();
let att_bob: Vec<&str> = vec!["H","I"];
let mut _bob = keygen(&_gp, &_auth3_msk, &String::from("bob"), &att_bob).unwrap();
let _plaintext =
String::from("dance like no one's watching, encrypt like everyone is!").into_bytes();
let _policy = String::from(r#"{"name": "and", "children": [{"name": "H"}, {"name": "B"}]}"#);
if let Err(e) = add_to_attribute(&_gp, &_auth1_msk, &String::from("B"), &mut _bob) {
panic!("Error: {}", e.to_string())
}
let pks: Vec<&Aw11PublicKey> = vec![&_auth3_pk, &_auth1_pk];
let ct_cp: Aw11Ciphertext = encrypt(&_gp, pks.as_slice(), &_policy, PolicyLanguage::JsonPolicy, &_plaintext).unwrap();
let _matching = decrypt(&_gp, &_bob, &ct_cp).unwrap();
assert_eq!(_matching, _plaintext);
}
#[test]
fn or() {
let _gp = setup();
let att_authority1: Vec<&str> = vec!["A","B"];
let (_auth1_pk, _auth1_msk) = authgen(&_gp, &att_authority1).unwrap();
let att_authority2: Vec<&str> = vec!["C","D"];
let (_auth2_pk, _auth2_msk) = authgen(&_gp, &att_authority2).unwrap();
let mut _bob = keygen(
&_gp,
&_auth1_msk,
&String::from("bob"),
&vec!["A"],
)
.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": "B"}, {"name": "C"}]}"#);
let pks: Vec<&Aw11PublicKey> = vec![&_auth2_pk, &_auth1_pk];
if let Err(e) = add_to_attribute(&_gp, &_auth2_msk, &String::from("C"), &mut _bob) {
panic!("Error: {}", e.to_string())
}
let ct_cp: Aw11Ciphertext = encrypt(&_gp, &pks, &_policy,PolicyLanguage::JsonPolicy, &_plaintext).unwrap();
let _matching = decrypt(&_gp, &_bob, &ct_cp).unwrap();
assert_eq!(_matching, _plaintext);
}
#[test]
fn or_and() {
let _gp = setup();
let att_authority1: Vec<&str> = vec!["A","B"];
let (_auth1_pk, _auth1_msk) = authgen(&_gp, &att_authority1).unwrap();
let att_authority2: Vec<&str> = vec!["C","D"];
let (_auth2_pk, _auth2_msk) = authgen(&_gp, &att_authority2).unwrap();
let mut _bob = keygen(
&_gp,
&_auth1_msk,
&String::from("bob"),
&vec!["A"],
)
.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": "B"}, {"name": "and", "children": [{"name": "C"}, {"name": "D"}]}]}"#);
let pks: Vec<&Aw11PublicKey> = vec![&_auth2_pk, &_auth1_pk];
if let Err(e) = add_to_attribute(&_gp, &_auth2_msk, &String::from("C"), &mut _bob) {
panic!("Error: {}", e.to_string())
}
if let Err(e) = add_to_attribute(&_gp, &_auth2_msk, &String::from("D"), &mut _bob) {
panic!("Error: {}", e.to_string())
}
let ct_cp: Aw11Ciphertext = encrypt(&_gp, pks.as_slice(), &_policy, PolicyLanguage::JsonPolicy, &_plaintext).unwrap();
let _matching = decrypt(&_gp, &_bob, &ct_cp).unwrap();
assert_eq!(_matching, _plaintext);
}
#[test]
fn not() {
let _gp = setup();
let att_authority1: Vec<&str> = vec!["A","B"];
let (_auth1_pk, _auth1_msk) = authgen(&_gp, &att_authority1).unwrap();
let att_authority2: Vec<&str> = vec!["C","D"];
let (_auth2_pk, _auth2_msk) = authgen(&_gp, &att_authority2).unwrap();
let mut _bob = keygen(
&_gp,
&_auth1_msk,
&String::from("bob"),
&vec!["A"],
)
.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": "B"}, {"name": "and", "children": [{"name": "C"}, {"name": "A"}]}]}"#);
let pks: Vec<&Aw11PublicKey> = vec![&_auth2_pk, &_auth1_pk];
if let Err(e) = add_to_attribute(&_gp, &_auth2_msk, &String::from("D"), &mut _bob) {
panic!("Error: {}", e.to_string())
}
let ct_cp: Aw11Ciphertext = encrypt(&_gp, pks.as_slice(), &_policy, PolicyLanguage::JsonPolicy, &_plaintext).unwrap();
let pt = decrypt(&_gp, &_bob, &ct_cp);
assert_eq!(pt.is_ok(), false);
}
}