From 6a5e8284b3180b620ef26631f39510f1636cbbd9 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Sun, 14 Jan 2018 14:16:05 -0800 Subject: [PATCH 1/8] doubleAndEncode for ristretto in sage doc --- aux/ristretto/ristretto.sage | 87 +++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/aux/ristretto/ristretto.sage b/aux/ristretto/ristretto.sage index 4bb08cc..93127e5 100644 --- a/aux/ristretto/ristretto.sage +++ b/aux/ristretto/ristretto.sage @@ -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 = 1/(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 = 1/(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,10 @@ class Decaf_1_1_Point(QuotientEdwardsPoint): x = 2*s / (1+a*s^2) y = (1-a*s^2) / t return cls(x,sgn*y) + + def doubleAndEncode(self): + # TODO + return self.doubleAndEncodeSpec() @classmethod def elligatorSpec(cls,r0,fromR=False): @@ -696,7 +737,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 +756,6 @@ def testElligator(cls,n): #break else: pass # TODO - - - def gangtest(classes,n): print "Gang test",[cls.__name__ for cls in classes] @@ -747,18 +784,28 @@ 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__ + for i in xrange(n): + r = randombytes(cls.encLen) + cls.elligator(r).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) From 1b7b5099ebf1e7d7472afb4ab400a7461cbf4364 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Mon, 15 Jan 2018 17:52:43 -0800 Subject: [PATCH 2/8] double and encode in ristretto.sage for decaf ed448, not ed25519 --- aux/ristretto/ristretto.sage | 61 +++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/aux/ristretto/ristretto.sage b/aux/ristretto/ristretto.sage index 93127e5..4982936 100644 --- a/aux/ristretto/ristretto.sage +++ b/aux/ristretto/ristretto.sage @@ -504,9 +504,60 @@ class Decaf_1_1_Point(QuotientEdwardsPoint): y = (1-a*s^2) / t return cls(x,sgn*y) + @optimized_version_of("doubleAndEncodeSpec") def doubleAndEncode(self): - # TODO - return self.doubleAndEncodeSpec() + X,Y,Z,T = self.xyzt() + a,d = self.a,self.d + + if self.cofactor == 8: + # TODO: optimized version with no isqrt + e = 2*X*Y + f = Z^2+d*T^2 + g = Y^2-a*X^2 + h = Z^2-d*T^2 + x = e*h + y = f*g + z = f*h + t = e*g + + # 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 + + # OK, the actual libdecaf code should be here + num = (z+y)*(z-y) + den = x*y + isr = isqrt(num*(a-d)*den^2) + + iden = isr * den * self.isoMagic + inum = isr * num + + if negative(iden*inum*self.i*t^2*(d-a)): + iden,inum = inum,iden + fac = x*sqrt(a) + toggle=(a==-1) + else: + fac = y + toggle=False + + imi = self.isoMagic * self.i + if negative(inum*t*imi) != toggle: inum =- inum + + tmp = fac*(inum*z + 1) + s = iden*tmp*imi + + else: + xy = X*Y + h = Z^2-d*T^2 + inv = 1/(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): @@ -787,8 +838,10 @@ def gangtest(classes,n): def testDoubleAndEncode(cls,n): print "Testing doubleAndEncode on %s" % cls.__name__ for i in xrange(n): - r = randombytes(cls.encLen) - cls.elligator(r).doubleAndEncode() + r1 = randombytes(cls.encLen) + r2 = randombytes(cls.encLen) + u = cls.elligator(r1) + cls.elligator(r2) + u.doubleAndEncode() testDoubleAndEncode(Ed25519Point,100) testDoubleAndEncode(NegEd25519Point,100) From b0af873fc881fd8f4c5aef8a9007c3d93d1b5877 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Tue, 16 Jan 2018 00:09:51 -0800 Subject: [PATCH 3/8] double and encode in ristretto.sage for decaf ed25519. kinda sloppy, but good enough for a poc since im not going to implement in c yet anyway --- aux/ristretto/ristretto.sage | 53 ++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/aux/ristretto/ristretto.sage b/aux/ristretto/ristretto.sage index 4982936..04cf4f9 100644 --- a/aux/ristretto/ristretto.sage +++ b/aux/ristretto/ristretto.sage @@ -510,44 +510,37 @@ class Decaf_1_1_Point(QuotientEdwardsPoint): a,d = self.a,self.d if self.cofactor == 8: - # TODO: optimized version with no isqrt - e = 2*X*Y - f = Z^2+d*T^2 - g = Y^2-a*X^2 - h = Z^2-d*T^2 - x = e*h - y = f*g - z = f*h - t = e*g - # Cofactor 8 version # Simulate IMAGINE_TWIST because that's how libdecaf does it - x = self.i*x - t = self.i*t + 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 - # OK, the actual libdecaf code should be here - num = (z+y)*(z-y) - den = x*y - isr = isqrt(num*(a-d)*den^2) - - iden = isr * den * self.isoMagic - inum = isr * num + e = 2*X*Y + f = Y^2+a*X^2 + g = Y^2-a*X^2 + h = Z^2-d*T^2 - if negative(iden*inum*self.i*t^2*(d-a)): - iden,inum = inum,iden - fac = x*sqrt(a) - toggle=(a==-1) - else: - fac = y - toggle=False + eim = e*self.isoMagic + inv = 1/(eim*g*f*h) + fh_inv = eim*g*inv*self.i - imi = self.isoMagic * self.i - if negative(inum*t*imi) != toggle: inum =- inum + 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 - tmp = fac*(inum*z + 1) - s = iden*tmp*imi + if negative(test*fh_inv): bar =- bar + s = idf*(foo+bar)*inv*f*h else: xy = X*Y From ea6c8cdd83f6d95ccaba8cb084e050a89410f78c Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Sun, 21 Jan 2018 16:12:44 -0800 Subject: [PATCH 4/8] add tests for identity and torquing --- aux/ristretto/ristretto.sage | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/aux/ristretto/ristretto.sage b/aux/ristretto/ristretto.sage index 04cf4f9..41b0d22 100644 --- a/aux/ristretto/ristretto.sage +++ b/aux/ristretto/ristretto.sage @@ -218,7 +218,7 @@ class RistrettoPoint(QuotientEdwardsPoint): g = Y^2-a*X^2 h = Z^2-d*T^2 - inv1 = 1/(e*f*g*h) + inv1 = inv0(e*f*g*h) z_inv = inv1*e*g # 1 / (f*h) t_inv = inv1*f*h @@ -236,7 +236,7 @@ class RistrettoPoint(QuotientEdwardsPoint): else: foo = Y^2+a*X^2 bar = X*Y - den = 1/(foo*bar) + 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 @@ -525,7 +525,7 @@ class Decaf_1_1_Point(QuotientEdwardsPoint): h = Z^2-d*T^2 eim = e*self.isoMagic - inv = 1/(eim*g*f*h) + inv = inv0(eim*g*f*h) fh_inv = eim*g*inv*self.i if negative(eim*g*fh_inv): @@ -545,7 +545,7 @@ class Decaf_1_1_Point(QuotientEdwardsPoint): else: xy = X*Y h = Z^2-d*T^2 - inv = 1/(xy*h) + 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 @@ -830,11 +830,18 @@ def gangtest(classes,n): 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) - u.doubleAndEncode() + assert u.doubleAndEncode() == u.torque().doubleAndEncode() testDoubleAndEncode(Ed25519Point,100) testDoubleAndEncode(NegEd25519Point,100) From 3acbdaf999abcb97712efab0f8fa7f0ded3e87e4 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Sun, 4 Feb 2018 18:46:13 -0800 Subject: [PATCH 5/8] fix python2/3 ord issue --- src/generator/curve_data.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/generator/curve_data.py b/src/generator/curve_data.py index 8e7e8d9..f1773be 100644 --- a/src/generator/curve_data.py +++ b/src/generator/curve_data.py @@ -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: From bf609436a05275b1abcfe4b0657825908b48773d Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Mon, 5 Feb 2018 16:06:07 -0800 Subject: [PATCH 6/8] fix sagetest; thanks sofi --- test/test_decaf.sage | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/test/test_decaf.sage b/test/test_decaf.sage index c2e7439..19e0490 100644 --- a/test/test_decaf.sage +++ b/test/test_decaf.sage @@ -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 From ffb134af3aedadcd04dffa13e59d8f4cef3ee928 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Tue, 10 Apr 2018 10:56:07 -0400 Subject: [PATCH 7/8] minor fixes: fix unreachable code, fix an integer used in boolean context, thanks to Sofi Celi --- src/GENERATED/c/curve25519/decaf.c | 2 +- src/GENERATED/c/ed448goldilocks/decaf.c | 2 +- src/GENERATED/include/decaf/point_255.hxx | 2 +- src/GENERATED/include/decaf/point_448.hxx | 2 +- src/per_curve/decaf.tmpl.c | 2 +- src/per_curve/point.tmpl.hxx | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/GENERATED/c/curve25519/decaf.c b/src/GENERATED/c/curve25519/decaf.c index d3ab6ac..48b21cf 100644 --- a/src/GENERATED/c/curve25519/decaf.c +++ b/src/GENERATED/c/curve25519/decaf.c @@ -763,7 +763,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) diff --git a/src/GENERATED/c/ed448goldilocks/decaf.c b/src/GENERATED/c/ed448goldilocks/decaf.c index 2e5bb3f..3952400 100644 --- a/src/GENERATED/c/ed448goldilocks/decaf.c +++ b/src/GENERATED/c/ed448goldilocks/decaf.c @@ -763,7 +763,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) diff --git a/src/GENERATED/include/decaf/point_255.hxx b/src/GENERATED/include/decaf/point_255.hxx index 905a8bc..8915d30 100644 --- a/src/GENERATED/include/decaf/point_255.hxx +++ b/src/GENERATED/include/decaf/point_255.hxx @@ -318,7 +318,7 @@ public: */ inline explicit Point(const FixedBlock &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(); } } diff --git a/src/GENERATED/include/decaf/point_448.hxx b/src/GENERATED/include/decaf/point_448.hxx index a39ca2a..a4a08c5 100644 --- a/src/GENERATED/include/decaf/point_448.hxx +++ b/src/GENERATED/include/decaf/point_448.hxx @@ -318,7 +318,7 @@ public: */ inline explicit Point(const FixedBlock &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(); } } diff --git a/src/per_curve/decaf.tmpl.c b/src/per_curve/decaf.tmpl.c index 9bfe4c0..bfc3843 100644 --- a/src/per_curve/decaf.tmpl.c +++ b/src/per_curve/decaf.tmpl.c @@ -752,7 +752,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) diff --git a/src/per_curve/point.tmpl.hxx b/src/per_curve/point.tmpl.hxx index d481777..2e5c11d 100644 --- a/src/per_curve/point.tmpl.hxx +++ b/src/per_curve/point.tmpl.hxx @@ -305,7 +305,7 @@ public: */ inline explicit Point(const FixedBlock &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(); } } From 15c3f7b7bb37b8339403ee31b02f604fa78f094d Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Thu, 3 May 2018 10:51:56 -0700 Subject: [PATCH 8/8] CC= -> CC?= in Makefile, thanks Timo Gurr --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index bb27775..b19fe3e 100644 --- a/Makefile +++ b/Makefile @@ -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)