Browse Source

Merge with master from the original depot

git://git.code.sf.net/p/ed448goldilocks/code
master
Johan Pascal 6 years ago
parent
commit
9de0d1a34e
6 changed files with 147 additions and 35 deletions
  1. +4
    -4
      Makefile
  2. +120
    -20
      _aux/ristretto/ristretto.sage
  3. +4
    -1
      src/generator/curve_data.py
  4. +1
    -1
      src/per_curve/decaf.tmpl.c
  5. +1
    -1
      src/per_curve/point.tmpl.hxx
  6. +17
    -8
      test/test_decaf.sage

+ 4
- 4
Makefile View File

@@ -20,11 +20,11 @@ BUILD_IBIN = build/obj/bin
DOXYGEN ?= doxygen

ifeq ($(UNAME),Darwin)
CC = clang
CXX = clang++
CC ?= clang
CXX ?= clang++
else
CC = gcc
CXX = g++
CC ?= gcc
CXX ?= g++
endif
LD = $(CC)
LDXX = $(CXX)


+ 120
- 20
_aux/ristretto/ristretto.sage View File

@@ -121,6 +121,8 @@ class QuotientEdwardsPoint(object):
else:
return self.__class__(-self.x, -self.y)
def doubleAndEncodeSpec(self):
return (self+self).encode()

# Utility functions
@classmethod
@@ -203,7 +205,42 @@ class RistrettoPoint(QuotientEdwardsPoint):
if negative(isr^2*num*y*t): y = -y
s = isr*y*(z-y)
return self.gfToBytes(s,mustBePositive=True)
@optimized_version_of("doubleAndEncodeSpec")
def doubleAndEncode(self):
X,Y,Z,T = self.xyzt()
a,d,mneg = self.a,self.d,self.mneg

if self.cofactor==8:
e = 2*X*Y
f = Z^2+d*T^2
g = Y^2-a*X^2
h = Z^2-d*T^2
inv1 = inv0(e*f*g*h)
z_inv = inv1*e*g # 1 / (f*h)
t_inv = inv1*f*h
if negative(e*g*z_inv):
if a==-1: sqrta = self.i
else: sqrta = -1
e,f,g,h = g,h,-e,f*sqrta
factor = self.i
else:
factor = self.magic
if negative(h*e*z_inv): g=-g
s = (h-g)*factor*g*t_inv
else:
foo = Y^2+a*X^2
bar = X*Y
den = inv0(foo*bar)
if negative(2*bar^2*den): tmp = a*X^2
else: tmp = Y^2
s = self.magic*(Z^2-tmp)*foo*den
return self.gfToBytes(s,mustBePositive=True)
@classmethod
@@ -466,6 +503,54 @@ class Decaf_1_1_Point(QuotientEdwardsPoint):
x = 2*s / (1+a*s^2)
y = (1-a*s^2) / t
return cls(x,sgn*y)

@optimized_version_of("doubleAndEncodeSpec")
def doubleAndEncode(self):
X,Y,Z,T = self.xyzt()
a,d = self.a,self.d
if self.cofactor == 8:
# Cofactor 8 version
# Simulate IMAGINE_TWIST because that's how libdecaf does it
X = self.i*X
T = self.i*T
a = -a
d = -d
# TODO: This is only being called for a=-1, so could
# be wrong for a=1
e = 2*X*Y
f = Y^2+a*X^2
g = Y^2-a*X^2
h = Z^2-d*T^2
eim = e*self.isoMagic
inv = inv0(eim*g*f*h)
fh_inv = eim*g*inv*self.i
if negative(eim*g*fh_inv):
idf = g*self.isoMagic*self.i
bar = f
foo = g
test = eim*f
else:
idf = eim
bar = h
foo = -eim
test = g*h
if negative(test*fh_inv): bar =- bar
s = idf*(foo+bar)*inv*f*h
else:
xy = X*Y
h = Z^2-d*T^2
inv = inv0(xy*h)
if negative(inv*2*xy^2*self.isoMagic): tmp = Y
else: tmp = X
s = tmp^2*h*inv # = X/Y or Y/X, interestingly
return self.gfToBytes(s,mustBePositive=True)
@classmethod
def elligatorSpec(cls,r0,fromR=False):
@@ -696,7 +781,6 @@ def test(cls,n):
if Q1 + Q0 != Q2: raise TestFailedException("Scalarmul doesn't work")
Q = Q1
def testElligator(cls,n):
print "Testing elligator on %s" % cls.__name__
for i in xrange(n):
@@ -716,9 +800,6 @@ def testElligator(cls,n):
#break
else:
pass # TODO



def gangtest(classes,n):
print "Gang test",[cls.__name__ for cls in classes]
@@ -747,18 +828,37 @@ def gangtest(classes,n):
print c,binascii.hexlify(ret)
print


test(Ed25519Point,100)
test(NegEd25519Point,100)
test(IsoEd25519Point,100)
test(IsoEd448Point,100)
test(TwistedEd448GoldilocksPoint,100)
test(Ed448GoldilocksPoint,100)
testElligator(Ed25519Point,100)
testElligator(NegEd25519Point,100)
testElligator(IsoEd25519Point,100)
testElligator(IsoEd448Point,100)
testElligator(Ed448GoldilocksPoint,100)
testElligator(TwistedEd448GoldilocksPoint,100)
gangtest([IsoEd448Point,TwistedEd448GoldilocksPoint,Ed448GoldilocksPoint],100)
gangtest([Ed25519Point,IsoEd25519Point],100)
def testDoubleAndEncode(cls,n):
print "Testing doubleAndEncode on %s" % cls.__name__
P = cls()
for i in xrange(cls.cofactor):
Q = P.torque()
assert P.doubleAndEncode() == Q.doubleAndEncode()
P = Q
for i in xrange(n):
r1 = randombytes(cls.encLen)
r2 = randombytes(cls.encLen)
u = cls.elligator(r1) + cls.elligator(r2)
assert u.doubleAndEncode() == u.torque().doubleAndEncode()

testDoubleAndEncode(Ed25519Point,100)
testDoubleAndEncode(NegEd25519Point,100)
testDoubleAndEncode(IsoEd25519Point,100)
testDoubleAndEncode(IsoEd448Point,100)
testDoubleAndEncode(TwistedEd448GoldilocksPoint,100)
#test(Ed25519Point,100)
#test(NegEd25519Point,100)
#test(IsoEd25519Point,100)
#test(IsoEd448Point,100)
#test(TwistedEd448GoldilocksPoint,100)
#test(Ed448GoldilocksPoint,100)
#testElligator(Ed25519Point,100)
#testElligator(NegEd25519Point,100)
#testElligator(IsoEd25519Point,100)
#testElligator(IsoEd448Point,100)
#testElligator(Ed448GoldilocksPoint,100)
#testElligator(TwistedEd448GoldilocksPoint,100)
#gangtest([IsoEd448Point,TwistedEd448GoldilocksPoint,Ed448GoldilocksPoint],100)
#gangtest([Ed25519Point,IsoEd25519Point],100)

+ 4
- 1
src/generator/curve_data.py View File

@@ -133,8 +133,11 @@ for curve,data in curve_data.items():
data["eddsa_sigma_iso"] = 0
if "rist_base_decoded" not in data:
def xord(x):
if isinstance(x,str): return ord(x)
else: return x
data["rist_base_decoded"] = sum(
ord(b)<<(8*i) for i,b in enumerate(unhexlify(data["rist_base"]))
xord(b)<<(8*i) for i,b in enumerate(unhexlify(data["rist_base"]))
)

if "imagine_twist" not in data:


+ 1
- 1
src/per_curve/decaf.tmpl.c View File

@@ -776,7 +776,7 @@ decaf_bool_t API_NS(point_eq) ( const point_t p, const point_t q ) {
gf_mul ( b, q->y, p->x );
mask_t succ = gf_eq(a,b);
#if (COFACTOR == 8) && IMAGINE_TWIST
#if (COFACTOR == 8)
gf_mul ( a, p->y, q->y );
gf_mul ( b, q->x, p->x );
#if !(IMAGINE_TWIST)


+ 1
- 1
src/per_curve/point.tmpl.hxx View File

@@ -305,7 +305,7 @@ public:
*/
inline explicit Point(const FixedBlock<SER_BYTES> &buffer, bool allow_identity=true)
/*throw(CryptoException)*/ {
if (DECAF_SUCCESS != decode(buffer,allow_identity ? DECAF_TRUE : DECAF_FALSE)) {
if (DECAF_SUCCESS != decode(buffer,allow_identity)) {
throw CryptoException();
}
}


+ 17
- 8
test/test_decaf.sage View File

@@ -10,6 +10,7 @@ p_tor4 = E.lift_x(-1)
Tor = [p_tor4 * i for i in xrange(4)]
q = 2^446-0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
FQ = GF(q)
isoMagic = 1/sqrt(F(39082/39081)-1)

passing = True

@@ -195,7 +196,16 @@ class DecafScalar():
return True

class DecafPoint():
_UNDER = c_uint64 * int(8*4)
@staticmethod
def _UNDER():
size = int(8*8*4)
alignment = 32
buf1 = bytearray(size+alignment-1)
buf2 = (c_char * int(size+alignment-1)).from_buffer(buf1)
raw_addr = addressof(buf2)
offset = (-raw_addr) % alignment
return (c_char*size).from_buffer(buf2,int(offset))
def __init__(self,cstruct=None,point=None):
if cstruct is None:
cstruct = DecafPoint._UNDER()
@@ -222,12 +232,11 @@ class DecafPoint():
@staticmethod
def _sage_deser(str):
s = from_le(str)
if s > (F.cardinality()-1)/2: raise Exception("Point didn't decode")
if is_odd(s): raise Exception("Point didn't decode")
if (s==0): return E(0)
if not E.is_x_coord(s^2): raise Exception("Point didn't decode")
P = E.lift_x(s^2)
t = P.xy()[1] / s
if is_odd(int(2*t/s)): P = -P
if is_odd(int(2*s^2*isoMagic/P.xy()[1])): P = -P
return P
def __eq__(self,other):
@@ -318,16 +327,16 @@ class DecafPoint():
x,y = P.xy()
s = sqrt(x)
if s==0: return to_le(0,56)
if is_odd(int(2*y/s^2)): s = 1/s
if int(s) > (F.cardinality()-1)/2: s = -s
if is_odd(int(2*s^2*isoMagic/y)): s = 1/s
if is_odd(int(s)): s = -s
return to_le(s,56)
def _check(self):
ss = self._sage_ser(self.point)
cs = self._c_ser(self.cstruct)
if ss != cs:
print ss
print cs
print "SAGE",b64encode(ss)
print "C ",b64encode(cs)
raise Exception("Check failed!")
return True


Loading…
Cancel
Save