use rabe_bn::{Fr, Gt};
use utils::{
secretsharing::{gen_shares_policy, calc_coefficients, calc_pruned},
aes::*
};
use rand::Rng;
use utils::policy::pest::{PolicyLanguage, parse};
use crate::error::RabeError;
use std::ops::Mul;
use utils::secretsharing::remove_index;
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "borsh")]
use borsh::{BorshSerialize, BorshDeserialize};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
pub struct Yct14Attribute {
name: String,
#[cfg_attr(feature = "borsh", borsh(skip))]
#[cfg_attr(not(feature = "borsh"), serde(skip_serializing_if = "Option::is_none"))]
node: Option<Yct14Type>,
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Yct14Type {
Public(Gt),
Private(Fr),
}
impl Yct14Type {
pub fn public(&self) -> Result<Gt, RabeError> {
match self {
Yct14Type::Public(g) => Ok(g.clone()),
_ => Err(RabeError::new("no public value (Gt) found"))
}
}
pub fn private(&self) -> Result<Fr, RabeError> {
match self {
Yct14Type::Private(fr) => Ok(fr.clone()),
_ => Err(RabeError::new("no private value (Fr) found"))
}
}
}
impl Yct14Attribute {
pub fn new(name: String, g: Gt) -> (Yct14Attribute, Yct14Attribute) {
let si: Fr = rand::thread_rng().gen();
(
Yct14Attribute {
name: name.clone(),
node: Some(Yct14Type::Public(g.pow(si))),
},
Yct14Attribute {
name,
node: Some(Yct14Type::Private(si)),
}
)
}
pub fn private_from(input: (String, Fr), msk: &Yct14AbeMasterKey) -> Result<Yct14Attribute, RabeError> {
match msk.get_private(&input.0) {
Ok(si) => Ok(
Yct14Attribute {
name: input.0,
node: Some(
Yct14Type::Private(
input.1.mul(si.inverse().unwrap())
)
)
}
),
Err(e) => Err(e)
}
}
pub fn public_from(name: &String, pk: &Yct14AbePublicKey, k: Fr) -> Yct14Attribute {
Yct14Attribute {
name: name.to_string(),
node: pk.attributes
.clone()
.into_iter()
.filter(|attribute| attribute.name.as_str() == name)
.map(|attribute| match attribute.node {
Some(node) => {
match node {
Yct14Type::Public(public) => {
Some(Yct14Type::Public(public.pow(k)))
},
_ => panic!("attribute {} has no public node value", attribute.name),
}
},
None => panic!("attribute {} has no public node", attribute.name),
})
.nth(0)
.unwrap()
}
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Yct14AbePublicKey {
g: Gt,
attributes: Vec<Yct14Attribute>
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Yct14AbeMasterKey {
s: Fr,
attributes: Vec<Yct14Attribute>
}
impl Yct14AbeMasterKey {
pub fn get_private(&self, attribute: &String) -> Result<Fr, RabeError> {
let res: Option<Fr> = self.attributes
.clone()
.into_iter()
.filter(|a| a.name.as_str() == attribute && a.node.is_some())
.map(|a| match a.node.unwrap().private() {
Ok(node_value) => node_value,
Err(e) => panic!("no private node value: {}",e)
} )
.nth(0);
res.ok_or(RabeError::new(&format!("no private key found for {}", attribute)))
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Yct14AbeSecretKey {
policy: (String, PolicyLanguage),
du: Vec<Yct14Attribute>,
}
impl Yct14AbeSecretKey {
pub fn get_private(&self, attribute: &String) -> Result<Fr, RabeError> {
let res: Option<Fr> = self.du
.clone()
.into_iter()
.filter(|a| a.name.as_str() == attribute)
.map(|a| match a.node.unwrap().private() {
Ok(node_value) => node_value,
Err(e) => panic!("no private node value: {}",e)
} )
.nth(0);
res.ok_or(RabeError::new(&format!("no private key found for {}", attribute)))
}
}
#[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Yct14AbeCiphertext {
attributes: Vec<Yct14Attribute>,
ct: Vec<u8>,
}
impl Yct14AbeCiphertext {
pub fn get_public(&self, attribute: &String) -> Result<Gt, RabeError> {
let res: Option<Gt> = self.attributes
.clone()
.into_iter()
.filter(|a| a.name.as_str() == attribute)
.map(|a| match a.node.unwrap().public() {
Ok(node_value) => node_value,
Err(e) => panic!("no public node value: {}",e)
} )
.nth(0);
res.ok_or(RabeError::new(&format!("no private key found for {}", attribute)))
}
}
pub fn setup(
attributes: Vec<&str>
) -> (Yct14AbePublicKey, Yct14AbeMasterKey) {
let mut _rng = rand::thread_rng();
let mut private: Vec<Yct14Attribute> = Vec::new();
let mut public: Vec<Yct14Attribute> = Vec::new();
let s: Fr = _rng.gen();
let g: Gt = _rng.gen();
for attribute in attributes {
let attribute_pair = Yct14Attribute::new(attribute.to_string(), g);
public.push(attribute_pair.0);
private.push(attribute_pair.1);
}
return (
Yct14AbePublicKey {
g: g.pow(s),
attributes: public
},
Yct14AbeMasterKey {
s,
attributes: private
}
);
}
pub fn keygen(
msk: &Yct14AbeMasterKey,
policy: &String,
language: PolicyLanguage,
) -> Result<Yct14AbeSecretKey, RabeError> {
match parse(policy, language) {
Ok(pol) => {
let mut du: Vec<Yct14Attribute> = Vec::new();
match gen_shares_policy(msk.s, &pol, None) {
Some(shares) => {
for share in shares.into_iter() {
match Yct14Attribute::private_from((remove_index(&share.0), share.1), msk) {
Ok(attribute) => du.push(attribute),
Err(e) => println!("Error: {:?}", e)
}
}
Ok(Yct14AbeSecretKey {
policy: (policy.clone(), language),
du
})
},
None => Err(RabeError::new("could not generate shares during keygen()"))
}
},
Err(e) => Err(e)
}
}
pub fn encrypt(
pk: &Yct14AbePublicKey,
attributes: &Vec<&str>,
plaintext: &[u8],
) -> Result<Yct14AbeCiphertext, RabeError> {
if attributes.is_empty() {
return Err(RabeError::new("attributes empty"));
}
else if plaintext.is_empty() {
return Err(RabeError::new("plaintext empty"));
}
else {
let mut attrs: Vec<Yct14Attribute> = Vec::new();
let k: Fr = rand::thread_rng().gen();
let _cs: Gt = pk.g.pow(k);
for attr in attributes.into_iter() {
attrs.push(Yct14Attribute::public_from(&attr.to_string(), pk, k));
}
match encrypt_symmetric(_cs, &plaintext.to_vec()) {
Ok(ct) => Ok(Yct14AbeCiphertext { attributes: attrs, ct }),
Err(e) => Err(e)
}
}
}
pub fn decrypt(
sk: &Yct14AbeSecretKey,
ct: &Yct14AbeCiphertext
) -> Result<Vec<u8>, RabeError> {
let attr = ct
.attributes
.iter()
.map(|value| value.name.clone())
.collect::<Vec<String>>();
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(_p) => {
let (_match, _list) = _p;
if _match {
let mut _prod_t = 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 in _list.into_iter() {
let z = ct.get_public(&_attr.0).unwrap().pow(sk.get_private(&_attr.0).unwrap());
let coeff = coeff_list
.clone()
.into_iter()
.filter(|a| a.0 == _attr.1)
.map(|a| a.1 )
.nth(0)
.unwrap();
_prod_t = _prod_t * z.pow(coeff);
}
decrypt_symmetric(_prod_t, &ct.ct)
} else {
Err(RabeError::new("Error in decrypt: attributes do not match policy."))
}
}
}
}
Err(e)=> Err(e)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn or() {
let attributes: Vec<&str> = vec!["A","B","C"];
let (pk, msk) = setup(attributes.clone());
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": "C"}]}"#);
let ct: Yct14AbeCiphertext = encrypt(&pk, &attributes, &plaintext).unwrap();
let sk: Yct14AbeSecretKey = keygen(&msk, &policy, PolicyLanguage::JsonPolicy).unwrap();
assert_eq!(decrypt(&sk, &ct).unwrap(), plaintext);
}
}