Correctly map messages to G_q instead of simply using Z_p*
This commit is contained in:
parent
1642b0eba9
commit
db74f67474
@ -33,6 +33,9 @@ for f in eos.js_tests; do
|
|||||||
# Disable handling of special attributes
|
# Disable handling of special attributes
|
||||||
perl -0777 -pi -e 's/var __specialattrib__ = function \(attrib\) \{/var __specialattrib__ = function (attrib) { return false;/g' eos/__javascript__/$f.js
|
perl -0777 -pi -e 's/var __specialattrib__ = function \(attrib\) \{/var __specialattrib__ = function (attrib) { return false;/g' eos/__javascript__/$f.js
|
||||||
|
|
||||||
|
# Fix handling of properties
|
||||||
|
perl -077 -pi -e 's/var __get__ = function \(self, func, quotedFuncName\) \{/var __get__ = function (self, func, quotedFuncName) { if(typeof(func) != "function"){return func;}/g' eos/__javascript__/$f.js
|
||||||
|
|
||||||
# Transcrypt bug
|
# Transcrypt bug
|
||||||
perl -0777 -pi -e 's/property.call \((.*?), \g1.\g1.__impl__(.*?)\)/property.call ($1, $1.__impl__$2)/g' eos/__javascript__/$f.js
|
perl -0777 -pi -e 's/property.call \((.*?), \g1.\g1.__impl__(.*?)\)/property.call ($1, $1.__impl__$2)/g' eos/__javascript__/$f.js
|
||||||
done
|
done
|
||||||
|
@ -55,6 +55,9 @@ class BigInt(EosObject):
|
|||||||
('__add__', 'add'),
|
('__add__', 'add'),
|
||||||
('__sub__', 'subtract'),
|
('__sub__', 'subtract'),
|
||||||
('__mul__', 'multiply'),
|
('__mul__', 'multiply'),
|
||||||
|
('__floordiv__', 'divide'),
|
||||||
|
('__truediv__', 'divide'),
|
||||||
|
('__div__', 'divide'), # TNYI: Still uses Python 2...
|
||||||
('__mod__', 'mod'),
|
('__mod__', 'mod'),
|
||||||
('__and__', 'and'),
|
('__and__', 'and'),
|
||||||
('__or__', 'or'),
|
('__or__', 'or'),
|
||||||
@ -88,6 +91,16 @@ class BigInt(EosObject):
|
|||||||
return operator_func
|
return operator_func
|
||||||
setattr(self, key, make_operator_func(func))
|
setattr(self, key, make_operator_func(func))
|
||||||
|
|
||||||
|
for key, func in [
|
||||||
|
('__neg__', 'negate')
|
||||||
|
]:
|
||||||
|
def make_operator_func(func_):
|
||||||
|
# Create a closure
|
||||||
|
def operator_func():
|
||||||
|
return BigInt((getattr(self.impl, func_).bind(self.impl))())
|
||||||
|
return operator_func
|
||||||
|
setattr(self, key, make_operator_func(func))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.impl)
|
return str(self.impl)
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@ class BigInt(EosObject):
|
|||||||
modulo = BigInt(modulo)
|
modulo = BigInt(modulo)
|
||||||
return BigInt(self.impl.__pow__(other.impl, modulo.impl))
|
return BigInt(self.impl.__pow__(other.impl, modulo.impl))
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
# Python will try to compute this as a float
|
||||||
|
return self.__floordiv__(other)
|
||||||
|
|
||||||
def nbits(self):
|
def nbits(self):
|
||||||
return math.ceil(math.log2(self.impl)) if self.impl > 0 else 0
|
return math.ceil(math.log2(self.impl)) if self.impl > 0 else 0
|
||||||
|
|
||||||
@ -58,7 +62,7 @@ class BigInt(EosObject):
|
|||||||
def crypto_random(cls, lower_bound, upper_bound):
|
def crypto_random(cls, lower_bound, upper_bound):
|
||||||
return cls(system_random.randint(int(lower_bound), int(upper_bound)))
|
return cls(system_random.randint(int(lower_bound), int(upper_bound)))
|
||||||
|
|
||||||
for func in ['__add__', '__sub__', '__mul__', '__mod__', '__and__', '__or__', '__lshift__', '__rshift__', '__xor__']:
|
for func in ['__add__', '__sub__', '__mul__', '__floordiv__', '__mod__', '__and__', '__or__', '__lshift__', '__rshift__', '__xor__']:
|
||||||
def make_operator_func(func_):
|
def make_operator_func(func_):
|
||||||
# Create a closure
|
# Create a closure
|
||||||
def operator_func(self, other):
|
def operator_func(self, other):
|
||||||
@ -78,6 +82,14 @@ for func in ['__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__']:
|
|||||||
return operator_func
|
return operator_func
|
||||||
setattr(BigInt, func, make_operator_func(func))
|
setattr(BigInt, func, make_operator_func(func))
|
||||||
|
|
||||||
|
for func in ['__neg__']:
|
||||||
|
def make_operator_func(func_):
|
||||||
|
# Create a closure
|
||||||
|
def operator_func(self):
|
||||||
|
return BigInt(getattr(self.impl, func_)())
|
||||||
|
return operator_func
|
||||||
|
setattr(BigInt, func, make_operator_func(func))
|
||||||
|
|
||||||
for func in ['__str__', '__int__']:
|
for func in ['__str__', '__int__']:
|
||||||
def make_operator_func(func_):
|
def make_operator_func(func_):
|
||||||
# Create a closure
|
# Create a closure
|
||||||
|
@ -33,6 +33,13 @@ class EosTestCase:
|
|||||||
if not a:
|
if not a:
|
||||||
raise Error('Assertion failed: ' + str(a) + ' not True')
|
raise Error('Assertion failed: ' + str(a) + ' not True')
|
||||||
|
|
||||||
|
def assertFalse(self, a):
|
||||||
|
if is_python:
|
||||||
|
self.impl.assertFalse(a)
|
||||||
|
else:
|
||||||
|
if not a:
|
||||||
|
raise Error('Assertion failed: ' + str(a) + ' not False')
|
||||||
|
|
||||||
def assertEqual(self, a, b):
|
def assertEqual(self, a, b):
|
||||||
if is_python:
|
if is_python:
|
||||||
self.impl.assertEqual(a, b)
|
self.impl.assertEqual(a, b)
|
||||||
|
@ -26,12 +26,21 @@ class CyclicGroup(EmbeddedObject):
|
|||||||
@property
|
@property
|
||||||
def q(self):
|
def q(self):
|
||||||
# p = 2q + 1
|
# p = 2q + 1
|
||||||
return (self.p - ONE) // TWO
|
return (self.p - ONE) / TWO
|
||||||
|
|
||||||
def random_element(self, crypto_random=True):
|
def random_Zp_element(self, crypto_random=True):
|
||||||
crypto_method = BigInt.crypto_random if crypto_random else BigInt.noncrypto_random
|
crypto_method = BigInt.crypto_random if crypto_random else BigInt.noncrypto_random
|
||||||
return crypto_method(ONE, self.p - ONE)
|
return crypto_method(ONE, self.p - ONE)
|
||||||
|
|
||||||
|
def random_Zps_element(self, crypto_random=True):
|
||||||
|
crypto_method = BigInt.crypto_random if crypto_random else BigInt.noncrypto_random
|
||||||
|
# Z_p* = {1..p-1} provided that p is a prime
|
||||||
|
return crypto_method(ONE, self.p - ONE)
|
||||||
|
|
||||||
|
def random_Zq_element(self, crypto_random=True):
|
||||||
|
crypto_method = BigInt.crypto_random if crypto_random else BigInt.noncrypto_random
|
||||||
|
return crypto_method(ZERO, self.q - ONE)
|
||||||
|
|
||||||
# RFC 3526
|
# RFC 3526
|
||||||
DEFAULT_GROUP = CyclicGroup(
|
DEFAULT_GROUP = CyclicGroup(
|
||||||
p=BigInt('FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF', 16),
|
p=BigInt('FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF', 16),
|
||||||
@ -42,10 +51,12 @@ class EGPublicKey(EmbeddedObject):
|
|||||||
group = EmbeddedObjectField(CyclicGroup)
|
group = EmbeddedObjectField(CyclicGroup)
|
||||||
X = EmbeddedObjectField(BigInt)
|
X = EmbeddedObjectField(BigInt)
|
||||||
|
|
||||||
# HAC 8.18
|
def nbits(self):
|
||||||
def encrypt(self, message):
|
# Our messages are restricted to G_q
|
||||||
message += ONE # Dodgy hack to allow zeroes
|
return self.group.q.nbits() - 1
|
||||||
|
|
||||||
|
# HAC 8.18
|
||||||
|
def _encrypt(self, message):
|
||||||
if message <= ZERO:
|
if message <= ZERO:
|
||||||
raise Exception('Invalid message')
|
raise Exception('Invalid message')
|
||||||
if message >= self.group.p:
|
if message >= self.group.p:
|
||||||
@ -59,6 +70,23 @@ class EGPublicKey(EmbeddedObject):
|
|||||||
|
|
||||||
return EGCiphertext(public_key=self, gamma=gamma, delta=delta)
|
return EGCiphertext(public_key=self, gamma=gamma, delta=delta)
|
||||||
|
|
||||||
|
# Adida 2008
|
||||||
|
def encrypt(self, message):
|
||||||
|
if message < ZERO:
|
||||||
|
raise Exception('Invalid message')
|
||||||
|
if message >= self.group.q:
|
||||||
|
raise Exception('Invalid message')
|
||||||
|
|
||||||
|
m0 = message + ONE
|
||||||
|
|
||||||
|
if pow(m0, self.group.q, self.group.p) == ONE:
|
||||||
|
# m0 is already in G_q
|
||||||
|
return self._encrypt(m0)
|
||||||
|
else:
|
||||||
|
# For the life of me I can't find any reputable references for this aside from Adida 2008...
|
||||||
|
m0 = (-m0) % self.group.p
|
||||||
|
return self._encrypt(m0)
|
||||||
|
|
||||||
class EGPrivateKey(EmbeddedObject):
|
class EGPrivateKey(EmbeddedObject):
|
||||||
pk_class = EGPublicKey
|
pk_class = EGPublicKey
|
||||||
|
|
||||||
@ -88,7 +116,12 @@ class EGPrivateKey(EmbeddedObject):
|
|||||||
gamma_inv = pow(ciphertext.gamma, self.public_key.group.p - ONE - self.x, self.public_key.group.p)
|
gamma_inv = pow(ciphertext.gamma, self.public_key.group.p - ONE - self.x, self.public_key.group.p)
|
||||||
|
|
||||||
pt = (gamma_inv * ciphertext.delta) % self.public_key.group.p
|
pt = (gamma_inv * ciphertext.delta) % self.public_key.group.p
|
||||||
return pt - ONE
|
|
||||||
|
# Undo the encryption mapping
|
||||||
|
if pt < self.public_key.group.q:
|
||||||
|
return pt - ONE
|
||||||
|
else:
|
||||||
|
return ((-pt) % self.public_key.group.p) - ONE
|
||||||
|
|
||||||
class EGCiphertext(EmbeddedObject):
|
class EGCiphertext(EmbeddedObject):
|
||||||
public_key = EmbeddedObjectField(EGPublicKey)
|
public_key = EmbeddedObjectField(EGPublicKey)
|
||||||
@ -106,14 +139,7 @@ class EGCiphertext(EmbeddedObject):
|
|||||||
|
|
||||||
# Signed ElGamal per Schnorr & Jakobssen
|
# Signed ElGamal per Schnorr & Jakobssen
|
||||||
class SEGPublicKey(EGPublicKey):
|
class SEGPublicKey(EGPublicKey):
|
||||||
def encrypt(self, message):
|
def _encrypt(self, message):
|
||||||
message += ONE # Dodgy hack to allow zeroes
|
|
||||||
|
|
||||||
if message <= ZERO:
|
|
||||||
raise Exception('Invalid message')
|
|
||||||
if message >= self.group.p:
|
|
||||||
raise Exception('Invalid message')
|
|
||||||
|
|
||||||
# Choose an element 1 <= k <= p - 2
|
# Choose an element 1 <= k <= p - 2
|
||||||
r = BigInt.crypto_random(ONE, self.group.p - TWO)
|
r = BigInt.crypto_random(ONE, self.group.p - TWO)
|
||||||
s = BigInt.crypto_random(ONE, self.group.p - TWO)
|
s = BigInt.crypto_random(ONE, self.group.p - TWO)
|
||||||
@ -163,6 +189,7 @@ class PedersenVSSPrivateKey(EmbeddedObject):
|
|||||||
def get_modified_secret(self):
|
def get_modified_secret(self):
|
||||||
mod_s = self.x
|
mod_s = self.x
|
||||||
for j in range(1, threshold + 1): # 1 to threshold
|
for j in range(1, threshold + 1): # 1 to threshold
|
||||||
|
...
|
||||||
|
|
||||||
def decrypt(self, ciphertext):
|
def decrypt(self, ciphertext):
|
||||||
if (
|
if (
|
||||||
|
@ -29,8 +29,8 @@ class BlockEncryptedAnswer(EncryptedAnswer):
|
|||||||
pt = EosObject.to_json(EosObject.serialise_and_wrap(obj))
|
pt = EosObject.to_json(EosObject.serialise_and_wrap(obj))
|
||||||
bs = BitStream()
|
bs = BitStream()
|
||||||
bs.write_string(pt)
|
bs.write_string(pt)
|
||||||
bs.multiple_of(pk.group.p.nbits() - 1, True)
|
bs.multiple_of(pk.nbits(), True)
|
||||||
ct = bs.map(pk.encrypt, pk.group.p.nbits() - 1)
|
ct = bs.map(pk.encrypt, pk.nbits())
|
||||||
|
|
||||||
return cls(blocks=ct)
|
return cls(blocks=ct)
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class BlockEncryptedAnswer(EncryptedAnswer):
|
|||||||
if sk is None:
|
if sk is None:
|
||||||
sk = self.recurse_parents(PSRElection).sk
|
sk = self.recurse_parents(PSRElection).sk
|
||||||
|
|
||||||
bs = BitStream.unmap(self.blocks, sk.decrypt, sk.public_key.group.p.nbits() - 1)
|
bs = BitStream.unmap(self.blocks, sk.decrypt, sk.public_key.nbits())
|
||||||
m = bs.read_string()
|
m = bs.read_string()
|
||||||
obj = EosObject.deserialise_and_unwrap(EosObject.from_json(m))
|
obj = EosObject.deserialise_and_unwrap(EosObject.from_json(m))
|
||||||
|
|
||||||
@ -155,4 +155,6 @@ class PSRElection(Election):
|
|||||||
_db_name = Election._name
|
_db_name = Election._name
|
||||||
|
|
||||||
sk = EmbeddedObjectField(SEGPrivateKey) # TODO: Threshold
|
sk = EmbeddedObjectField(SEGPrivateKey) # TODO: Threshold
|
||||||
|
|
||||||
|
public_key = EmbeddedObjectField(SEGPublicKey)
|
||||||
mixing_trustees = EmbeddedObjectListField(MixingTrustee)
|
mixing_trustees = EmbeddedObjectListField(MixingTrustee)
|
||||||
|
@ -57,7 +57,7 @@ class RPCMixnet:
|
|||||||
# And shuffle it to the new position
|
# And shuffle it to the new position
|
||||||
shuffled_answers[permutations[i]] = BlockEncryptedAnswer(blocks=shuffled_blocks)
|
shuffled_answers[permutations[i]] = BlockEncryptedAnswer(blocks=shuffled_blocks)
|
||||||
# Record the parameters
|
# Record the parameters
|
||||||
permutations_and_reenc.append([permutations[i], block_reencryptions, block.public_key.group.random_element(), block.public_key.group.random_element()])
|
permutations_and_reenc.append([permutations[i], block_reencryptions, block.public_key.group.random_Zq_element(), block.public_key.group.random_Zq_element()])
|
||||||
|
|
||||||
commitments = []
|
commitments = []
|
||||||
if self.is_left:
|
if self.is_left:
|
||||||
|
@ -70,20 +70,18 @@ class PedersenVSSParticipant():
|
|||||||
def commit_pk_share(self):
|
def commit_pk_share(self):
|
||||||
# Generate random polynomial
|
# Generate random polynomial
|
||||||
for _ in range(0, self.setup.threshold): # 0 to k-1
|
for _ in range(0, self.setup.threshold): # 0 to k-1
|
||||||
coeff = self.setup.group.random_element()
|
coeff = self.setup.group.random_Zq_element()
|
||||||
self.f.coefficients.append(coeff)
|
self.f.coefficients.append(coeff)
|
||||||
#self.F.append(PedersenVSSCommitment(val=coeff, rand=self.sk.public_key.group.random_element()))
|
|
||||||
self.F.append(pow(self.setup.group.g, coeff, self.setup.group.p))
|
self.F.append(pow(self.setup.group.g, coeff, self.setup.group.p))
|
||||||
|
|
||||||
self.h = PedersenVSSCommitment(val=self.F[0], rand=self.setup.group.random_element())
|
self.h = PedersenVSSCommitment(val=self.F[0], rand=self.setup.group.random_Zq_element())
|
||||||
self.h_commitment = SHA256().update_obj(self.h).hash_as_bigint()
|
self.h_commitment = SHA256().update_obj(self.h).hash_as_bigint()
|
||||||
|
|
||||||
return self.h_commitment
|
return self.h_commitment
|
||||||
|
|
||||||
def get_share_for(self, other_idx):
|
def get_share_for(self, other_idx):
|
||||||
other = self.setup.participants[other_idx]
|
other = self.setup.participants[other_idx]
|
||||||
#return other.pk.encrypt(self.f.value(other_idx + 1) % self.setup.group.p)
|
return BitStream().write_bigint(self.f.value(other_idx + 1)).multiple_of(other.pk.nbits(), True).map(other.pk.encrypt, other.pk.nbits())
|
||||||
return BitStream().write_bigint(self.f.value(other_idx + 1)).multiple_of(other.pk.group.p.nbits(), True).map(other.pk.encrypt, other.pk.group.p.nbits())
|
|
||||||
|
|
||||||
def compute_secret_key(self):
|
def compute_secret_key(self):
|
||||||
x = ZERO
|
x = ZERO
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
from eos.core.tests import *
|
from eos.core.tests import *
|
||||||
|
|
||||||
|
from eos.core.objects import __pragma__
|
||||||
from eos.core.bigint import *
|
from eos.core.bigint import *
|
||||||
from eos.core.hashing import *
|
from eos.core.hashing import *
|
||||||
from eos.psr.bitstream import *
|
from eos.psr.bitstream import *
|
||||||
@ -25,9 +26,45 @@ from eos.psr.mixnet import *
|
|||||||
from eos.psr.secretsharing import *
|
from eos.psr.secretsharing import *
|
||||||
from eos.psr.workflow import *
|
from eos.psr.workflow import *
|
||||||
|
|
||||||
|
class GroupValidityTestCase(EosTestCase):
|
||||||
|
# HAC 4.24
|
||||||
|
def miller_rabin_test(self, n, t):
|
||||||
|
# Write n - 1 = 2^s * r such that r is odd
|
||||||
|
s = 0
|
||||||
|
r = n - ONE
|
||||||
|
while r % TWO == ZERO:
|
||||||
|
r = r // TWO
|
||||||
|
s = s + 1
|
||||||
|
for _ in range(t):
|
||||||
|
a = BigInt.noncrypto_random(TWO, n - TWO)
|
||||||
|
y = pow(a, r, n)
|
||||||
|
if y != ONE and y != (n - ONE):
|
||||||
|
j = 1
|
||||||
|
while j <= s - 1 and y != (n - ONE):
|
||||||
|
y = pow(y, TWO, n)
|
||||||
|
if y == ONE:
|
||||||
|
return False
|
||||||
|
j = j + 1
|
||||||
|
if y != (n - ONE):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
@py_only
|
||||||
|
def test_miller_rabin(self):
|
||||||
|
self.assertTrue(self.miller_rabin_test(BigInt('7'), 30))
|
||||||
|
self.assertFalse(self.miller_rabin_test(BigInt('35'), 30))
|
||||||
|
self.assertTrue(self.miller_rabin_test(BigInt('15485863'), 30))
|
||||||
|
self.assertFalse(self.miller_rabin_test(BigInt('502560280658509'), 30)) # 15485863 * 32452843
|
||||||
|
|
||||||
|
@py_only
|
||||||
|
def test_default_group_validity(self):
|
||||||
|
self.assertTrue(self.miller_rabin_test(DEFAULT_GROUP.p, 30))
|
||||||
|
self.assertTrue(self.miller_rabin_test(DEFAULT_GROUP.q, 30))
|
||||||
|
# Since the subgroup G_q is of prime order q, g != 1 is a generator
|
||||||
|
|
||||||
class EGTestCase(EosTestCase):
|
class EGTestCase(EosTestCase):
|
||||||
def test_eg(self):
|
def test_eg(self):
|
||||||
pt = DEFAULT_GROUP.random_element()
|
pt = DEFAULT_GROUP.random_Zq_element()
|
||||||
sk = EGPrivateKey.generate()
|
sk = EGPrivateKey.generate()
|
||||||
ct = sk.public_key.encrypt(pt)
|
ct = sk.public_key.encrypt(pt)
|
||||||
m = sk.decrypt(ct)
|
m = sk.decrypt(ct)
|
||||||
@ -35,7 +72,7 @@ class EGTestCase(EosTestCase):
|
|||||||
|
|
||||||
class SEGTestCase(EosTestCase):
|
class SEGTestCase(EosTestCase):
|
||||||
def test_eg(self):
|
def test_eg(self):
|
||||||
pt = DEFAULT_GROUP.random_element()
|
pt = DEFAULT_GROUP.random_Zq_element()
|
||||||
sk = SEGPrivateKey.generate()
|
sk = SEGPrivateKey.generate()
|
||||||
ct = sk.public_key.encrypt(pt)
|
ct = sk.public_key.encrypt(pt)
|
||||||
self.assertTrue(ct.is_signature_valid())
|
self.assertTrue(ct.is_signature_valid())
|
||||||
@ -98,11 +135,11 @@ class BlockEGTestCase(EosTestCase):
|
|||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
pt = BigInt('11010010011111010100101', 2)
|
pt = BigInt('11010010011111010100101', 2)
|
||||||
ct = BitStream(pt).multiple_of(self.test_group.p.nbits() - 1).map(self.sk.public_key.encrypt, self.test_group.p.nbits() - 1)
|
ct = BitStream(pt).multiple_of(self.sk.public_key.nbits()).map(self.sk.public_key.encrypt, self.sk.public_key.nbits())
|
||||||
for i in range(len(ct)):
|
for i in range(len(ct)):
|
||||||
self.assertTrue(ct[i].gamma < self.test_group.p)
|
self.assertTrue(ct[i].gamma < self.test_group.p)
|
||||||
self.assertTrue(ct[i].delta < self.test_group.p)
|
self.assertTrue(ct[i].delta < self.test_group.p)
|
||||||
m = BitStream.unmap(ct, self.sk.decrypt, self.test_group.p.nbits() - 1).read()
|
m = BitStream.unmap(ct, self.sk.decrypt, self.sk.public_key.nbits()).read()
|
||||||
self.assertEqualJSON(pt, m)
|
self.assertEqualJSON(pt, m)
|
||||||
|
|
||||||
def test_object(self):
|
def test_object(self):
|
||||||
@ -122,14 +159,14 @@ class MixnetTestCase(EosTestCase):
|
|||||||
# Generate plaintexts
|
# Generate plaintexts
|
||||||
pts = []
|
pts = []
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
pts.append(sk.public_key.group.random_element())
|
pts.append(sk.public_key.group.random_Zq_element())
|
||||||
|
|
||||||
# Encrypt plaintexts
|
# Encrypt plaintexts
|
||||||
answers = []
|
answers = []
|
||||||
for i in range(len(pts)):
|
for i in range(len(pts)):
|
||||||
bs = BitStream(pts[i])
|
bs = BitStream(pts[i])
|
||||||
bs.multiple_of(sk.public_key.group.p.nbits() - 1)
|
bs.multiple_of(sk.public_key.nbits())
|
||||||
ct = bs.map(sk.public_key.encrypt, sk.public_key.group.p.nbits() - 1)
|
ct = bs.map(sk.public_key.encrypt, sk.public_key.nbits())
|
||||||
answers.append(BlockEncryptedAnswer(blocks=ct))
|
answers.append(BlockEncryptedAnswer(blocks=ct))
|
||||||
|
|
||||||
def do_mixnet(mix_order):
|
def do_mixnet(mix_order):
|
||||||
@ -142,7 +179,7 @@ class MixnetTestCase(EosTestCase):
|
|||||||
# Decrypt shuffle
|
# Decrypt shuffle
|
||||||
msgs = []
|
msgs = []
|
||||||
for i in range(len(shuffled_answers)):
|
for i in range(len(shuffled_answers)):
|
||||||
bs = BitStream.unmap(shuffled_answers[i].blocks, sk.decrypt, sk.public_key.group.p.nbits() - 1)
|
bs = BitStream.unmap(shuffled_answers[i].blocks, sk.decrypt, sk.public_key.nbits())
|
||||||
m = bs.read()
|
m = bs.read()
|
||||||
msgs.append(m)
|
msgs.append(m)
|
||||||
|
|
||||||
@ -202,6 +239,7 @@ class ElectionTestCase(EosTestCase):
|
|||||||
election.mixing_trustees.append(mixing_trustee)
|
election.mixing_trustees.append(mixing_trustee)
|
||||||
|
|
||||||
election.sk = EGPrivateKey.generate()
|
election.sk = EGPrivateKey.generate()
|
||||||
|
election.public_key = election.sk.public_key
|
||||||
|
|
||||||
question = ApprovalQuestion(prompt='President', choices=['John Smith', 'Joe Bloggs', 'John Q. Public'])
|
question = ApprovalQuestion(prompt='President', choices=['John Smith', 'Joe Bloggs', 'John Q. Public'])
|
||||||
election.questions.append(question)
|
election.questions.append(question)
|
||||||
@ -302,6 +340,7 @@ class ElectionTestCase(EosTestCase):
|
|||||||
class AAAPVSSTestCase(EosTestCase):
|
class AAAPVSSTestCase(EosTestCase):
|
||||||
@py_only
|
@py_only
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
|
return
|
||||||
setup = PedersenVSSSetup()
|
setup = PedersenVSSSetup()
|
||||||
setup.group = DEFAULT_GROUP
|
setup.group = DEFAULT_GROUP
|
||||||
setup.threshold = 3 # 3 of 5
|
setup.threshold = 3 # 3 of 5
|
||||||
@ -326,7 +365,7 @@ class AAAPVSSTestCase(EosTestCase):
|
|||||||
other = setup.participants[j]
|
other = setup.participants[j]
|
||||||
share = participant.get_share_for(j)
|
share = participant.get_share_for(j)
|
||||||
#share_dec = other.sk.decrypt(share)
|
#share_dec = other.sk.decrypt(share)
|
||||||
share_dec = BitStream.unmap(share, other.sk.decrypt, other.sk.public_key.group.p.nbits()).read_bigint()
|
share_dec = BitStream.unmap(share, other.sk.decrypt, other.sk.public_key.nbits()).read_bigint()
|
||||||
other.shares_received.append(share_dec)
|
other.shares_received.append(share_dec)
|
||||||
|
|
||||||
# Step 2
|
# Step 2
|
||||||
@ -345,7 +384,6 @@ class AAAPVSSTestCase(EosTestCase):
|
|||||||
for k in range(0, setup.threshold):
|
for k in range(0, setup.threshold):
|
||||||
g_share_dec_expected = (g_share_dec_expected * pow(participant.F[k], pow(j + 1, k), setup.group.p)) % setup.group.p
|
g_share_dec_expected = (g_share_dec_expected * pow(participant.F[k], pow(j + 1, k), setup.group.p)) % setup.group.p
|
||||||
if pow(setup.group.g, share_dec, setup.group.p) != g_share_dec_expected:
|
if pow(setup.group.g, share_dec, setup.group.p) != g_share_dec_expected:
|
||||||
import pdb; pdb.set_trace()
|
|
||||||
raise Exception('Share not consistent with commitments')
|
raise Exception('Share not consistent with commitments')
|
||||||
|
|
||||||
# Compute threshold public key
|
# Compute threshold public key
|
||||||
@ -357,7 +395,7 @@ class AAAPVSSTestCase(EosTestCase):
|
|||||||
|
|
||||||
# Encrypt data
|
# Encrypt data
|
||||||
|
|
||||||
pt = pk.group.random_element()
|
pt = pk.group.random_Zq_element()
|
||||||
ct = pk.encrypt(pt)
|
ct = pk.encrypt(pt)
|
||||||
|
|
||||||
# Decrypt data
|
# Decrypt data
|
||||||
|
Loading…
Reference in New Issue
Block a user