Skip to content

Commit

Permalink
Added boudot commitment checks
Browse files Browse the repository at this point in the history
  • Loading branch information
qstokkink committed Jun 20, 2019
1 parent 06bc243 commit 288323a
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 37 deletions.
39 changes: 2 additions & 37 deletions ipv8/attestation/wallet/bonehexact/attestation.py
@@ -1,11 +1,12 @@
from __future__ import absolute_import
from __future__ import division

from hashlib import sha256, sha512

from random import randint, shuffle
from threading import Lock

from .structs import BonehAttestation, BitPairAttestation
from ..primitives.attestation import sha256_as_int, sha256_4_as_int, sha512_as_int
from ..primitives.boneh import decode, encode
from ..primitives.value import FP2Value

Expand Down Expand Up @@ -54,18 +55,6 @@ def attest(PK, value, bitspace):
return BonehAttestation(PK, bitpairs)


def sha512_as_int(value):
"""
Convert a SHA512 hash to an integer.
"""
out = 0
hashed = sha512(value).digest()
for i in range(len(hashed)):
out <<= 8
out |= ord(hashed[i:i + 1])
return out


def attest_sha512(PK, value):
"""
Create an attestation for a value using a SHA512 hash.
Expand All @@ -80,18 +69,6 @@ def binary_relativity_sha512(value):
return binary_relativity(sha512_as_int(value), 512)


def sha256_as_int(value):
"""
Convert a SHA256 hash to an integer.
"""
out = 0
hashed = sha256(value).digest()
for i in range(len(hashed)):
out <<= 8
out |= ord(hashed[i:i + 1])
return out


def attest_sha256(PK, value):
"""
Create an attestation for a value using a SHA256 hash.
Expand All @@ -106,18 +83,6 @@ def binary_relativity_sha256(value):
return binary_relativity(sha256_as_int(value), 256)


def sha256_4_as_int(value):
"""
Convert a SHA256 4 byte hash to an integer.
"""
out = 0
hashed = sha256(value).digest()[:4]
for i in range(len(hashed)):
out <<= 8
out |= ord(hashed[i:i + 1])
return out


