• No results found

Table Generation

6.7 Linking Tables

7.1.2 Table Generation

To implement FRIBs, the LUTs need to be generated by a single entity. For an organisation storing and processing data in the cloud, they would generate their own tables. However, for processing across multiple entities, as it would be for government voting, another entity would be required to generate the tables. The performance of LUT generation is not critical to the performance of FRIBs, because they can be reused and only need to be generated once (they can be regenerated regularly to limit patterns, but each request can use the same LUTs).

that defines what result a combination of fragments represents needs changing. For example, Listing 7.1 defines the function to add a carry bit to x-bits using the XOR fragmentation algorithm. The argument args is an array of N = len(args) fragment states, where the carry bit is at bit index 0 of each fragment. The resulting array contains the result fragments, whereN −1 can be random, and the last fragment is chosen so that the fragments give the correct result. Sample fragment input of 15,10,5 (01111⊕01010⊕00101 = 00000) could give 30,25,7 (11110⊕11001⊕00111 = 00000), or input 15,10,7 (01111⊕01010⊕00111 = 00010) which is 0001 plus the carry bit 0, gives an output of 19,4,22 (10011⊕00100⊕10110 = 00001), where bit index 4 is the resulting carry of the addition.

Listing 7.1:Function to get the result of fragments for addition

def g e t A d d R e s u l t ( a r g s ) : r = [] v = c = 0 for arg in a r g s : c = c ^ ( arg & 1) v = v ^ ( arg > > 1) v = v + c rv = 0 for i in r a n g e ( len ( a r g s ) -1) : r . a p p e n d ( r a n d o m . r a n d i n t (0 ,31) ) rv = rv ^ r [ i ] r . a p p e n d ( rv ^ v ) r e t u r n r

Adding redundancy makes the table generation more difficult, as different state combinations need to give the same result. Instead of randomly choos- ing the resulting fragments, the results need to be precomputed such that if corruption to one state occurs, the same result is returned if there was no corruption. The function for getting the fragments would be a lookup to get the precomputed result, as shown in Listing 7.2. The locations of sample code for generating the precomputed results are given in Appendix D.

Listing 7.2:Function to get the result of fragments for addition with redundancy

def g e t A d d R e d R e s u l t ( a r g s ) :

if str ( a r g s ) in v a l i d R e s u l t s :

r e t u r n v a l i d R e s u l t s [ str ( a r g s ) ]

r e t u r n N o n e

Another example of a resulting fragment function would be that of a NAND function with variable usage. This would be a result LUT that could be used to

compute nearly any arbitrary operation in a privacy-preserving manner. The LUTs can be computed before the algorithm or function has been defined, al- lowing for new functions or changes to existing functions without regenerating LUTs. If all the fragment servers are managed by different entities, as would be the case for voting, each entity can agree or disagree to running the new/- modified function. The process of getting the result fragments with a variable usage NAND function requires more steps than a static function. First, the state needs to be split such that the order of operations is observed, as shown in Listing 7.3. Recall that 0 is used to represent an operation and the number of 0s define order. For example, the state 1107 = 10001010011 would give [1,[[1,1],11]], which in terms of NAND functions is (1⊕((1⊕1)⊕0)).

Listing 7.3:Function to split each fragment by NAND operation

def s p l i t F r a g m e n t ( f , ops ) : if ops == 0: r e t u r n f f1 = f . s p l i t (’ 0 ’ * ops ) if len ( f1 ) == 1: r e t u r n s p l i t F r a g m e n t ( f , ops - 1) o u t p u t = [] for sf in f1 : o u t p u t . a p p e n d ( s p l i t F r a g m e n t ( sf , ops - 1) ) r e t u r n o u t p u t

With the order of operations preserved, the fragments need to be joined by the fragmentation algorithm (XOR). A sample is given in 7.4.

Listing 7.4:Function to join the fragments by the fragmentation algorithm

def f r a g m e n t E v a l X o r ( f0 , f1 ) : if t y p e ( f0 ) is str : if f0 == " 11 " and f1 == " 11 ": r e t u r n " 11 " if f0 == " 1 " and f1 == " 1 ": r e t u r n " 11 " r e t u r n " 1 " r e s u l t = [] for i in r a n g e (0 , len ( f0 ) ) : r e s u l t . a p p e n d ( f r a g m e n t E v a l X o r ( f0 [ i ] , f1 [ i ]) ) r e t u r n r e s u l t

The fragment result can now be solved with Listing 7.5, giving a single bit. To implement a different operation, the NAND function can be replaced.

Listing 7.5:Function to split each fragment by NAND operation

def f r a g m e n t E v a l ( f ) :

if t y p e ( f ) is str :

r e t u r n 0

r e t u r n 1

e = f r a g m e n t E v a l ( f [ 0 ] )

for i in r a n g e (1 , len ( f ) ) :

e = int (not( e and f r a g m e n t E v a l ( f [ i ]) ) )

r e t u r n e

Finally, the random result fragments, which are single bits, unlike the dedicated addition example, can be computed. Sample input 1107,1577,6355 into the function for 7.6 would be a randomised fragment for (1Z((0Z1)Z1)) = 1, which could be 0,1,0.

Listing 7.6: Function to get result fragments for variable NAND operations

def g e t N a n d R e s u l t ( a r g s ) : r = []

rv = 0

v = f r a g m e n t E v a l ( r e d u c e (l a m b d a x , y : f r a g m e n t E v a l X o r ( x , y ) , map (l a m b d a arg : s p l i t F r a g m e n t ( bin ( arg ) [2:] , 3) , a r g s ) ) ) for i in r a n g e ( len ( a r g s ) -1) : r . a p p e n d ( r a n d o m . r a n d i n t (0 ,1) ) rv = rv ^ r [ i ] r . a p p e n d ( rv ^ v ) r e t u r n r

The remaining step for generating the LUTs is to generate a list of valid states, which in the case of the addition example in Listing 7.2 is 0 → 2x−1, where x is the number of bits (including the carry bit). The generic NAND example requires validation because 29 = 11101 would not be a reachable state. Once a list of states is generated, a random mapping for each fragment server to obfuscate its state for sending to the other fragment servers is generated (as described in Chapter 6). All possible state combinations can be tried and the resulting fragments can be generated using the functions defined earlier in this section. Finally, the obfuscation and result LUTs are outputted and distributed to their corresponding fragment servers.