Browse Source

elligator apparently(?) working for ed448

master
Michael Hamburg 7 years ago
parent
commit
5fc32bf1e9
9 changed files with 315 additions and 205 deletions
  1. +91
    -35
      aux/ristretto/ristretto.sage
  2. +43
    -26
      src/GENERATED/c/curve25519/decaf.c
  3. +31
    -30
      src/GENERATED/c/curve25519/elligator.c
  4. +43
    -26
      src/GENERATED/c/ed448goldilocks/decaf.c
  5. +31
    -30
      src/GENERATED/c/ed448goldilocks/elligator.c
  6. +43
    -26
      src/per_curve/decaf.tmpl.c
  7. +31
    -30
      src/per_curve/elligator.tmpl.c
  8. +1
    -1
      test/ristretto.cxx
  9. +1
    -1
      test/test_decaf.cxx

+ 91
- 35
aux/ristretto/ristretto.sage View File

@@ -305,9 +305,8 @@ class Decaf_1_1_Point(QuotientEdwardsPoint):
return cls(x,y)

@optimized_version_of("encodeSpec")
def encode(self):
"""Encode, optimized version"""
def toJacobiQuartic(self,toggle_rotation=False,toggle_altx=False,toggle_s=False):
"Return s,t on jacobi curve"
a,d = self.a,self.d
x,y,z,t = self.xyzt()
@@ -327,50 +326,88 @@ class Decaf_1_1_Point(QuotientEdwardsPoint):
iden = isr * den * self.isoMagic
inum = isr * num
if negative(iden*inum*self.i*t^2*(d-a)):
if negative(iden*inum*self.i*t^2*(d-a)) != toggle_rotation:
iden,inum = inum,iden
fac = x*sqrt(a)
toggle = (-a==1)
toggle=(a==-1)
else:
fac = y
toggle = False
toggle=False
imi = self.isoMagic * self.i
altx = inum*t*imi
if negative(altx) != toggle: inum =- inum
s = fac*iden*(inum*z + 1)*imi
neg_altx = negative(altx) != toggle_altx
if neg_altx != toggle: inum =- inum
tmp = fac*(inum*z + 1)
s = iden*tmp*imi
# Version without the above IMAGINE_TWIST hack
# num = (z+y)*(z-y)
# den = x*y
# isr = isqrt(num*(a-d)*den^2)
#
# imi = self.isoMagic * self.i
# iden = isr * den * imi
# inum = isr * num
# if isr: assert iden*inum == 1/imi/den
#
# 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
#
# altx = inum*t*self.isoMagic
# if negative(altx) != toggle: inum =- inum
# s = fac*iden*imi*(inum*z - 1)
negm1 = (negative(s) != toggle_s) != neg_altx
if negm1: m1 = a*fac + z
else: m1 = a*fac - z
swap = toggle_s
else:
# Much simpler cofactor 4 version
num = (x+t)*(x-t)
isr = isqrt(num*(a-d)*x^2)
ratio = isr*num
if negative(ratio*self.isoMagic): ratio=-ratio
s = (a-d)*isr*x*(ratio*z - t)
altx = ratio*self.isoMagic
neg_altx = negative(altx) != toggle_altx
if neg_altx: ratio =- ratio
tmp = ratio*z - t
s = (a-d)*isr*x*tmp
negx = (negative(s) != toggle_s) != neg_altx
if negx: m1 = -a*t + x
else: m1 = -a*t - x
swap = toggle_s
if negative(s): s = -s
return self.gfToBytes(s,mustBePositive=True)
return s,m1,a*tmp,swap
def invertElligator(self,toggle_r=False,*args,**kwargs):
"Produce preimage of self under elligator, or None"
a,d = self.a,self.d
rets = []
tr = [False,True] if self.cofactor == 8 else [False]
for toggle_rotation in tr:
for toggle_altx in [False,True]:
for toggle_s in [False,True]:
for toggle_r in [False,True]:
s,m1,m12,swap = self.toJacobiQuartic(toggle_rotation,toggle_altx,toggle_s)
if self == self.__class__():
# Hacks for identity!
if toggle_altx: m12 = 1
elif toggle_s: m1 = 1
elif toggle_r: continue
## BOTH???
rnum = (d*a*m12-m1)
rden = ((d*a-1)*m12+m1)
if swap: rnum,rden = rden,rnum
ok,sr = isqrt_i(rnum*rden*self.qnr)
if not ok: continue
sr *= rnum
if negative(sr) != toggle_r: sr = -sr
ret = self.gfToBytes(sr)
assert self.elligator(ret) == self or self.elligator(ret) == -self
if self.elligator(ret) == -self and self != -self: print "Negated!",[toggle_rotation,toggle_altx,toggle_s,toggle_r]
rets.append(bytes(ret))
return rets