def attest_sha256_4(PK, value):
"""
Create an attestation for a value using a SHA256 4 byte hash.
Expand Down
151 changes: 151 additions & 0 deletions ipv8/attestation/wallet/pengbaorange/boudot.py
@@ -0,0 +1,151 @@
"""
Implementation of proofs for checking commitment equality and if a commitment is a square ("Efficient Proofs that a
Committed NumberLies in an Interval" by F. Boudot).
Modified for use with range proofs ("An efficient range proof scheme." by K. Peng and F. Bao).
"""
from __future__ import absolute_import, division

from binascii import hexlify
from math import ceil, log
from os import urandom
from struct import pack, unpack

from ..primitives.attestation import sha256_as_int
from ..primitives.structs import ipack, iunpack
from ..primitives.value import FP2Value


def secure_randint(nmin, nmax):
normalized_range = nmax - nmin
n = int(ceil(log(normalized_range, 2)/8.0))
rbytes_int = int(hexlify(urandom(n)), 16)
return nmin + (rbytes_int % normalized_range)


def _sipack(*n):
if len(n) > 8:
raise RuntimeError("More than 8 values specified to _sipack")
sign_byte = 0
packed = b''
for i in n:
sign_byte = sign_byte << 1
sign_byte |= 1 if i < 0 else 0
packed = ipack(-i if i < 0 else i) + packed
return pack(">B", sign_byte) + packed


def _siunpack(buf, amount):
rem = buf[1:]
nums = []
sign_byte, = unpack(">B", buf[0:1])
while rem and len(nums) < amount:
unpacked, rem = iunpack(rem)
negative = sign_byte & 0x01
sign_byte = sign_byte >> 1
nums.append(-unpacked if negative else unpacked)
return reversed(nums)


class EL(object):

def __init__(self, c, D, D1, D2):
self.c = c
self.D = D
self.D1 = D1
self.D2 = D2

@classmethod
def create(cls, x, r1, r2, g1, h1, g2, h2, b, bitspace, t=80, l=40):
maxrange_w = 2^(l+t) * b - 1
maxrange_n = 2^(l+t+bitspace) * g1.mod - 1
w = secure_randint(1, maxrange_w)
n1 = secure_randint(1, maxrange_n)
n2 = secure_randint(1, maxrange_n)
W1 = g1.intpow(w) * h1.intpow(n1)
W2 = g2.intpow(w) * h2.intpow(n2)
cW1 = (W1.wp_nominator() * W1.wp_denom_inverse()).normalize()
cW2 = (W2.wp_nominator() * W2.wp_denom_inverse()).normalize()

c = sha256_as_int(str(cW1.a) + str(cW1.b) + str(cW2.a) + str(cW2.b))
D = w + c * x
D1 = n1 + c * r1
D2 = n2 + c * r2
return cls(c, D, D1, D2)

def check(self, g1, h1, g2, h2, y1, y2):
if self.D1 >= 0:
cW1 = g1.intpow(self.D) * h1.intpow(self.D1) * y1.intpow(self.c).inverse()
else:
cW1 = g1.intpow(self.D) * h1.intpow(-self.D1).inverse() * y1.intpow(self.c).inverse()
if self.D2 >= 0:
cW2 = g2.intpow(self.D) * h2.intpow(self.D2) * y2.intpow(self.c).inverse()
else:
cW2 = g2.intpow(self.D) * h2.intpow(-self.D2).inverse() * y2.intpow(self.c).inverse()
cW1 = (cW1.wp_nominator() * cW1.wp_denom_inverse()).normalize()
cW2 = (cW2.wp_nominator() * cW2.wp_denom_inverse()).normalize()

return self.c == sha256_as_int(str(cW1.a) + str(cW1.b) + str(cW2.a) + str(cW2.b))

def serialize(self):
return _sipack(self.c, self.D, self.D1, self.D2)

@classmethod
def unserialize(cls, s):
return cls(*_siunpack(s, 4))

def __eq__(self, other):
if not isinstance(other, EL):
return False
return (self.c == other.c) and (self.D == other.D) and (self.D1 == other.D1) and (self.D2 == other.D2)

def __hash__(self):
return 6976

def __str__(self):
return 'EL<%d,%d,%d,%d>' % (self.c, self.D, self.D1, self.D2)


class SQR(object):

def __init__(self, F, el):
self.F = F
self.el = el

@classmethod
def create(cls, x, r1, g, h, b, bitspace):
r2 = secure_randint(-2^bitspace * g.mod + 1, 2^bitspace * g.mod -1)
if r2 >= 0:
F = g.intpow(x) * h.intpow(r2)
else:
F = g.intpow(x) * h.intpow(-r2).inverse()
r3 = r1 - r2 * x
return cls(F, EL.create(x, r2, r3, g, h, F, h, b, bitspace))

def check(self, g, h, y):
return self.el.check(g, h, self.F, h, self.F, y)

def serialize(self):
norm_f = self.F.normalize()
min_f = norm_f.wp_nominator() * norm_f.wp_denom_inverse()
return ipack(min_f.mod) + ipack(min_f.a) + ipack(min_f.b) + self.el.serialize()

@classmethod
def unserialize(cls, s):
rem = s
mod, rem = iunpack(rem)
Fa, rem = iunpack(rem)
Fb, rem = iunpack(rem)
el = EL.unserialize(rem)
return cls(FP2Value(mod, Fa, Fb), el)

def __eq__(self, other):
if not isinstance(other, SQR):
return False
return (self.F == other.F) and (self.el == other.el)

def __hash__(self):
return 838182

def __str__(self):
return 'SQR<%s,%s>' % (str(self.F), str(self.el))
37 changes: 37 additions & 0 deletions ipv8/attestation/wallet/primitives/attestation.py
@@ -0,0 +1,37 @@
from hashlib import sha256, sha512


def sha512_as_int(value):
"""
Convert a SHA512 hash to an integer.
"""
out = 0
hashed = sha512(value).digest()
for i in range(len(hashed)):
out <<= 8
out |= ord(hashed[i:i + 1])
return out


def sha256_as_int(value):
"""
Convert a SHA256 hash to an integer.
"""
out = 0
hashed = sha256(value).digest()
for i in range(len(hashed)):
out <<= 8
out |= ord(hashed[i:i + 1])
return out


def sha256_4_as_int(value):
"""
Convert a SHA256 4 byte hash to an integer.
"""
out = 0
hashed = sha256(value).digest()[:4]
for i in range(len(hashed)):
out <<= 8
out |= ord(hashed[i:i + 1])
return out

0 comments on commit 288323a

Please sign in to comment.