use std::string::String;
use rand::Rng;
use rabe_bn::{Group, Fr, G1, G2, Gt, pairing};
use utils::{
policy::*,
tools::*,
aes::*,
hash::sha3_hash_fr
};
use utils::policy::pest::{PolicyLanguage, parse, PolicyType};
use crate::error::RabeError;
use utils::policy::dnf::policy_in_dnf;
#[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 BdabePublicKey {
pub g1: G1,
pub g2: G2,
pub p1: G1,
pub p2: G2,
pub e_gg_y: Gt,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabeMasterKey {
pub y: Fr,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabeUserKey {
pub sk: BdabeSecretUserKey,
pub pk: BdabePublicUserKey,
pub sk_a: Vec<BdabeSecretAttributeKey>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabePublicUserKey {
pub u: String,
pub u1: G1,
pub u2: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabeSecretUserKey {
pub u1: G1,
pub u2: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabeSecretAttributeKey {
pub attr: String,
pub au1: G1,
pub au2: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabePublicAttributeKey {
pub attr: String,
pub a1: G1,
pub a2: G2,
pub a3: Gt,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabeSecretAuthorityKey {
pub name: String,
pub a1: G1,
pub a2: G2,
pub a3: Fr,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabeCiphertextTuple {
pub attr: Vec<String>,
pub e1: Gt,
pub e2: G1,
pub e3: G2,
pub e4: G1,
pub e5: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BdabeCiphertext {
pub policy: (String, PolicyLanguage),
pub j: Vec<BdabeCiphertextTuple>,
pub ct: Vec<u8>,
}
pub fn setup() -> (BdabePublicKey, BdabeMasterKey) {
let mut rng = rand::thread_rng();
let g1:G1 = rng.gen();
let g2:G2 = rng.gen();
let p1:G1 = rng.gen();
let p2:G2 = rng.gen();
let y:Fr = rng.gen();
(
BdabePublicKey { g1, g2, p1, p2, e_gg_y: pairing(g1, g2).pow(y) },
BdabeMasterKey { y }
)
}
pub fn authgen(
pk: &BdabePublicKey,
msk: &BdabeMasterKey,
name: &str,
) -> BdabeSecretAuthorityKey {
let mut rng = rand::thread_rng();
let _alpha: Fr = rng.gen();
let _beta = msk.y - _alpha;
let a1 = pk.g1 * _alpha;
let a2 = pk.g2 * _beta;
let a3:Fr = rng.gen();
BdabeSecretAuthorityKey { a1, a2, a3, name: name.to_string()}
}
pub fn keygen(
pk: &BdabePublicKey,
sk_a: &BdabeSecretAuthorityKey,
name: &str,
) -> BdabeUserKey {
let mut rng = rand::thread_rng();
let r_u: Fr = rng.gen();
BdabeUserKey {
sk: BdabeSecretUserKey {
u1: sk_a.a1 + (pk.p1 * r_u),
u2: sk_a.a2 + (pk.p2 * r_u),
},
pk: BdabePublicUserKey {
u: name.to_string(),
u1: pk.g1 * r_u,
u2: pk.g2 * r_u,
},
sk_a: Vec::new(),
}
}
pub fn request_attribute_pk(
pk: &BdabePublicKey,
sk_a: &BdabeSecretAuthorityKey,
attribute: &str,
) -> Result<BdabePublicAttributeKey, RabeError> {
return if from_authority(attribute, &sk_a.name) {
match sha3_hash_fr(attribute) {
Ok(hash_1) => {
match sha3_hash_fr(&sk_a.name) {
Ok(hash_2) => {
let exp = hash_1 * hash_2 * sk_a.a3;
Ok(BdabePublicAttributeKey {
attr: attribute.to_string(),
a1: pk.g1 * exp,
a2: pk.g2 * exp,
a3: pk.e_gg_y.pow(exp),
})
},
Err(e) => Err(e)
}
},
Err(e) => Err(e)
}
} else {
Err(RabeError::new(&format!("attribute {} is not from_authority() or !is_eligible()", attribute.to_string())))
}
}
pub fn request_attribute_sk(
pk_u: &BdabePublicUserKey,
sk_a: &BdabeSecretAuthorityKey,
attribute: &str,
) -> Result<BdabeSecretAttributeKey, RabeError> {
return if from_authority(attribute, &sk_a.name) && is_eligible(attribute, &pk_u.u) {
match sha3_hash_fr(attribute) {
Ok(hash_1) => {
match sha3_hash_fr(&sk_a.name) {
Ok(hash_2) => {
let exp = hash_1 * hash_2 * sk_a.a3;
Ok(BdabeSecretAttributeKey {
attr: attribute.to_string(),
au1: pk_u.u1 * exp,
au2: pk_u.u2 * exp,
})
},
Err(e) => Err(e)
}
},
Err(e) => Err(e)
}
} else {
Err(RabeError::new(&format!("attribute {} is not from_authority() or !is_eligible()", attribute.to_string())))
}
}
pub fn encrypt(
pk: &BdabePublicKey,
attr_pks: &[&BdabePublicAttributeKey],
policy: &str,
language: PolicyLanguage,
plaintext: &[u8],
) -> Result<BdabeCiphertext, RabeError> {
match parse(policy, language) {
Ok(pol) => {
if policy_in_dnf(&pol, false, None) {
let mut rng = rand::thread_rng();
let dnf: dnf::DnfPolicy = dnf::DnfPolicy::from_string(policy, attr_pks, language).unwrap();
let _msg = pairing(rng.gen(), rng.gen());
let mut j: Vec<BdabeCiphertextTuple> = Vec::new();
for _term in dnf.terms {
let _r_j: Fr = rng.gen();
j.push(BdabeCiphertextTuple {
attr: _term.0,
e1: _term.1.pow(_r_j) * _msg,
e2: pk.p1 * _r_j,
e3: pk.p2 * _r_j,
e4: _term.3 * _r_j,
e5: _term.4 * _r_j,
});
}
match encrypt_symmetric(_msg, &plaintext.to_vec()) {
Ok(ct) => Ok(BdabeCiphertext { policy: (policy.to_string(), language), j, ct }),
Err(e) => Err(e)
}
} else {
Err(RabeError::new("Error in bdabe/encrypt: Policy not in DNF."))
}
},
Err(e) => Err(e)
}
}
pub fn decrypt(
sk: &BdabeUserKey,
ct: &BdabeCiphertext
) -> Result<Vec<u8>, RabeError> {
let str_attr = sk
.sk_a
.iter()
.map(|v| v.attr.to_string())
.collect::<Vec<_>>();
match parse(ct.policy.0.as_ref(), ct.policy.1) {
Ok(pol) => {
if traverse_policy(&str_attr, &pol, PolicyType::Leaf) == false {
Err(RabeError::new("Error in bdabe/decrypt: attributes in sk do not match policy in ct."))
} else {
let mut msg = Gt::one();
for (_i, _ct_j) in ct.j.iter().enumerate() {
if is_satisfiable(&_ct_j.attr, &sk.sk_a) {
let _sk_sum = calc_satisfiable(&_ct_j.attr, &sk.sk_a);
msg = _ct_j.e1
* pairing(_ct_j.e2, _sk_sum.1)
* pairing(_sk_sum.0, _ct_j.e3)
* (pairing(_ct_j.e4, sk.sk.u2) * pairing(sk.sk.u1, _ct_j.e5)).inverse();
break;
}
}
decrypt_symmetric(msg, &ct.ct)
}
},
Err(e) => Err(e)
}
}
fn is_satisfiable(
conjunction: &Vec<String>,
sk: &Vec<BdabeSecretAttributeKey>
) -> bool {
let mut _ret: bool = true;
for _attr in conjunction {
match sk.into_iter().find(|&x| x.attr == *_attr) {
None => {
_ret = false;
break;
}
Some(_attr_sk) => {}
}
}
_ret
}
fn calc_satisfiable(
conjunction: &Vec<String>,
sk: &Vec<BdabeSecretAttributeKey>,
) -> (G1, G2) {
let mut ret: (G1, G2) = (G1::one(), G2::one());
for _i in 0usize..conjunction.len() {
match sk
.into_iter()
.find(|&x| x.attr == conjunction[_i].to_string())
{
None => {}
Some(_found) => {
if _i == 0 {
ret = (_found.au1, _found.au2);
} else {
ret = (ret.0 + _found.au1, ret.1 + _found.au2);
}
}
}
}
ret
}
fn from_authority(
attr: &str,
authority: &str
) -> bool {
let v: Vec<_> = attr.match_indices("::").collect();
if v.len() == 1 {
return attr.get(0..v[0].0).unwrap().to_string() == authority.to_string();
}
return false;
}
fn is_eligible(
_attr: &str,
_user: &str
) -> bool {
return true;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn and() {
let (_pk, _msk) = setup();
let _a1_key = authgen(&_pk, &_msk, &String::from("aa1"));
let _a2_key = authgen(&_pk, &_msk, &String::from("aa2"));
let mut sk = keygen(&_pk, &_a1_key, &String::from("u1"));
let _att1 = String::from("aa1::A");
let _att2 = String::from("aa2::B");
let _att1_pk = request_attribute_pk(&_pk, &_a1_key, &_att1).unwrap();
let _att2_pk = request_attribute_pk(&_pk, &_a2_key, &_att2).unwrap();
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a1_key, &_att1).unwrap());
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a2_key, &_att2).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": "aa1::A"}, {"name": "aa2::B"}]}"#);
let attr_pks: Vec<&BdabePublicAttributeKey> = vec!(&_att1_pk, &_att2_pk);
let _ct: BdabeCiphertext =
encrypt(
&_pk,
&attr_pks.as_slice(),
&policy,
PolicyLanguage::JsonPolicy,
&_plaintext
).unwrap();
let _match = decrypt(&sk, &_ct);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), _plaintext);
}
#[test]
fn or() {
let (_pk, _msk) = setup();
let _a1_key = authgen(&_pk, &_msk, &String::from("aa1"));
let _a2_key = authgen(&_pk, &_msk, &String::from("aa2"));
let mut sk = keygen(&_pk, &_a2_key, &String::from("u1"));
let _att1 = String::from("aa1::C");
let _att2 = String::from("aa2::B");
let _att1_pk = request_attribute_pk(&_pk, &_a1_key, &_att1).unwrap();
let _att2_pk = request_attribute_pk(&_pk, &_a2_key, &_att2).unwrap();
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a1_key, &_att1).unwrap());
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a2_key, &_att2).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": "aa1::A"}, {"name": "aa2::B"}]}"#);
let attr_pks: Vec<&BdabePublicAttributeKey> = vec!(&_att1_pk, &_att2_pk);
let _ct: BdabeCiphertext =
encrypt(&_pk, &attr_pks.as_slice(), &_policy, PolicyLanguage::JsonPolicy, &_plaintext).unwrap();
let _match = decrypt(&sk, &_ct);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), _plaintext);
}
#[test]
fn or_and() {
let (_pk, _msk) = setup();
let _a1_key = authgen(&_pk, &_msk, &String::from("aa1"));
let _a2_key = authgen(&_pk, &_msk, &String::from("aa2"));
let _a3_key = authgen(&_pk, &_msk, &String::from("aa3"));
let mut sk = keygen(&_pk, &_a2_key, &String::from("u1"));
let _att1 = String::from("aa1::A");
let _att2 = String::from("aa2::B");
let _att3 = String::from("aa3::C");
let _att1_pk = request_attribute_pk(&_pk, &_a1_key, &_att1).unwrap();
let _att2_pk = request_attribute_pk(&_pk, &_a2_key, &_att2).unwrap();
let _att2_pk = request_attribute_pk(&_pk, &_a3_key, &_att3).unwrap();
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a1_key, &_att1).unwrap());
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a2_key, &_att2).unwrap());
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a3_key, &_att3).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": "and", "children": [{"name": "aa3::C"}, {"name": "aa2::B"}]}, {"name": "aa1::X"}]}"#,
);
let attr_pks: Vec<&BdabePublicAttributeKey> = vec!(&_att1_pk, &_att2_pk);
let _ct: BdabeCiphertext =
encrypt(&_pk, &attr_pks.as_slice(), &_policy,PolicyLanguage::JsonPolicy, &_plaintext).unwrap();
let _match = decrypt(&sk, &_ct);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), _plaintext);
}
#[test]
fn not() {
let (_pk, _msk) = setup();
let _a1_key = authgen(&_pk, &_msk, &String::from("aa1"));
let _a2_key = authgen(&_pk, &_msk, &String::from("aa2"));
let mut sk = keygen(&_pk, &_a2_key, &String::from("u1"));
let _att1 = String::from("aa1::A");
let _att2 = String::from("aa2::B");
let _att1_pk = request_attribute_pk(&_pk, &_a1_key, &_att1).unwrap();
let _att2_pk = request_attribute_pk(&_pk, &_a2_key, &_att2).unwrap();
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a1_key, &_att1).unwrap());
sk
.sk_a
.push(request_attribute_sk(&sk.pk, &_a2_key, &_att2).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": "aa1::B"}, {"name": "aa2::A"}]}"#);
let attr_pks: Vec<&BdabePublicAttributeKey> = vec!(&_att1_pk, &_att2_pk);
let _ct: BdabeCiphertext =
encrypt(&_pk, &attr_pks.as_slice(), &_policy, PolicyLanguage::JsonPolicy, &_plaintext).unwrap();
let _match = decrypt(&sk, &_ct);
assert_eq!(_match.is_ok(), false);
}
}