diff --git a/script/research/mpc/ec_share.sage b/script/research/mpc/ec_share.sage new file mode 100644 index 000000000..8085a1562 --- /dev/null +++ b/script/research/mpc/ec_share.sage @@ -0,0 +1,74 @@ +load('pedersen.sage') + +def open_2pc(party0_share, party1_share): + return party0_share + party1_share + +def verify_2pc_mac_check(party0_mac, party1_mac): + assert party0_mac+party1_mac == 0 + +global_key = random.randint(0, p) + +class ECAuthenticatedShare(object): + """ + additive share + """ + def __init__(self, share, mac=None, modifier=None): + self.share = share + self.mac = global_key * self.share if mac==None else mac + self.public_modifier = 0 if modifier == None else modifier # carry out extra addition/subtraction by public scalars until opening + + def __repr__(self): + return "share: %s, mac: %s"%(self.share, self.mac) + + # SPDZ mac authentication + def authenticated_open(self, peer_authenticated_share): + opened_share = open_2pc(self.share, peer_authenticated_share.share) + mac_key = random.randint(0,global_key) + mac_share = mac_key * (opened_share + self.public_modifier) - self.mac + + peer_mac_key = global_key - mac_key + peer_mac_share = peer_mac_key * (opened_share + peer_authenticated_share.public_modifier) - peer_authenticated_share.mac + assert (mac_share + peer_mac_share) == 0 + + return opened_share + + def mul_scalar(self, scalar): + return ECAuthenticatedShare(self.share * scalar, self.mac * scalar, self.public_modifier * scalar) + + def add_point(self, point, party_id): + return ECAuthenticatedShare(self.share + point, self.mac , self.public_modifier - point) if party_id ==0 else ECAuthenticatedShare(self.share, self.mac, self.public_modifier - point) + + def __add__(self, rhs): + ''' + add additive shares + ''' + return ECAuthenticatedShare(self.share + rhs.share, self.mac + rhs.mac, self.public_modifier + rhs.public_modifier) + + def __sub__(self, rhs): + ''' + sub additive shares + ''' + return ECAuthenticatedShare(self.share - rhs.share, self.mac - rhs.mac, self.public_modifier - rhs.public_modifier) + + +class ScalingECAuthenticatedShares(object): + def __init__(self, alpha, beta, triplet, party_id): + # authenticated shares + self.alpha_as = alpha + self.beta_as = beta + self.a_as = triplet[0] + self.b_as = triplet[1] + self.c_as = triplet[2] + self.party_id = party_id + + def __mul__(self, peer_share): + generator = CurvePoint.generator() + + masked_e_share = self.beta_as - self.b_as + peer_masked_e_share = peer_share.beta_as - peer_share.b_as + e = open_2pc(masked_e_share.share, peer_masked_e_share.share) + peer_masked_d_share = peer_share.alpha_as - peer_share.a_as.mul_point(generator) + masked_d_share = self.alpha_as - self.a_as.mul_point(generator) + d = open_2pc(masked_d_share.share, peer_masked_d_share.share) + + return (self.b_as.mul_point(d) + self.a_as.mul_point(generator).mul_scalar(e) + self.c_as.mul_point(generator)).add_point(d * e, self.party_id) diff --git a/script/research/mpc/ec_spdz.sage b/script/research/mpc/ec_spdz.sage new file mode 100644 index 000000000..ffd467a36 --- /dev/null +++ b/script/research/mpc/ec_spdz.sage @@ -0,0 +1,60 @@ +load('beaver.sage') +load('curve.sage') +load('ec_share.sage') + +p = 10 + +party0_val = CurvePoint.random() +party1_val = CurvePoint.random() +public_scalar = 2 + +# additive share distribution, and communication of private values +party0_random = CurvePoint.random() +alpha1 = ECAuthenticatedShare(party0_random) +alpha2 = ECAuthenticatedShare(party0_val - party0_random) +assert (alpha1.authenticated_open(alpha2) == party0_val) + +party1_random = CurvePoint.random() +beta1 = ECAuthenticatedShare(party1_random) +beta2 = ECAuthenticatedShare(party1_val - party1_random) +assert (beta1.authenticated_open(beta2) == party1_val) + +# mul_scalar by public scalar +mul_left_share = alpha1.mul_scalar(public_scalar) +mul_right_share = alpha2.mul_scalar(public_scalar) +assert (mul_left_share.authenticated_open(mul_right_share) == (public_scalar * party0_val)) + +# add authenticated shares +add_party0_share = alpha1 + beta2 +add_party1_share = alpha2 + beta1 + +lhs = add_party0_share.authenticated_open(add_party1_share) + +assert (lhs == (party0_val + party1_val)) + + +# sub authenticated shares +sub_party0_share = alpha1 - beta2 +sub_party1_share = alpha2 - beta1 + +lhs = sub_party0_share.authenticated_open(sub_party1_share) + +assert (lhs == (party0_val - party1_val)) + + +# authenticated ec point scaled with authenticated scalar +party1_val = random.randint(0,p) +party1_random = random.randint(0,p) +beta1 = AuthenticatedShare(party1_random) +beta2 = AuthenticatedShare(party1_val - party1_random) + +s = Source(p) +alpha1beta1_share = ScalingECAuthenticatedShares(alpha1, beta1, s.triplet(0), 0) +alpha2beta2_share = ScalingECAuthenticatedShares(alpha2, beta2, s.triplet(1), 1) + +lhs_share = alpha1beta1_share * alpha2beta2_share +rhs_share = alpha2beta2_share * alpha1beta1_share +lhs = lhs_share.authenticated_open(rhs_share) + +mul_res = party0_val * party1_val +assert (lhs == (party0_val * party1_val)), 'lhs: {}, rhs: {}'.format(lhs, party0_val * party1_val) diff --git a/script/research/mpc/share.sage b/script/research/mpc/share.sage index bd3a15701..768e6b247 100644 --- a/script/research/mpc/share.sage +++ b/script/research/mpc/share.sage @@ -1,4 +1,5 @@ load('pedersen.sage') +load('ec_share.sage') def open_2pc(party0_share, party1_share): return party0_share + party1_share @@ -6,7 +7,7 @@ def open_2pc(party0_share, party1_share): def verify_2pc_mac_check(party0_mac, party1_mac): assert party0_mac+party1_mac == 0 -global_key = random.randint(0,100) +global_key = random.randint(0, p) class AuthenticatedShare(object): """ @@ -41,6 +42,9 @@ class AuthenticatedShare(object): def mul_scalar(self, scalar): return AuthenticatedShare(self.share * scalar, self.mac * scalar, self.public_modifier * scalar) + def mul_point(self, point): + return ECAuthenticatedShare(self.share * point, self.mac * point, self.public_modifier * point) + def __add__(self, rhs): ''' add additive shares