Minimalist quadratic masking transformer¶
This is an example for the transformer of minimalist quadratic masking scheme which was proposed in BU18
Define the transformer¶
from circkit.transformers.core import CircuitTransformer
from circkit.boolean import BooleanCircuit
from circkit.array import Array
class BUQuadraticMasking(CircuitTransformer):
# circuit type of the target circuit
TARGET_CIRCUIT = BooleanCircuit
def __init__(self):
"""
Arguments
---------
:order: ISW masking order
"""
super().__init__()
# fixed number of shares
self.n_shares = 3
def refresh(self, shares, randshares):
a, b, c = shares
ra, rb, rc = randshares
ma = ra * (b + rc)
mb = rb * (a + rc)
rc = ma + mb + (ra + rc)*(rb + rc) + rc
a1 = a + ra
b1 = b + rb
c1 = c + rc
new_shares = Array([a1, b1, c1])
return new_shares
def visit_INPUT(self, node):
shares = []
for i in range(self.n_shares):
new_name = f"{node.operation.name}_share{i}"
x = self.target_circuit.add_input(new_name)
shares.append(x)
shares = Array(shares)
return shares
def visit_XOR(self, node, shares_1, shares_2):
ra = self.target_circuit.RND()()
rb = self.target_circuit.RND()()
rc = self.target_circuit.RND()()
randshares_1 = Array([ra, rb, rc])
rd = self.target_circuit.RND()()
re = self.target_circuit.RND()()
rf = self.target_circuit.RND()()
randshares_2 = Array([rd, re, rf])
a, b, c = self.refresh(shares_1, randshares_1)
d, e, f = self.refresh(shares_2, randshares_2)
x = a + d
y = b + e
z = c + f + a*e + b*d
return Array([x, y, z])
def visit_AND(self, node, shares_1, shares_2):
ra = self.target_circuit.RND()()
rb = self.target_circuit.RND()()
rc = self.target_circuit.RND()()
randshares_1 = Array([ra, rb, rc])
rd = self.target_circuit.RND()()
re = self.target_circuit.RND()()
rf = self.target_circuit.RND()()
randshares_2 = Array([rd, re, rf])
a, b, c = self.refresh(shares_1, randshares_1)
d, e, f = self.refresh(shares_2, randshares_2)
ma = b*f + rc * e
md = c*e + rf * b
x = a*e + rf
y = b*d + rc
z = a*ma + d*md + rc*rf + c*f
return Array([x, y, z])
def visit_CONST(self, node):
ra = self.target_circuit.RND()()
rb = self.target_circuit.RND()()
x = self.target_circuit.add_const(node.operation.value)
rx = ra*rb + x
shares = Array([ra, rb, rx])
return shares
Test on a boolean circuit¶
from circkit.boolean import BooleanCircuit
C = BooleanCircuit()
x = C.add_input("x")
y = C.add_input("y")
z = x * y + 1
t = z + x + 1
C.add_output(t)
# ISW transformer
transformer = BUQuadraticMasking()
newC = transformer.transform(C)
# see the graph and verify the ISW circuit
# iswC.digraph().view()
# # Evaluate on original circuit
inp = [1, 0]
out = C.evaluate(inp)
print(f"Original circuit output: {out}")
# Evaluate on BU quadratic masking circuit
# 1 = 1 * 0 + 1 and 0 = 1 * 1 + 1
inp_shares = [1, 0, 1, 1, 1, 1]
n_tests = 10
for i in range(n_tests):
out_shares = newC.evaluate(inp_shares)
a, b, c = out_shares
ret = a*b + c
print(f"Output shares: {out_shares} --> {ret}")
Original circuit output: [1]
Output shares: [0, 0, 1] --> 1
Output shares: [1, 1, 0] --> 1
Output shares: [1, 0, 1] --> 1
Output shares: [1, 1, 0] --> 1
Output shares: [0, 1, 1] --> 1
Output shares: [0, 0, 1] --> 1
Output shares: [1, 0, 1] --> 1
Output shares: [1, 1, 0] --> 1
Output shares: [0, 0, 1] --> 1
Output shares: [0, 0, 1] --> 1