Refactor hashing out into separate library
This commit is contained in:
parent
3427b376b5
commit
a242f1f666
82
eos/core/hashing/__init__.py
Normal file
82
eos/core/hashing/__init__.py
Normal file
@ -0,0 +1,82 @@
|
||||
# Eos - Verifiable elections
|
||||
# Copyright © 2017 RunasSudo (Yingtong Li)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
try:
|
||||
__pragma__ = __pragma__
|
||||
is_python = False
|
||||
except:
|
||||
is_python = True
|
||||
def __pragma__(*args):
|
||||
pass
|
||||
|
||||
from eos.core.bigint import *
|
||||
|
||||
# Libraries
|
||||
# =========
|
||||
|
||||
if is_python:
|
||||
__pragma__('skip')
|
||||
import base64
|
||||
import hashlib
|
||||
__pragma__('noskip')
|
||||
else:
|
||||
# Load jssha-sha256.js
|
||||
lib = __pragma__('js', '''
|
||||
(function() {{
|
||||
{}
|
||||
var exports = {{}};
|
||||
exports.jsSHA = window.jsSHA;
|
||||
return exports;
|
||||
}})()''', __include__('eos/core/hashing/jssha-sha256.js'))
|
||||
|
||||
# Implementation
|
||||
# ==============
|
||||
|
||||
class SHA256:
|
||||
def __init__(self):
|
||||
if is_python:
|
||||
self.impl = hashlib.sha256()
|
||||
else:
|
||||
# TNYI: This is completely borked
|
||||
self.impl = __pragma__('js', '{}', 'new lib.jsSHA("SHA-256", "TEXT")')
|
||||
|
||||
def update_text(self, *values):
|
||||
for value in values:
|
||||
if is_python:
|
||||
self.impl.update(value.encode('utf-8'))
|
||||
else:
|
||||
self.impl.js_update(value)
|
||||
return self
|
||||
|
||||
def update_bigint(self, *values):
|
||||
for value in values:
|
||||
self.update_text(str(value))
|
||||
return self
|
||||
|
||||
def hash_as_b64(self):
|
||||
if is_python:
|
||||
return base64.b64encode(self.impl.digest()).decode('utf-8')
|
||||
else:
|
||||
return self.impl.getHash('B64')
|
||||
|
||||
def hash_as_hex(self):
|
||||
if is_python:
|
||||
return self.impl.hexdigest()
|
||||
else:
|
||||
return self.impl.getHash('HEX')
|
||||
|
||||
def hash_as_bigint(self):
|
||||
return BigInt(self.hash_as_hex(), 16)
|
@ -36,16 +36,14 @@ if is_python:
|
||||
import uuid
|
||||
__pragma__('noskip')
|
||||
else:
|
||||
# Load json.js, jssha-sha256.js
|
||||
# Load json.js
|
||||
lib = __pragma__('js', '''
|
||||
(function() {{
|
||||
{}
|
||||
{}
|
||||
var exports = {{}};
|
||||
exports.stringify = stringify_main;
|
||||
exports.jsSHA = window.jsSHA;
|
||||
return exports;
|
||||
}})()''', __include__('eos/core/objects/json.js'), __include__('eos/core/objects/jssha-sha256.js'))
|
||||
}})()''', __include__('eos/core/objects/json.js'))
|
||||
|
||||
# Database
|
||||
# ========
|
||||
@ -155,7 +153,7 @@ class EosObject(metaclass=EosObjectType):
|
||||
|
||||
@property
|
||||
def hash(self):
|
||||
return EosObject.to_sha256(EosObject.to_json(EosObject.serialise_and_wrap(self)))[0]
|
||||
return SHA256().update_text(EosObject.to_json(EosObject.serialise_and_wrap(self))).hash_as_b64()
|
||||
|
||||
@staticmethod
|
||||
def serialise_and_wrap(value, object_type=None):
|
||||
@ -185,22 +183,6 @@ class EosObject(metaclass=EosObjectType):
|
||||
else:
|
||||
return JSON.parse(value)
|
||||
|
||||
@staticmethod
|
||||
def to_sha256(*values):
|
||||
from eos.core.bigint import BigInt
|
||||
|
||||
if is_python:
|
||||
sha_obj = hashlib.sha256()
|
||||
for value in values:
|
||||
sha_obj.update(value.encode('utf-8'))
|
||||
return base64.b64encode(sha_obj.digest()).decode('utf-8'), BigInt(sha_obj.hexdigest(), 16)
|
||||
else:
|
||||
# TNYI: This is completely borked
|
||||
sha_obj = __pragma__('js', '{}', 'new lib.jsSHA("SHA-256", "TEXT")')
|
||||
for value in values:
|
||||
sha_obj.js_update(value)
|
||||
return sha_obj.getHash('B64'), BigInt(sha_obj.getHash('HEX'), 16)
|
||||
|
||||
class EosList(EosObject):
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
from eos.core.bigint import *
|
||||
from eos.core.objects import *
|
||||
from eos.core.hashing import *
|
||||
|
||||
# Common library things
|
||||
# ===================
|
||||
@ -95,7 +96,7 @@ class ObjectTestCase(EosTestCase):
|
||||
|
||||
class HashTestCase(EosTestCase):
|
||||
def test_hash(self):
|
||||
self.assertEqual(EosObject.to_sha256('Hello World!')[0], 'f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=')
|
||||
self.assertEqual(SHA256().update_text('Hello World!').hash_as_b64(), 'f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk=')
|
||||
|
||||
class BigIntTestCase(EosTestCase):
|
||||
def test_basic(self):
|
||||
|
@ -16,9 +16,13 @@
|
||||
|
||||
import eos.core.objects
|
||||
import eos.core.bigint
|
||||
import eos.core.hashing
|
||||
|
||||
import eos.base.election
|
||||
import eos.base.workflow
|
||||
|
||||
import eos.psr.bitstream
|
||||
import eos.psr.crypto
|
||||
import eos.psr.election
|
||||
import eos.psr.mixnet
|
||||
import eos.psr.workflow
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
from eos.core.bigint import *
|
||||
from eos.core.objects import *
|
||||
from eos.core.hashing import *
|
||||
from eos.base.election import *
|
||||
|
||||
class CyclicGroup(EmbeddedObject):
|
||||
@ -120,7 +121,7 @@ class SEGPublicKey(EGPublicKey):
|
||||
gamma = pow(self.group.g, r, self.group.p) # h
|
||||
delta = (message * pow(self.X, r, self.group.p)) % self.group.p # f
|
||||
|
||||
_, c = EosObject.to_sha256(str(pow(self.group.g, s, self.group.p)), str(gamma), str(delta))
|
||||
c = SHA256().update_bigint(pow(self.group.g, s, self.group.p), gamma, delta).hash_as_bigint()
|
||||
|
||||
z = s + c*r
|
||||
|
||||
@ -136,6 +137,6 @@ class SEGCiphertext(EGCiphertext):
|
||||
|
||||
def is_signature_valid(self):
|
||||
gs = (pow(self.public_key.group.g, self.z, self.public_key.group.p) * pow(self.gamma, self.public_key.group.p - ONE - self.c, self.public_key.group.p)) % self.public_key.group.p
|
||||
_, c = EosObject.to_sha256(str(gs), str(self.gamma), str(self.delta))
|
||||
c = SHA256().update_bigint(gs, self.gamma, self.delta).hash_as_bigint()
|
||||
|
||||
return self.c == c
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
from eos.core.bigint import *
|
||||
from eos.core.objects import *
|
||||
from eos.core.hashing import *
|
||||
from eos.psr.election import *
|
||||
|
||||
class RPCMixnet:
|
||||
@ -63,7 +64,7 @@ class RPCMixnet:
|
||||
for i in range(len(permutations_and_reenc)):
|
||||
val = permutations_and_reenc[i]
|
||||
val_obj = MixChallengeResponse(index=val[0], reenc=val[1], rand=val[2])
|
||||
commitments.append(EosObject.to_sha256(EosObject.to_json(val_obj.serialise()))[1])
|
||||
commitments.append(SHA256().update_text(EosObject.to_json(val_obj.serialise())).hash_as_bigint())
|
||||
else:
|
||||
for i in range(len(permutations_and_reenc)):
|
||||
# Find the answer that went to 'i'
|
||||
@ -71,7 +72,7 @@ class RPCMixnet:
|
||||
val = permutations_and_reenc[idx]
|
||||
|
||||
val_obj = MixChallengeResponse(index=idx, reenc=val[1], rand=val[3])
|
||||
commitments.append(EosObject.to_sha256(EosObject.to_json(val_obj.serialise()))[1])
|
||||
commitments.append(SHA256().update_text(EosObject.to_json(val_obj.serialise())).hash_as_bigint())
|
||||
|
||||
self.params = permutations_and_reenc
|
||||
return shuffled_answers, commitments
|
||||
|
@ -17,6 +17,7 @@
|
||||
from eos.core.tests import *
|
||||
|
||||
from eos.core.bigint import *
|
||||
from eos.core.hashing import *
|
||||
from eos.psr.bitstream import *
|
||||
from eos.psr.crypto import *
|
||||
from eos.psr.election import *
|
||||
@ -158,7 +159,7 @@ class MixnetTestCase(EosTestCase):
|
||||
for i in range(len(pts)):
|
||||
perm, reencs, rand = mixnet.challenge(i)
|
||||
val_obj = MixChallengeResponse(index=perm, reenc=reencs, rand=rand)
|
||||
self.assertEqual(commitments[i], EosObject.to_sha256(EosObject.to_json(val_obj.serialise()))[1])
|
||||
self.assertEqual(commitments[i], SHA256().update_text(EosObject.to_json(val_obj.serialise())).hash_as_bigint())
|
||||
|
||||
if mixnet.is_left:
|
||||
verify_shuffle(i, perm, reencs)
|
||||
|
Loading…
Reference in New Issue
Block a user