From d4895ddd375ac1e61ac5519421d7fda413b8edaa Mon Sep 17 00:00:00 2001 From: ertosns Date: Thu, 7 Sep 2023 02:36:11 +0300 Subject: [PATCH] [research/mpc] spdz in sage --- script/research/mpc/beaver.sage | 19 ++++++++ script/research/mpc/curve.sage | 43 +++++++++++++++++ script/research/mpc/pedersen.sage | 9 ++++ script/research/mpc/share.sage | 76 +++++++++++++++++++++++++++++++ script/research/mpc/spdz.sage | 69 ++++++++++++++++++++++++++++ 5 files changed, 216 insertions(+) create mode 100644 script/research/mpc/beaver.sage create mode 100644 script/research/mpc/curve.sage create mode 100644 script/research/mpc/pedersen.sage create mode 100644 script/research/mpc/share.sage create mode 100644 script/research/mpc/spdz.sage diff --git a/script/research/mpc/beaver.sage b/script/research/mpc/beaver.sage new file mode 100644 index 000000000..37dff04db --- /dev/null +++ b/script/research/mpc/beaver.sage @@ -0,0 +1,19 @@ +load('share.sage') + +import random +class Source(object): + def __init__(self, p): + self.a = random.randint(0,p) + self.b = random.randint(0,p) + self.c = self.a*self.b + self.left_a = random.randint(0,self.a) + self.right_a = self.a - self.left_a + self.left_b = random.randint(0,self.b) + self.right_b = self.b - self.left_b + self.left_c = random.randint(0,self.c) + self.right_c = self.c - self.left_c + + def triplet(self, party_id): + triplet = [self.left_a, self.left_b, self.left_c] if party_id==0 else [self.right_a, self.right_b, self.right_c] + return [AuthenticatedShare(share) for share in triplet] + diff --git a/script/research/mpc/curve.sage b/script/research/mpc/curve.sage new file mode 100644 index 000000000..052ec3367 --- /dev/null +++ b/script/research/mpc/curve.sage @@ -0,0 +1,43 @@ +# stark curve https://docs.starkware.co/starkex/crypto/stark-curve.html + +p = 3618502788666131213697322783095070105623107215331596699973092056135872020481 +alpha = 1 +# $$y^2 = x^3 + \alpha \dot x + \beta$$ (mod p) +beta = 3141592653589793238462643383279502884197169399375105820974944592307816406665 +K = GF(p) +E = EllipticCurve(K, (alpha,beta)) +ec_order = E.order() +# ECDSA scheme generator +G = E(874739451078007766457464989774322083649278607533249481151382481072868806602, 152666792071518830868575557812948353041420400780739481342941381225525861407) + +import random +class CurvePoint(): + def __init__(self, x=None, y=None): + if x==None or y==None: + self.point = CurvePoint.random() + else: + self.point = E(x,y) + self.x = self.point[0] + self.y = self.point[1] + + def __repr__(self): + return "[ x: %s, y: %s, z: 1]"%(self.x, self.y) + + def random(max=p): + return G* random.randint(0, max) + + def __add__(self, rhs): + return self.point + rhs.point + + def __sub__(self, rhs): + return self.point - rhs.point + + def __neg__(self): + return -1 * self.point + + def generator(): + return G + + def __mul__(self, factor): + return factor * self.point + diff --git a/script/research/mpc/pedersen.sage b/script/research/mpc/pedersen.sage new file mode 100644 index 000000000..20ab3fead --- /dev/null +++ b/script/research/mpc/pedersen.sage @@ -0,0 +1,9 @@ +load('curve.sage') + +class PedersenCommitment(object): + def __init__(self, value, blinder=None): + self.value = value + self.blinder = blinder if blinder is not None else random.randint(0,p) + + def commitment(self): + return CurvePoint.generator() * self.value + CurvePoint.generator() * self.blinder diff --git a/script/research/mpc/share.sage b/script/research/mpc/share.sage new file mode 100644 index 000000000..bd3a15701 --- /dev/null +++ b/script/research/mpc/share.sage @@ -0,0 +1,76 @@ +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,100) + +class AuthenticatedShare(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 sub_scalar(self, scalar, party_id): + return AuthenticatedShare(self.share - scalar, self.mac, self.public_modifier + scalar) if party_id == 0 else AuthenticatedShare(self.share , self.mac, self.public_modifier + scalar) + + def add_scalar(self, scalar, party_id): + return AuthenticatedShare(self.share + scalar, self.mac , self.public_modifier - scalar) if party_id ==0 else AuthenticatedShare(self.share, self.mac, self.public_modifier - scalar) + + def mul_scalar(self, scalar): + return AuthenticatedShare(self.share * scalar, self.mac * scalar, self.public_modifier * scalar) + + def __add__(self, rhs): + ''' + add additive shares + ''' + return AuthenticatedShare(self.share + rhs.share, self.mac + rhs.mac, self.public_modifier + rhs.public_modifier) + + def __sub__(self, rhs): + ''' + sub additive shares + ''' + return AuthenticatedShare(self.share - rhs.share, self.mac - rhs.mac, self.public_modifier - rhs.public_modifier) + + +class MultiplicationAuthenticatedShares(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): + masked_d_share = self.alpha_as - self.a_as + peer_masked_d_share = peer_share.alpha_as - peer_share.a_as + d = open_2pc(masked_d_share.share, peer_masked_d_share.share) + + 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) + + return (self.b_as.mul_scalar(d) + self.a_as.mul_scalar(e) + self.c_as).add_scalar(d*e, self.party_id) diff --git a/script/research/mpc/spdz.sage b/script/research/mpc/spdz.sage new file mode 100644 index 000000000..1c22929f7 --- /dev/null +++ b/script/research/mpc/spdz.sage @@ -0,0 +1,69 @@ +load('beaver.sage') +p = 10 + +party0_val = 3 +party1_val = 22 +public_scalar = 2 + +# additive share distribution, and communication of private values +party0_random = random.randint(0,p) +alpha1 = AuthenticatedShare(party0_random) +alpha2 = AuthenticatedShare(party0_val - party0_random) +assert (alpha1.authenticated_open(alpha2) == party0_val) + +party1_random = random.randint(0,p) +beta1 = AuthenticatedShare(party1_random) +beta2 = AuthenticatedShare(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)) + + +# sub_scalar by public scalar +sub_left_share = alpha1.sub_scalar(public_scalar, 0) +sub_right_share = alpha2.sub_scalar(public_scalar, 1) +assert (sub_left_share.authenticated_open(sub_right_share) == (party0_val - public_scalar)) + + + +# add_scalar by public scalar +add_left_share = alpha1.add_scalar(public_scalar, 0) +add_right_share = alpha2.add_scalar(public_scalar, 1) +assert (add_left_share.authenticated_open(add_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)) + + + +# mul authenticated shares +mul_res = party0_val * party1_val + +s = Source(p) +alpha1beta1_share = MultiplicationAuthenticatedShares(alpha1, beta1, s.triplet(0), 0) +alpha2beta2_share = MultiplicationAuthenticatedShares(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) + +assert (lhs == (party0_val * party1_val)), 'lhs: {}, rhs: {}'.format(lhs, party0_val * party1_val)