use rabe_bn::{Fr, G1, G2, Gt, pairing};
use rand::Rng;
use utils::{
secretsharing::{gen_shares_policy, calc_pruned, calc_coefficients},
tools::*,
aes::*,
hash::*
};
use utils::policy::pest::{PolicyLanguage, parse, PolicyType};
use crate::error::RabeError;
use utils::secretsharing::remove_index;
#[cfg(feature = "borsh")]
use borsh::{BorshSerialize, BorshDeserialize};
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct CpAbePublicKey {
pub g1: G1,
pub g2: G2,
pub h: G1,
pub f: G2,
pub e_gg_alpha: Gt,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct CpAbeMasterKey {
pub beta: Fr,
pub g2_alpha: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct CpAbeCiphertext {
pub policy: (String, PolicyLanguage),
pub c: G1,
pub c_p: Gt,
pub c_y: Vec<CpAbeAttribute>,
pub data: Vec<u8>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct CpAbeSecretKey {
pub d: G2,
pub d_j: Vec<CpAbeAttribute>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct CpAbeAttribute {
pub string: String,
pub g1: G1,
pub g2: G2,
}
pub fn setup() -> (CpAbePublicKey, CpAbeMasterKey) {
let mut rng = rand::thread_rng();
let g1:G1 = rng.gen();
let g2:G2 = rng.gen();
let beta:Fr = rng.gen();
let alpha:Fr = rng.gen();
let h = g1 * beta;
let f = g2 * beta.inverse().unwrap();
let g2_alpha = g2 * alpha;
let e_gg_alpha = pairing(g1, g2_alpha);
return (
CpAbePublicKey { g1, g2, h, f, e_gg_alpha },
CpAbeMasterKey { beta, g2_alpha },
);
}
pub fn keygen(
pk: &CpAbePublicKey,
msk: &CpAbeMasterKey,
attributes: &[&str],
) -> Option<CpAbeSecretKey> {
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 d = (msk.g2_alpha + g2_r) * msk.beta.inverse().unwrap();
let mut d_j: Vec<CpAbeAttribute> = Vec::new();
for j in attributes {
let r_j:Fr = rng.gen();
d_j.push(CpAbeAttribute {
string: j.to_string(), g1: pk.g1 * r_j, g2: g2_r + (sha3_hash(pk.g2, j).expect("could not hash _j") * r_j), });
}
return Some(CpAbeSecretKey { d, d_j });
}
pub fn delegate(
pk: &CpAbePublicKey,
sk: &CpAbeSecretKey,
subset: &[&str],
) -> Option<CpAbeSecretKey> {
let attr_str = sk.d_j
.iter()
.map(|val| val.string.as_str())
.collect::<Vec<_>>();
return if !is_subset(subset, &attr_str) {
println!("Error: the given attribute set is not a subset of the given sk.");
None
} else {
if subset.is_empty() || subset.len() == 0 {
println!("Error: the given attribute subset is empty.");
return None;
}
let mut rng = rand::thread_rng();
let r: Fr = rng.gen();
let mut d_j: Vec<CpAbeAttribute> = Vec::new();
for attr in subset {
let r_j: Fr = rng.gen();
let d_j_val = sk.d_j
.iter()
.find(|x| x.string == attr.to_string())
.map(|x| (x.g1, x.g2))
.unwrap();
d_j.push(CpAbeAttribute {
string: attr.to_string(),
g1: d_j_val.0 + (pk.g1 * r_j),
g2: d_j_val.1 + (sha3_hash(pk.g2, attr.as_ref()).expect("could not hash _attr") * r_j) + (pk.g2 * r),
});
}
Some(CpAbeSecretKey {
d: sk.d + (pk.f * r),
d_j,
})
}
}
pub fn encrypt(
pk: &CpAbePublicKey,
policy: &str,
language: PolicyLanguage,
plaintext: &[u8],
) -> Result<CpAbeCiphertext, 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.h * secret;
let c_p = pk.e_gg_alpha.pow(secret) * msg;
let mut c_y: Vec<CpAbeAttribute> = Vec::new();
for (node, i_val) in shares.clone() {
let j = remove_index(&node);
c_y.push(CpAbeAttribute {
string: node,
g1: pk.g1 * i_val,
g2: sha3_hash(pk.g2, &j).expect("could not hash j") * i_val,
});
}
match encrypt_symmetric(msg, &plaintext.to_vec()) {
Ok(data) => Ok(CpAbeCiphertext { policy: (policy.to_string(), language), c, c_p, c_y, data }),
Err(e) => Err(e)
}
}
Err(e) => Err(e)
}
}
pub fn decrypt(
sk: &CpAbeSecretKey,
ct: &CpAbeCiphertext
) -> Result<Vec<u8>, RabeError> {
let attr = sk.d_j
.iter()
.map(|v| v.string.clone() )
.collect::<Vec<_>>();
match parse(ct.policy.0.as_ref(), ct.policy.1) {
Ok(policy_value) => {
return if traverse_policy(&attr, &policy_value, PolicyType::Leaf) == false {
Err(RabeError::new("Error in bsw/encrypt: attributes do not match policy."))
} else {
match calc_pruned(&attr, &policy_value, None) {
Err(e) => Err(e),
Ok(pruned) => {
if !pruned.0 {
Err(RabeError::new("Error in bsw/encrypt: attributes do not match policy."))
} else {
let mut z: Vec<(String, Fr)> = Vec::new();
z = calc_coefficients(&policy_value, Some(Fr::one()), z, None).unwrap();
let mut a = Gt::one();
for _i in pruned.1 {
let _k = _i.0;
let _j = _i.1;
match ct.c_y.iter().find(|x| x.string == _j.to_string()) {
Some(c_y) => {
match sk.d_j.iter().find(|x| x.string == _k.to_string()) {
Some(d_j) => {
for _z_tuple in z.iter() {
if _z_tuple.0 == _j {
a = a *
(pairing(c_y.g1, d_j.g2) *
pairing(d_j.g1, c_y.g2).inverse())
.pow(_z_tuple.1);
}
}
}
None => {
}
}
}
None => {
}
}
}
let _msg = ct.c_p * ((pairing(ct.c, sk.d)) * a.inverse()).inverse();
decrypt_symmetric(_msg, &ct.data)
}
}
}
}
}
Err(e) => Err(e)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn or() {
let (pk, msk) = setup();
let mut att_matching: Vec<&str> = Vec::new();
att_matching.push("D");
att_matching.push("B");
let mut att_not_matching: Vec<&str> = Vec::new();
att_not_matching.push("C");
att_not_matching.push("D");
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: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &att_matching).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[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 att: Vec<&str> = att_matching.iter().map(|x| x.as_ref()).collect();
let mut att_not_matching: Vec<&str> = Vec::new();
att_not_matching.push("attr201");
att_not_matching.push("attr200");
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: CpAbeCiphertext = encrypt(&pk, &_policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &att).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[test]
fn nested() {
let (pk, msk) = setup();
let _num_nested = 30; let mut att_matching: Vec<String> = Vec::new();
for _i in 1..(_num_nested + 1) {
att_matching.push(["a".to_string(), _i.to_string()].concat());
}
let attr: Vec<&str> = att_matching.iter().map(|x| x.as_ref()).collect();
let mut att_not_matching: Vec<&str> = Vec::new();
att_not_matching.push("x");
att_not_matching.push("y");
let plaintext = String::from("dance like no one's watching, encrypt like everyone is!")
.into_bytes();
let mut policy = String::from("{\"name\":\"and\", \"children\": [{\"name\": \"a2\"}, {\"name\": \"a1\"}]}");
for _i in 3.._num_nested {
let mut policy_str = String::from("{\"name\":\"and\", \"children\":[");
policy_str.push_str("{\"name\":\"");
policy_str.push_str(&attr[_i - 1]);
policy_str.push_str("\"},");
policy_str.push_str(&policy);
policy_str.push_str("]}");
policy = policy_str.clone();
}
let ct_cp: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &attr).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[test]
fn or3() {
let (pk, msk) = setup();
let mut att_matching: Vec<&str> = Vec::new();
att_matching.push("A");
let mut att_not_matching: Vec<&str> = Vec::new();
att_not_matching.push("B");
att_not_matching.push("C");
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": "X"}, {"name": "Y"}, {"name": "A"}]}"#);
let ct_cp: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &att_matching).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[test]
fn and() {
let (pk, msk) = setup();
let mut att_matching: Vec<&str> = Vec::new();
att_matching.push("A");
att_matching.push("B");
att_matching.push("C");
let mut att_not_matching: Vec<&str> = Vec::new();
att_not_matching.push("A");
att_not_matching.push("D");
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": "A"}, {"name": "B"}]}"#);
let ct_cp: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &att_matching).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[test]
fn dual_attributes() {
let (pk, msk) = setup();
let mut att_matching: Vec<&str> = Vec::new();
att_matching.push("A");
att_matching.push("B");
let mut att_not_matching: Vec<&str> = Vec::new();
att_not_matching.push("A");
att_not_matching.push("C");
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": "A"}, {"name": "B"}]}, {"name": "and", "children": [{"name": "B"}, {"name": "C"}]}]}"#);
let ct_cp: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &att_matching).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[test]
fn and3() {
let (pk, msk) = setup();
let mut att_matching: Vec<&str> = Vec::new();
att_matching.push("A");
att_matching.push("B");
att_matching.push("C");
let mut att_not_matching: Vec<&str> = Vec::new();
att_not_matching.push("A");
att_not_matching.push("D");
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": "A"}, {"name": "B"}, {"name": "C"}]}"#);
let ct_cp: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &att_matching).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[test]
fn or_and() {
let (pk, msk) = setup();
let att_matching: Vec<&str> = vec!["A","B","C","D"];
let att_not_matching: Vec<&str> = vec!["A","C"];
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": "A"}, {"name": "B"}]}, {"name": "and", "children": [{"name": "C"}, {"name": "D"}]}]}"#);
let ct_cp: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let _match = decrypt(&keygen(&pk, &msk, &att_matching).unwrap(), &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
let _no_match = decrypt(&keygen(&pk, &msk, &att_not_matching).unwrap(), &ct_cp);
assert_eq!(_no_match.is_ok(), false);
}
#[test]
fn delegate_ab() {
let (pk, msk) = setup();
let att_matching: Vec<&str> = vec!["A","B","C"];
let delegate_att: Vec<&str> = vec!["A","B"];
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": "A"}, {"name": "B"}]}"#);
let ct_cp: CpAbeCiphertext = encrypt(&pk, &policy, PolicyLanguage::JsonPolicy, &plaintext).unwrap();
let sk: CpAbeSecretKey = keygen(&pk, &msk, &att_matching).unwrap();
let del: CpAbeSecretKey = delegate(&pk, &sk, &delegate_att).unwrap();
let _match = decrypt(&del, &ct_cp);
assert_eq!(_match.is_ok(), true);
assert_eq!(_match.unwrap(), plaintext);
}
}