Skip to content

Instantly share code, notes, and snippets.

@y-yu
Last active January 3, 2022 11:43
Show Gist options
  • Save y-yu/d8897e9dce479b620606 to your computer and use it in GitHub Desktop.
Save y-yu/d8897e9dce479b620606 to your computer and use it in GitHub Desktop.
from charm.toolbox.integergroup import IntegerGroupQ
from charm.core.math.integer import toInt
import random
from functools import reduce
group = IntegerGroupQ()
group.paramgen(512)
cards = 52
# Utility Functions
def odd_random():
while True:
r = group.random()
if not toInt(r) % 2 == 0:
break
return r
def make_pi(n = cards):
xs = [(random.random(), i) for i in range(n)]
return [x[1] for x in sorted(xs)]
def permute(pi, d):
assert len(pi) == len(d)
return [d[i] for i in pi]
def compose(pi2, pi1):
assert len(pi1) == len(pi2)
return [pi1[i] for i in pi2]
def inverse(pi):
xs = [(pi[i], i) for i in range(len(pi))]
return [x[1] for x in sorted(xs)]
def mask(s):
return [random.choice([True, False]) for _ in range(s)]
# operation
def procedure_32(deck):
r = [ odd_random() for _ in range(len(deck)) ]
c = [(x[0][0] ** x[1], x[0][1] ** x[1]) for x in zip(deck, r)]
p = make_pi()
assert len(p) == len(deck)
return (permute(p, c), r, p)
def procedure_33(ca, cb, r, pi):
def f(i):
db_i, ab_i = cb[i]
da_i, aa_i = ca[pi[i]]
r_i = r[pi[i]]
return db_i == (da_i ** r_i) and ab_i == (aa_i ** r_i)
return all( f(i) for i in range(cards) )
def protocol_48(ci_1, ci, pi, r, s):
c = [ procedure_32(ci) for _ in range(s) ]
u = mask(s)
def f(i):
c_ik, r_ik, pi_ik = c[i]
if u[i]:
return procedure_33(ci, c_ik, r_ik, pi_ik)
else:
pi_ = compose(pi_ik, pi)
r_ = permute( inverse(pi_), [ r[pi_[j]] * r_ik[pi_ik[j]] for j in range(cards) ] )
return procedure_33(ci_1, c_ik, r_, pi_)
return all( f(i) for i in range(s) )
def protocol_47(c0, s, players):
ci_1 = c0
for p in players:
ci, ri, pii = procedure_32(ci_1)
assert protocol_48(ci_1, ci, pii, ri, s) == True
ci_1 = ci
return ci
def cp_proof(alpha, beta, er, er_1, c, r, a, b):
return alpha ** r == a * (beta ** c) and er ** r == b * (er_1 ** c)
# Class
class Player:
def __init__(self, alpha, room):
self.key = group.random()
self.beta = alpha ** self.key
self.room = room
self.hands = []
def send_r(self, s, c):
return s + c * self.key
def draw(self, n = 0):
room = self.room
assert n < len(room.deck)
def fn_er(er_1, p):
if p is self:
return er_1
else:
er = er_1 ** (p.key ** -1)
for p_ in room.players:
if not p_ is p:
s, c = group.random(), group.random()
a, b = room.alpha ** s, er ** s
r = p.send_r(s, c)
assert cp_proof(room.alpha, p.beta, er, er_1, c, r, a, b)
return er
d, a = room.deck[n]
en = reduce(fn_er, room.players, a) ** (self.key ** -1)
def get_card(xs):
for x, i in zip(xs, range(len(xs))):
if en ** x == d:
return i
return -1
c = get_card(room.x)
assert c > -1
del room.deck[n]
self.hands.append( (c, en) )
return c
def open(self, n):
assert n < len(self.hands)
card, en = self.hands[n]
for p in self.room.players:
if not p is self:
for p_ in self.room.players:
if not p_ is p:
s, c = group.random(), group.random()
a, b = self.room.alpha ** s, en ** s
r = self.send_r(s, c)
en_1 = en ** self.key
assert cp_proof(self.room.alpha, self.beta, en, en_1, c, r, a, b)
return card
class Room:
def setup(self, number):
self.alpha = group.randomGen()
self.x = [ odd_random() for _ in range(cards) ]
self.players = [ Player(self.alpha, self) for _ in range(number) ]
self.beta = reduce( lambda x, y: x ** y.key, self.players, self.alpha )
self.c0 = [ (self.alpha ** self.x[i], self.beta) for i in range(cards) ]
def shuffle(self, s):
self.deck = protocol_47(self.c0, s, self.players)
r = Room()
r.setup(3)
r.shuffle(10)
for _ in range(cards):
r.players[0].draw()
print( sorted([x[0] for x in r.players[0].hands]) )
print( [r.players[0].open(i) for i in range(cards)] )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment