use rabe_bn::{Group, Fr, G1, G2, Gt, pairing};
use std::ops::Neg;
use utils::{
tools::*,
secretsharing::{gen_shares_policy, calc_coefficients, calc_pruned},
aes::*,
hash::{sha3_hash_fr, sha3_hash}
};
use rand::Rng;
use utils::policy::pest::{PolicyLanguage, parse};
use crate::error::RabeError;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "borsh")]
use borsh::{BorshSerialize, BorshDeserialize};
use utils::secretsharing::remove_index;
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct KpAbePublicKey {
g1: G1,
g2: G2,
g1_b: G1,
g1_b2: G1,
h_b: G1,
e_gg_alpha: Gt,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct KpAbeMasterKey {
alpha1: Fr,
alpha2: Fr,
b: Fr,
h_g1: G1,
h_g2: G2,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct KpAbeSecretKey {
policy: (String, PolicyLanguage),
dj: Vec<(String, G1, G2, G1, G1, G1)>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct KpAbeCiphertext {
e1: Gt,
e2: G2,
ej: Vec<(String, G1, G1, G1)>,
ct: Vec<u8>,
}
pub fn setup() -> (KpAbePublicKey, KpAbeMasterKey) {
let mut rng = rand::thread_rng();
let alpha1:Fr = rng.gen();
let alpha2:Fr = rng.gen();
let b:Fr = rng.gen();
let alpha = alpha1 * alpha2;
let g1:G1 = rng.gen();
let g2:G2 = rng.gen();
let h_g1:G1 = rng.gen();
let h_g2:G2 = rng.gen();
let g1_b = g1 * b;
let g1_b2 = g1_b * b;
let h_b = h_g1 * b;
let e_gg_alpha = pairing(g1, g2).pow(alpha);
return (
KpAbePublicKey { g1, g2, g1_b, g1_b2, h_b, e_gg_alpha },
KpAbeMasterKey { alpha1, alpha2, b, h_g1, h_g2 }
);
}
pub fn keygen(
pk: &KpAbePublicKey,
msk: &KpAbeMasterKey,
policy: &str,
language: PolicyLanguage,
) -> Result<KpAbeSecretKey, RabeError> {
let mut rng = rand::thread_rng();
match parse(policy, language) {
Ok(policy_value) => {
match gen_shares_policy(msk.alpha1, &policy_value, None) {
Some(shares) => {
let mut dj: Vec<(String, G1, G2, G1, G1, G1)> = Vec::new();
for (share_str, share_value) in shares.into_iter() {
let striped = remove_index(&share_str);
let random:Fr = rng.gen();
if is_negative(&striped) {
let share_hash = sha3_hash_fr(&striped).expect("could not hash _share_str");
dj.push((
striped,
G1::zero(),
G2::zero(),
(pk.g1 * share_value) + (pk.g1_b2 * random),
pk.g1_b * (share_hash * random) + (msk.h_g1 * random),
pk.g1 * random.neg(),
));
} else {
let share_hash = sha3_hash(pk.g1, &striped).expect("could not hash _share_str");
dj.push((
striped,
(pk.g1 * (msk.alpha2 * share_value))
+ (share_hash * random),
pk.g2 * random,
G1::zero(),
G1::zero(),
G1::zero(),
));
}
}
return Ok(KpAbeSecretKey {
policy: (policy.to_string(), language),
dj,
});
},
None => Err(RabeError::new("could not share secret over policy"))
}
}
Err(e) => Err(e)
}
}
pub fn encrypt(
pk: &KpAbePublicKey,
attributes: &[&str],
plaintext: &[u8],
) -> Result<KpAbeCiphertext, RabeError> {
if attributes.is_empty() || plaintext.is_empty() {
Err(RabeError::new("attributes or data empty"))
} else {
let mut rng = rand::thread_rng();
let mut ej: Vec<(String, G1, G1, G1)> = Vec::new();
let secret:Fr = rng.gen();
let mut sx: Vec<Fr> = Vec::new();
sx.push(secret);
for (_i, _attr) in attributes.iter().enumerate() {
sx.push(rng.gen());
sx[0] = sx[0] - sx[_i];
}
for (_i, _attr) in attributes.into_iter().enumerate() {
ej.push((
_attr.to_string(),
sha3_hash(pk.g1, &_attr).expect("could not hash _attr") * secret,
pk.g1_b * sx[_i.clone()],
(pk.g1_b2 * (sx[_i.clone()] * sha3_hash_fr(&_attr.to_string()).expect("could not hash _attr"))) + (pk.h_b * sx[_i]),
));
}
let msg: Gt = rng.gen();
let e1: Gt = pk.e_gg_alpha.pow(secret) * msg;
let e2: G2 = pk.g2 * secret;
match encrypt_symmetric(msg, &plaintext.to_vec()) {
Ok(ct) => Ok(KpAbeCiphertext { e1, e2, ej, ct }),
Err(e) => Err(e)
}
}
}
pub fn decrypt(
sk: &KpAbeSecretKey,
ct: &KpAbeCiphertext
) -> Result<Vec<u8>, RabeError> {
let attr = ct
.ej
.iter()
.map(|a| a.clone().0.to_string())
.collect::<Vec<_>>();
match parse(sk.policy.0.as_ref(), sk.policy.1) {
Ok(policy_value) => {
return match calc_pruned(&attr, &policy_value, None) {
Err(e) => Err(e),
Ok((matches, list)) => {
if matches {
let mut prod_t = Gt::one();
let mut _z_y = Gt::one();
let mut coeff_list: Vec<(String, Fr)> = Vec::new();
coeff_list = calc_coefficients(&policy_value, Some(Fr::one()), coeff_list, None).unwrap();
for attr_str in list.iter() {
let sk_attr = sk
.dj
.iter()
.filter(|_attr| { _attr.0 == attr_str.0.to_string() })
.nth(0)
.unwrap();
let ct_attr = ct
.ej
.iter()
.filter(|_attr| _attr.0 == attr_str.0.to_string())
.nth(0)
.unwrap();
let coeff = coeff_list
.iter()
.filter(|_attr| _attr.0 == attr_str.1.to_string())
.nth(0)
.unwrap();
if is_negative(&attr_str.0) {
} else {
_z_y = pairing(sk_attr.1, ct.e2)
* pairing(ct_attr.1, sk_attr.2).inverse();
}
prod_t = prod_t * _z_y.pow(coeff.1);
}
let msg: Gt = ct.e1 * prod_t.inverse();
decrypt_symmetric(msg, &ct.ct)
} else {
Err(RabeError::new("Error in lsw/decrypt: attributes do not match policy."))
}
}
}
}
Err(e)=> Err(e)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn and() {
let (pk, msk) = setup();
let att_matching: Vec<&str> = vec!["A","B","C"];
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": "C"}, {"name": "B"}]}"#);
let ct_kp_matching: KpAbeCiphertext = encrypt(&pk, &att_matching, &plaintext).unwrap();
let sk: KpAbeSecretKey = keygen(&pk, &msk, &policy, PolicyLanguage::JsonPolicy).unwrap();
assert_eq!(decrypt(&sk, &ct_kp_matching).unwrap(), plaintext);
}
#[test]
fn or() {
let (pk, msk) = setup();
let att_matching: Vec<&str> = vec!["A","B","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": "B"}]}"#);
let ct_kp_matching: KpAbeCiphertext = encrypt(&pk, &att_matching, &plaintext).unwrap();
let sk: KpAbeSecretKey = keygen(&pk, &msk, &policy, PolicyLanguage::JsonPolicy).unwrap();
assert_eq!(decrypt(&sk, &ct_kp_matching).unwrap(), plaintext);
}
#[test]
fn or_and() {
let (pk, msk) = setup();
let att_matching: Vec<&str> = vec!["X","Y","Z"];
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": "and", "children": [{"name": "Y"}, {"name": "Z"}]}]}"#);
let ct: KpAbeCiphertext = encrypt(&pk, &att_matching, &plaintext).unwrap();
let sk: KpAbeSecretKey = keygen(&pk, &msk, &policy, PolicyLanguage::JsonPolicy).unwrap();
assert_eq!(decrypt(&sk, &ct).unwrap(), plaintext);
}
#[test]
fn not() {
let (pk, msk) = setup();
let att_matching: 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": "or", "children": [{"name": "X"}, {"name": "Y"}]}"#);
let ct_kp_matching: KpAbeCiphertext = encrypt(&pk, &att_matching, &plaintext).unwrap();
let sk: KpAbeSecretKey = keygen(&pk, &msk, &policy, PolicyLanguage::JsonPolicy).unwrap();
let res = decrypt(&sk, &ct_kp_matching);
assert_eq!(res.is_ok(), false);
}
}