@optimized_version_of("encodeSpec")
def encode(self):
"""Encode, optimized version"""
return self.gfToBytes(self.toJacobiQuartic()[0])
@classmethod
@optimized_version_of("decodeSpec")
@@ -404,9 +441,10 @@ class Decaf_1_1_Point(QuotientEdwardsPoint):
return cls(x,sgn*y)
@classmethod
def elligatorSpec(cls,r0):
def elligatorSpec(cls,r0,fromR=False):
a,d = cls.a,cls.d
r = cls.qnr * cls.bytesToGf(r0)^2
if fromR: r = r0
else: r = cls.qnr * cls.bytesToGf(r0)^2
den = (d*r-(d-a))*((d-a)*r-d)
if den == 0: return cls()
@@ -608,9 +646,27 @@ test(Ed448GoldilocksPoint,100)
def testElligator(cls,n):
print "Testing elligator on %s" % cls.__name__
for i in xrange(n):
cls.elligator(randombytes(cls.encLen))
r = randombytes(cls.encLen)
P = cls.elligator(r)
if hasattr(P,"invertElligator"):
iv = P.invertElligator()
modr = bytes(cls.gfToBytes(cls.bytesToGf(r)))
iv2 = P.torque().invertElligator()
if modr not in iv: print "Failed to invert Elligator!"
if len(iv) != len(set(iv)):
print "Elligator inverses not unique!", len(set(iv)), len(iv)
if iv != iv2:
print "Elligator is untorqueable!"
#print [binascii.hexlify(j) for j in iv]
#print [binascii.hexlify(j) for j in iv2]
#break
else:
pass # TODO

testElligator(Ed25519Point,100)
testElligator(NegEd25519Point,100)
testElligator(IsoEd25519Point,100)
testElligator(IsoEd448Point,100)
testElligator(Ed448GoldilocksPoint,100)
testElligator(TwistedEd448GoldilocksPoint,100)


+ 43
- 26
src/GENERATED/c/curve25519/decaf.c View File

@@ -131,27 +131,30 @@ gf_invert(gf y, const gf x, int assert_nonzero) {
const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};

/* Predeclare because not static: called by elligator */
void API_NS(deisogenize) (
mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_s,
mask_t toggle_altx,
mask_t toggle_rotation
);

