use na::{DMatrix, DVector}; use pairing::{PrimeField, Field}; use pairing::bls12_381::{Fq, FqRepr}; pub fn u64_to_field(x: u64) -> F { F::from_repr( >::from(x) ).unwrap() } #[derive(Debug, Clone, PartialEq)] pub enum Gate<'a> { Attribute(&'a [u8]), Threshold {t: usize, children: Vec>}, } impl<'a> Gate<'a> { fn children(self) -> Vec> { match self { Gate::Threshold {children, ..} => children, Gate::Attribute (_) => Vec::new(), } } fn label(self) -> &'a [u8] { match self { Gate::Threshold {..} => b"", Gate::Attribute (l) => l, } } fn lsss(&self) -> DMatrix { match self { &Gate::Attribute (_) => DMatrix::from_row_slice(1, 1, &[1u64]), &Gate::Threshold {t, ref children} => { let m = children.len(); DMatrix::from_fn(m, t, |i, j| { ((i as u64) + 1).pow(j as u32) }) } } } fn rec_msp(ast: AS<'a>) -> AS<'a>{ // find the first threshold-tree string rather than a simple attribute let at = ast.rho.iter().enumerate().skip_while(|&(_, g)| { match *g { Gate::Attribute (_) => true, Gate::Threshold {..} => false, } }).next(); // if none is found, simply return ast, we're done. // otherwise, [cont.] if let Some((i, g)) = at { let mg = g.lsss(); // refresh rho with the resolved attribute let mut rho = ast.rho.clone(); rho.remove(i); // XXX. lots of cloning for the safety god. // perhaps the fact that we're inside a class can spare us // the copy of all the gates? for c in g.clone().children().iter() { rho.insert(i, c.clone()); } let (m1, d1) = ast.m.shape(); let (m2, d2) = mg.shape(); // insert the lsss matrix into m let w = ast.m.row(i).kronecker(&mg.column(0)); let mg = mg.remove_column(0); let m = ast.m.remove_row(i); let m = DMatrix::from_fn( m1 + m2 - 1, d1 + d2 - 1, |row, col| { if row < i && col < d1 { m[(row, col)] } else if row < i && col >= d1 { 0 } else if row < i+m2 && col < d1 { w[(row-i, col)] } else if row < i+m2 && col >= d1 { mg[(row-i, col-d1)] } else if row >= i+m2 && col < d1 { m[(row-m2, col)] } else { 0 } } ); Self::rec_msp(AS {m, rho}) } else { ast.clone() } } fn msp(self) -> AS<'a> { let rho = vec![self]; let m = DMatrix::from_row_slice(1, 1, &[1u64]); let ast = Self::rec_msp(AS {m, rho}); ast } } #[derive(Clone)] struct AS<'a> { m: DMatrix, rho: Vec>, } impl<'a> AS<'a> { fn gen_shares(&self) -> DVector { let m = DMatrix::::from_fn(self.m.nrows(), self.m.ncols(), |row, col| { u64_to_field(self.m[(row, col)]) } ); DVector::from_fn(self.m.nrows(), |row, col| { F::one() } ) } } mod tc { use std::str; use std::str::FromStr; use nom::{digit, alphanumeric}; use msp::Gate; named!(parens , ws!(delimited!(tag!("("), threshold_gate, tag!(")") )) ); named!(threshold_gate , do_parse!( t: threshold >> children: attributes >> (Gate::Threshold {t, children}) ) ); named!(attributes < Vec> >, many1!(preceded!(tag!(","), parse)) ); named!(threshold , map_res!(map_res!(ws!(digit), str::from_utf8), FromStr::from_str) ); named!(attribute , map!(ws!(alphanumeric), Gate::Attribute) ); named!(pub parse , alt!(attribute | parens) ); } mod bc { use nom::{IResult, alphanumeric}; use msp::Gate; named!(parens, ws!(delimited!( tag!("("), expr, tag!(")") )) ); named!(attribute , map!(ws!(alphanumeric), Gate::Attribute) ); named!(gate , alt!(attribute | parens) ); named!(term >, do_parse!( init: gate >> res: fold_many0!( pair!(alt!(tag!("^") | tag!("∧") | tag!("and")), gate), init, |acc, (op, g): (&[u8], Gate<'a>)| { let v: Vec> = vec![acc, g]; Gate::Threshold {t: 2usize, children: v} } ) >> (res) ) ); named!(expr >, do_parse!( init: term >> res: fold_many0!( pair!(alt!(tag!("v") | tag!("or") | tag!("∨")), term), init, |acc, (op, g): (&[u8], Gate<'a>)| { let v: Vec> = vec![acc, g]; Gate::Threshold {t: 2usize, children: v} } ) >> (res) ) ); // XXX. this needs to be changed into a result type. // Also note that making instead "expr" pub will fuck up everything // because the "lifetime is not defined" - not sure I really understood why. pub fn parse(i: &[u8]) -> IResult<&[u8], Gate, u32> { expr(i) } } #[test] fn test_tc_parse() { // see eprint 2010/374 let policy = b"(2, (2, (3, I, J, K, L), G, H), (2, A, B, C), (2, D, E, F))"; let (_, pp) = tc::parse(policy).unwrap(); let msp = pp.msp(); assert_eq!(msp.rho.len(), 12); let expected = DMatrix::from_row_slice(12, 2 + (2-1) + (3-1) + (2-1) + (2-1), &[1, 1, 1, 0, 0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 1, 2, 0, 2, 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 1, 3, 0, 0, 1, 0, 0, 1, 3, 0, 0, 2, 0, 0, 1, 3, 0, 0, 3, 1, 1, 1, 3, 0, 0, 3, 2, 4, 1, 3, 0, 0, 3, 3, 9, 1, 3, 0, 0, 3, 4, 16, ] ); assert_eq!(expected, msp.m) } use std::collections::VecDeque; pub struct Bfs<'a> { stack: VecDeque> } impl<'a> Bfs<'a> { fn new(g: Gate<'a>) -> Self { let mut stack = VecDeque::new(); stack.push_back(g); Bfs { stack } } } impl<'a> Iterator for Bfs<'a> { type Item = Gate<'a>; fn next(&mut self) -> Option { let g = self.stack.pop_front()?; let children = g.clone().children(); self.stack.extend(children.iter().cloned()); Some(g) } } #[test] fn test_bc_parse() { let policy = b"intern and topsecret or xkeyscore"; let (_, gate) = bc::parse(policy).unwrap(); let children = gate.children(); assert_eq!(children.len(), 2); } #[test] fn test_bfs() { let policy = b"1 and (3 and 4)"; let (_, gate) = bc::parse(policy).unwrap(); assert_eq!(gate.clone().children().len(), 2); let mut bfs = Bfs::new(gate); let root = bfs.next(); let expected = Gate::Attribute(b"1"); assert_eq!(Some(expected), bfs.next()); assert_eq!(bfs.next().unwrap().children().len(), 2); } #[test] fn test_matrix_field() { let policy = b"1 and 2"; let (_, gate) = bc::parse(policy).unwrap(); let msp = gate.msp(); let m = msp.m; let mm = DVector::::from_fn(m.ncols(), |row, col| { u64_to_field(m[(row, col)]) } ); let v = DVector::from_fn(m.ncols(), |row, col| { 1u64 }); let vv = DVector::from_fn(m.ncols(), |row, col| { Fq::one() }); let d = mm.dot(&vv); }