void API_NS(deisogenize) (
mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_s,
mask_t toggle_altx,
mask_t toggle_rotation
) {
#if COFACTOR == 4
#if COFACTOR == 4 && !IMAGINE_TWIST
(void)toggle_rotation; /* Only applies to cofactor 8 */
gf t1,t2,t3;
gf t1;
gf_s *t2 = s, *t3=inv_el_sum, *t4=inv_el_m1;
gf_add(t1,p->x,p->t);
gf_sub(t2,p->x,p->t);
@@ -161,20 +164,27 @@ void API_NS(deisogenize) (
gf_mulw(t2,t1,-1-TWISTED_D); /* -x^2 * (a-d) * num */
gf_isr(t1,t2); /* t1 = isr */
gf_mul(t2,t1,t3); /* t2 = ratio */
gf_mul(altx,t2,RISTRETTO_ISOMAGIC);
mask_t negx = gf_lobit(altx) ^ toggle_altx;
gf_mul(t4,t2,RISTRETTO_ISOMAGIC);
mask_t negx = gf_lobit(t4) ^ toggle_altx;
gf_cond_neg(t2, negx);
gf_cond_neg(altx, negx);
gf_mul(t3,t2,p->z);
gf_sub(t3,t3,p->t);
gf_mul(t2,t3,p->x);
gf_mulw(t3,t2,-1-TWISTED_D);
gf_mul(s,t3,t1);
gf_cond_neg(s,gf_lobit(s)^toggle_hibit_s);
gf_mulw(t4,t2,-1-TWISTED_D);
gf_mul(s,t4,t1);
mask_t lobs = gf_lobit(s);
gf_cond_neg(s,lobs);
gf_copy(inv_el_m1,p->x);
gf_cond_neg(inv_el_m1,~lobs^negx^toggle_s);
gf_add(inv_el_m1,inv_el_m1,p->t);
return toggle_s;
#elif COFACTOR == 8 && IMAGINE_TWIST
gf_s *altx = inv_el_sum; // TODO
(void)inv_el_m1;
#elif COFACTOR == 8
/* More complicated because of rotation */
gf t1,t2,t3,t4;
gf t1,t2,t3,t4,t5;
gf_add(t1,p->z,p->y);
gf_sub(t2,p->z,p->y);
gf_mul(t3,t1,t2); /* t3 = num */
@@ -196,27 +206,34 @@ void API_NS(deisogenize) (
mask_t rotate = toggle_rotation ^ gf_lobit(t3);
gf_cond_swap(t1,t2,rotate);
gf_cond_sel(t4,p->y,t4,rotate); /* ix if rotate, else y */
gf_cond_sel(t4,p->y,t4,rotate); /* "fac" = ix if rotate, else y */
gf_mul(t3,t2,t4); /* "fac*iden" */
gf_mul_qnr(t2,RISTRETTO_ISOMAGIC);
gf_mul(t4,t2,t3); /* "fac*iden*imi" */
gf_mul(t3,t2,p->t);
gf_mul(altx,t3,t1);
mask_t negx = rotate ^ gf_lobit(altx) ^ toggle_altx;
gf_cond_neg(altx,negx);
gf_cond_neg(t1,negx);
gf_mul(t5,t2,p->t);
gf_mul(altx,t5,t1);
mask_t negx = gf_lobit(altx) ^ toggle_altx;
gf_cond_neg(t1,negx^rotate);
gf_mul(t2,t1,p->z);
gf_add(t2,t2,ONE);
gf_mul(s,t2,t4);
gf_cond_neg(s,gf_lobit(s)^toggle_hibit_s);
mask_t negs = gf_lobit(s);
gf_cond_neg(s,negs);
mask_t negz = ~negs ^ toggle_s ^ negx;
gf_copy(inv_el_m1,p->z);
gf_cond_neg(inv_el_m1,negz);
gf_sub(inv_el_m1,inv_el_m1,t3);
return toggle_s;
#else
#error "Cofactor must be 4 or 8"
#error "Cofactor must be 4 (with no IMAGINE_TWIST) or 8 (with IMAGINE_TWIST)"
#endif
}

void API_NS(point_encode)( unsigned char ser[SER_BYTES], const point_t p ) {
gf s, mtos;
API_NS(deisogenize)(s,mtos,p,0,0,0);
gf s,ie1,ie2;
(void)API_NS(deisogenize)(s,ie1,ie2,p,0,0,0);
gf_serialize(ser,s,1);
}



+ 31
- 30
src/GENERATED/c/curve25519/elligator.c View File

@@ -23,9 +23,10 @@
static const int EDWARDS_D = -121665;
/* End of template stuff */

extern void API_NS(deisogenize) (
extern mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_altx,
@@ -131,48 +132,48 @@ API_NS(invert_elligator_nonuniform) (
const point_t p,
uint32_t hint_
) {
/* TODO: test that this can produce sqrt((d-a)/ud) etc. */
mask_t hint = hint_;
mask_t sgn_s = -(hint & 1),
sgn_t_over_s = -(hint>>1 & 1),
sgn_altx = -(hint>>1 & 1),
sgn_r0 = -(hint>>2 & 1),
/* FUTURE MAGIC: eventually if there's a curve which needs sgn_ed_T but not sgn_r0,
* change this mask extraction.
*/
sgn_ed_T = -(hint>>3 & 1);
gf a, b, c, d;
API_NS(deisogenize)(a,c,p,sgn_s,sgn_t_over_s,sgn_ed_T);
gf a,b,c;
mask_t swap = API_NS(deisogenize)(a,b,c,p,sgn_s,sgn_altx,sgn_ed_T);
mask_t is_identity = gf_eq(p->t,ZERO);
(void)is_identity;
gf_cond_sel(b,b,ONE,is_identity & sgn_altx);
gf_cond_sel(c,c,ONE,is_identity & sgn_s &~ sgn_altx);
#if IMAGINE_TWIST
gf_mulw(a,b,EDWARDS_D);
gf_sub(b,a,b);
#else
gf_mulw(a,b,EDWARDS_D-1);
gf_add(b,a,b);
#endif
gf_sub(a,a,c);
gf_add(b,b,c);
gf_cond_swap(a,b,swap);
gf_mul_qnr(c,b);
gf_mul(b,c,a);
mask_t succ = gf_isr(c,b);
succ |= gf_eq(b,ZERO);
gf_mul(b,c,a);
#if 255 == 8*SER_BYTES + 1 /* p521. */
sgn_r0 = 0;
#endif
/* ok, a = s; c = -t/s */
gf_mul(b,c,a);
gf_sub(b,ONE,b); /* t+1 */
gf_sqr(c,a); /* s^2 */
mask_t is_identity = gf_eq(p->t,ZERO);

/* identity adjustments */
/* in case of identity, currently c=0, t=0, b=1, will encode to 1 */
/* if hint is 0, -> 0 */
/* if hint is to neg t/s, then go to infinity, effectively set s to 1 */
gf_cond_sel(c,c,ONE,is_identity & sgn_t_over_s);
gf_cond_sel(b,b,ZERO,is_identity & ~sgn_t_over_s & ~sgn_s);
gf_mulw(d,c,2*EDWARDS_D-1); /* $d = (2d-a)s^2 */
gf_add(a,b,d); /* num? */
gf_sub(d,d,b); /* den? */
gf_mul(b,a,d); /* n*d */
gf_cond_sel(a,d,a,sgn_s);
gf_mul_qnr(d,b);
mask_t succ = gf_isr(c,d)|gf_eq(d,ZERO);
gf_mul(b,a,c);
gf_cond_neg(b, sgn_r0^gf_hibit(b));
succ &= ~(gf_eq(b,ZERO) & sgn_r0);
#if COFACTOR == 8
succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
#endif
// #if COFACTOR == 8
// succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
// #endif
#if 255 == 8*SER_BYTES + 1 /* p521 */
gf_serialize(recovered_hash,b,0);


+ 43
- 26
src/GENERATED/c/ed448goldilocks/decaf.c View File

@@ -131,27 +131,30 @@ gf_invert(gf y, const gf x, int assert_nonzero) {
const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};

/* Predeclare because not static: called by elligator */
void API_NS(deisogenize) (
mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_s,
mask_t toggle_altx,
mask_t toggle_rotation
);

void API_NS(deisogenize) (
mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_s,
mask_t toggle_altx,
mask_t toggle_rotation
) {
#if COFACTOR == 4
#if COFACTOR == 4 && !IMAGINE_TWIST
(void)toggle_rotation; /* Only applies to cofactor 8 */
gf t1,t2,t3;
gf t1;
gf_s *t2 = s, *t3=inv_el_sum, *t4=inv_el_m1;
gf_add(t1,p->x,p->t);
gf_sub(t2,p->x,p->t);
@@ -161,20 +164,27 @@ void API_NS(deisogenize) (
gf_mulw(t2,t1,-1-TWISTED_D); /* -x^2 * (a-d) * num */
gf_isr(t1,t2); /* t1 = isr */
gf_mul(t2,t1,t3); /* t2 = ratio */
gf_mul(altx,t2,RISTRETTO_ISOMAGIC);
mask_t negx = gf_lobit(altx) ^ toggle_altx;
gf_mul(t4,t2,RISTRETTO_ISOMAGIC);
mask_t negx = gf_lobit(t4) ^ toggle_altx;
gf_cond_neg(t2, negx);
gf_cond_neg(altx, negx);
gf_mul(t3,t2,p->z);
gf_sub(t3,t3,p->t);
gf_mul(t2,t3,p->x);
gf_mulw(t3,t2,-1-TWISTED_D);
gf_mul(s,t3,t1);
gf_cond_neg(s,gf_lobit(s)^toggle_hibit_s);
gf_mulw(t4,t2,-1-TWISTED_D);
gf_mul(s,t4,t1);
mask_t lobs = gf_lobit(s);
gf_cond_neg(s,lobs);
gf_copy(inv_el_m1,p->x);
gf_cond_neg(inv_el_m1,~lobs^negx^toggle_s);
gf_add(inv_el_m1,inv_el_m1,p->t);
return toggle_s;
#elif COFACTOR == 8 && IMAGINE_TWIST
gf_s *altx = inv_el_sum; // TODO
(void)inv_el_m1;
#elif COFACTOR == 8
/* More complicated because of rotation */
gf t1,t2,t3,t4;
gf t1,t2,t3,t4,t5;
gf_add(t1,p->z,p->y);
gf_sub(t2,p->z,p->y);
gf_mul(t3,t1,t2); /* t3 = num */
@@ -196,27 +206,34 @@ void API_NS(deisogenize) (
mask_t rotate = toggle_rotation ^ gf_lobit(t3);
gf_cond_swap(t1,t2,rotate);
gf_cond_sel(t4,p->y,t4,rotate); /* ix if rotate, else y */
gf_cond_sel(t4,p->y,t4,rotate); /* "fac" = ix if rotate, else y */
gf_mul(t3,t2,t4); /* "fac*iden" */
gf_mul_qnr(t2,RISTRETTO_ISOMAGIC);
gf_mul(t4,t2,t3); /* "fac*iden*imi" */
gf_mul(t3,t2,p->t);
gf_mul(altx,t3,t1);
mask_t negx = rotate ^ gf_lobit(altx) ^ toggle_altx;
gf_cond_neg(altx,negx);
gf_cond_neg(t1,negx);
gf_mul(t5,t2,p->t);
gf_mul(altx,t5,t1);
mask_t negx = gf_lobit(altx) ^ toggle_altx;
gf_cond_neg(t1,negx^rotate);
gf_mul(t2,t1,p->z);
gf_add(t2,t2,ONE);
gf_mul(s,t2,t4);
gf_cond_neg(s,gf_lobit(s)^toggle_hibit_s);
mask_t negs = gf_lobit(s);
gf_cond_neg(s,negs);
mask_t negz = ~negs ^ toggle_s ^ negx;
gf_copy(inv_el_m1,p->z);
gf_cond_neg(inv_el_m1,negz);
gf_sub(inv_el_m1,inv_el_m1,t3);
return toggle_s;
#else
#error "Cofactor must be 4 or 8"
#error "Cofactor must be 4 (with no IMAGINE_TWIST) or 8 (with IMAGINE_TWIST)"
#endif
}

void API_NS(point_encode)( unsigned char ser[SER_BYTES], const point_t p ) {
gf s, mtos;
API_NS(deisogenize)(s,mtos,p,0,0,0);
gf s,ie1,ie2;
(void)API_NS(deisogenize)(s,ie1,ie2,p,0,0,0);
gf_serialize(ser,s,1);
}



+ 31
- 30
src/GENERATED/c/ed448goldilocks/elligator.c View File

@@ -23,9 +23,10 @@
static const int EDWARDS_D = -39081;
/* End of template stuff */

extern void API_NS(deisogenize) (
extern mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_altx,
@@ -131,48 +132,48 @@ API_NS(invert_elligator_nonuniform) (
const point_t p,
uint32_t hint_
) {
/* TODO: test that this can produce sqrt((d-a)/ud) etc. */
mask_t hint = hint_;
mask_t sgn_s = -(hint & 1),
sgn_t_over_s = -(hint>>1 & 1),
sgn_altx = -(hint>>1 & 1),
sgn_r0 = -(hint>>2 & 1),
/* FUTURE MAGIC: eventually if there's a curve which needs sgn_ed_T but not sgn_r0,
* change this mask extraction.
*/
sgn_ed_T = -(hint>>3 & 1);
gf a, b, c, d;
API_NS(deisogenize)(a,c,p,sgn_s,sgn_t_over_s,sgn_ed_T);
gf a,b,c;
mask_t swap = API_NS(deisogenize)(a,b,c,p,sgn_s,sgn_altx,sgn_ed_T);
mask_t is_identity = gf_eq(p->t,ZERO);
(void)is_identity;
gf_cond_sel(b,b,ONE,is_identity & sgn_altx);
gf_cond_sel(c,c,ONE,is_identity & sgn_s &~ sgn_altx);
#if IMAGINE_TWIST
gf_mulw(a,b,EDWARDS_D);
gf_sub(b,a,b);
#else
gf_mulw(a,b,EDWARDS_D-1);
gf_add(b,a,b);
#endif
gf_sub(a,a,c);
gf_add(b,b,c);
gf_cond_swap(a,b,swap);
gf_mul_qnr(c,b);
gf_mul(b,c,a);
mask_t succ = gf_isr(c,b);
succ |= gf_eq(b,ZERO);
gf_mul(b,c,a);
#if 448 == 8*SER_BYTES + 1 /* p521. */
sgn_r0 = 0;
#endif
/* ok, a = s; c = -t/s */
gf_mul(b,c,a);
gf_sub(b,ONE,b); /* t+1 */
gf_sqr(c,a); /* s^2 */
mask_t is_identity = gf_eq(p->t,ZERO);

/* identity adjustments */
/* in case of identity, currently c=0, t=0, b=1, will encode to 1 */
/* if hint is 0, -> 0 */
/* if hint is to neg t/s, then go to infinity, effectively set s to 1 */
gf_cond_sel(c,c,ONE,is_identity & sgn_t_over_s);
gf_cond_sel(b,b,ZERO,is_identity & ~sgn_t_over_s & ~sgn_s);
gf_mulw(d,c,2*EDWARDS_D-1); /* $d = (2d-a)s^2 */
gf_add(a,b,d); /* num? */
gf_sub(d,d,b); /* den? */
gf_mul(b,a,d); /* n*d */
gf_cond_sel(a,d,a,sgn_s);
gf_mul_qnr(d,b);
mask_t succ = gf_isr(c,d)|gf_eq(d,ZERO);
gf_mul(b,a,c);
gf_cond_neg(b, sgn_r0^gf_hibit(b));
succ &= ~(gf_eq(b,ZERO) & sgn_r0);
#if COFACTOR == 8
succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
#endif
// #if COFACTOR == 8
// succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
// #endif
#if 448 == 8*SER_BYTES + 1 /* p521 */
gf_serialize(recovered_hash,b,0);


+ 43
- 26
src/per_curve/decaf.tmpl.c View File

@@ -120,27 +120,30 @@ gf_invert(gf y, const gf x, int assert_nonzero) {
const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}};

/* Predeclare because not static: called by elligator */
void API_NS(deisogenize) (
mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_s,
mask_t toggle_altx,
mask_t toggle_rotation
);

void API_NS(deisogenize) (
mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_s,
mask_t toggle_altx,
mask_t toggle_rotation
) {
#if COFACTOR == 4
#if COFACTOR == 4 && !IMAGINE_TWIST
(void)toggle_rotation; /* Only applies to cofactor 8 */
gf t1,t2,t3;
gf t1;
gf_s *t2 = s, *t3=inv_el_sum, *t4=inv_el_m1;
gf_add(t1,p->x,p->t);
gf_sub(t2,p->x,p->t);
@@ -150,20 +153,27 @@ void API_NS(deisogenize) (
gf_mulw(t2,t1,-1-TWISTED_D); /* -x^2 * (a-d) * num */
gf_isr(t1,t2); /* t1 = isr */
gf_mul(t2,t1,t3); /* t2 = ratio */
gf_mul(altx,t2,RISTRETTO_ISOMAGIC);
mask_t negx = gf_lobit(altx) ^ toggle_altx;
gf_mul(t4,t2,RISTRETTO_ISOMAGIC);
mask_t negx = gf_lobit(t4) ^ toggle_altx;
gf_cond_neg(t2, negx);
gf_cond_neg(altx, negx);
gf_mul(t3,t2,p->z);
gf_sub(t3,t3,p->t);
gf_mul(t2,t3,p->x);
gf_mulw(t3,t2,-1-TWISTED_D);
gf_mul(s,t3,t1);
gf_cond_neg(s,gf_lobit(s)^toggle_hibit_s);
gf_mulw(t4,t2,-1-TWISTED_D);
gf_mul(s,t4,t1);
mask_t lobs = gf_lobit(s);
gf_cond_neg(s,lobs);
gf_copy(inv_el_m1,p->x);
gf_cond_neg(inv_el_m1,~lobs^negx^toggle_s);
gf_add(inv_el_m1,inv_el_m1,p->t);
return toggle_s;
#elif COFACTOR == 8 && IMAGINE_TWIST
gf_s *altx = inv_el_sum; // TODO
(void)inv_el_m1;
#elif COFACTOR == 8
/* More complicated because of rotation */
gf t1,t2,t3,t4;
gf t1,t2,t3,t4,t5;
gf_add(t1,p->z,p->y);
gf_sub(t2,p->z,p->y);
gf_mul(t3,t1,t2); /* t3 = num */
@@ -185,27 +195,34 @@ void API_NS(deisogenize) (
mask_t rotate = toggle_rotation ^ gf_lobit(t3);
gf_cond_swap(t1,t2,rotate);
gf_cond_sel(t4,p->y,t4,rotate); /* ix if rotate, else y */
gf_cond_sel(t4,p->y,t4,rotate); /* "fac" = ix if rotate, else y */
gf_mul(t3,t2,t4); /* "fac*iden" */
gf_mul_qnr(t2,RISTRETTO_ISOMAGIC);
gf_mul(t4,t2,t3); /* "fac*iden*imi" */
gf_mul(t3,t2,p->t);
gf_mul(altx,t3,t1);
mask_t negx = rotate ^ gf_lobit(altx) ^ toggle_altx;
gf_cond_neg(altx,negx);
gf_cond_neg(t1,negx);
gf_mul(t5,t2,p->t);
gf_mul(altx,t5,t1);
mask_t negx = gf_lobit(altx) ^ toggle_altx;
gf_cond_neg(t1,negx^rotate);
gf_mul(t2,t1,p->z);
gf_add(t2,t2,ONE);
gf_mul(s,t2,t4);
gf_cond_neg(s,gf_lobit(s)^toggle_hibit_s);
mask_t negs = gf_lobit(s);
gf_cond_neg(s,negs);
mask_t negz = ~negs ^ toggle_s ^ negx;
gf_copy(inv_el_m1,p->z);
gf_cond_neg(inv_el_m1,negz);
gf_sub(inv_el_m1,inv_el_m1,t3);
return toggle_s;
#else
#error "Cofactor must be 4 or 8"
#error "Cofactor must be 4 (with no IMAGINE_TWIST) or 8 (with IMAGINE_TWIST)"
#endif
}

void API_NS(point_encode)( unsigned char ser[SER_BYTES], const point_t p ) {
gf s, mtos;
API_NS(deisogenize)(s,mtos,p,0,0,0);
gf s,ie1,ie2;
(void)API_NS(deisogenize)(s,ie1,ie2,p,0,0,0);
gf_serialize(ser,s,1);
}



+ 31
- 30
src/per_curve/elligator.tmpl.c View File

@@ -12,9 +12,10 @@
static const int EDWARDS_D = $(d);
/* End of template stuff */

extern void API_NS(deisogenize) (
extern mask_t API_NS(deisogenize) (
gf_s *__restrict__ s,
gf_s *__restrict__ altx,
gf_s *__restrict__ inv_el_sum,
gf_s *__restrict__ inv_el_m1,
const point_t p,
mask_t toggle_hibit_s,
mask_t toggle_altx,
@@ -120,48 +121,48 @@ API_NS(invert_elligator_nonuniform) (
const point_t p,
uint32_t hint_
) {
/* TODO: test that this can produce sqrt((d-a)/ud) etc. */
mask_t hint = hint_;
mask_t sgn_s = -(hint & 1),
sgn_t_over_s = -(hint>>1 & 1),
sgn_altx = -(hint>>1 & 1),
sgn_r0 = -(hint>>2 & 1),
/* FUTURE MAGIC: eventually if there's a curve which needs sgn_ed_T but not sgn_r0,
* change this mask extraction.
*/
sgn_ed_T = -(hint>>3 & 1);
gf a, b, c, d;
API_NS(deisogenize)(a,c,p,sgn_s,sgn_t_over_s,sgn_ed_T);
gf a,b,c;
mask_t swap = API_NS(deisogenize)(a,b,c,p,sgn_s,sgn_altx,sgn_ed_T);
mask_t is_identity = gf_eq(p->t,ZERO);
(void)is_identity;
gf_cond_sel(b,b,ONE,is_identity & sgn_altx);
gf_cond_sel(c,c,ONE,is_identity & sgn_s &~ sgn_altx);
#if IMAGINE_TWIST
gf_mulw(a,b,EDWARDS_D);
gf_sub(b,a,b);
#else
gf_mulw(a,b,EDWARDS_D-1);
gf_add(b,a,b);
#endif
gf_sub(a,a,c);
gf_add(b,b,c);
gf_cond_swap(a,b,swap);
gf_mul_qnr(c,b);
gf_mul(b,c,a);
mask_t succ = gf_isr(c,b);
succ |= gf_eq(b,ZERO);
gf_mul(b,c,a);
#if $(gf_bits) == 8*SER_BYTES + 1 /* p521. */
sgn_r0 = 0;
#endif
/* ok, a = s; c = -t/s */
gf_mul(b,c,a);
gf_sub(b,ONE,b); /* t+1 */
gf_sqr(c,a); /* s^2 */
mask_t is_identity = gf_eq(p->t,ZERO);

/* identity adjustments */
/* in case of identity, currently c=0, t=0, b=1, will encode to 1 */
/* if hint is 0, -> 0 */
/* if hint is to neg t/s, then go to infinity, effectively set s to 1 */
gf_cond_sel(c,c,ONE,is_identity & sgn_t_over_s);
gf_cond_sel(b,b,ZERO,is_identity & ~sgn_t_over_s & ~sgn_s);
gf_mulw(d,c,2*EDWARDS_D-1); /* $d = (2d-a)s^2 */
gf_add(a,b,d); /* num? */
gf_sub(d,d,b); /* den? */
gf_mul(b,a,d); /* n*d */
gf_cond_sel(a,d,a,sgn_s);
gf_mul_qnr(d,b);
mask_t succ = gf_isr(c,d)|gf_eq(d,ZERO);
gf_mul(b,a,c);
gf_cond_neg(b, sgn_r0^gf_hibit(b));
succ &= ~(gf_eq(b,ZERO) & sgn_r0);
#if COFACTOR == 8
succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
#endif
// #if COFACTOR == 8
// succ &= ~(is_identity & sgn_ed_T); /* NB: there are no preimages of rotated identity. */
// #endif
#if $(gf_bits) == 8*SER_BYTES + 1 /* p521 */
gf_serialize(recovered_hash,b,0);


+ 1
- 1
test/ristretto.cxx View File

@@ -75,7 +75,7 @@ void usage() {
fprintf(stderr," Operations:\n");
fprintf(stderr," -n [point]: negative of point\n");
fprintf(stderr," -s [scalar] * [point]: Hash to curve using elligator\n");
fprintf(stderr," [point] + [point]: Add two poitns\n");
fprintf(stderr," [point] + [point]: Add two points\n");
fprintf(stderr,"\n");
fprintf(stderr," NB: this is a debugging widget. It doesn't yet have order of operations.\n");
fprintf(stderr," *** DON'T USE THIS UTILITY FOR ACTUAL CRYPTO! ***\n");


+ 1
- 1
test/test_decaf.cxx View File

@@ -483,7 +483,7 @@ static void test_cfrg_vectors() {
SecureBuffer eddsa_pk2 = priv.pub().serialize();
if (!memeq(SecureBuffer(eddsa_pk[t]), eddsa_pk2)) {
test.fail();
printf(" EdDSA PK vectors disagree.");
printf(" EdDSA PK vectors #%d disagree.", t);
printf("\n Correct: ");
for (unsigned i=0; i<eddsa_pk[t].size(); i++) printf("%02x", eddsa_pk[t][i]);
printf("\n Incorrect: ");


Loading…
Cancel
Save