@@ -67,24 +67,30 @@ def decaf_encode_from_E_c(X,Y): | |||||
# Precompute | # Precompute | ||||
sd = sqrt(F(1-d)) | sd = sqrt(F(1-d)) | ||||
zx = Z^2-X^2 | |||||
TZ = T*Z | |||||
# comments in case of identity point | |||||
# (1,0) or (0,1) | |||||
zx = Z^2-X^2 # 0^2 or 1 * Z^2 | |||||
TZ = T*Z # 0 * Z^2 | |||||
assert zx.is_square | assert zx.is_square | ||||
ooAll = isqrt(zx*TZ^2) | |||||
osx = ooAll * TZ | |||||
ooTZ = ooAll * zx * osx | |||||
ooAll = isqrt(zx*TZ^2) # inf^2 or inf * 1/Z^3 | |||||
osx = ooAll * TZ # inf or 1 * 1/Z | |||||
ooTZ = ooAll * zx * osx # inf * 1/Z^2 | |||||
floop = qpositive(T^2 * ooTZ) or doPinkBikeShed | |||||
floop = qpositive(T^2 * ooTZ) or doPinkBikeShed # 0 | |||||
if floop: | if floop: | ||||
frob = zx * ooTZ | |||||
frob = zx * ooTZ # 0 or inf | |||||
# Y = 0 or 1 | |||||
else: | else: | ||||
frob = sd | |||||
Y = -X | |||||
frob = sd # sd | |||||
Y = -X # -1 or 0 * Z | |||||
osx *= frob | |||||
osx *= frob # 1 or inf * 1/Z || inf sd or sd * 1/Z | |||||
# y * osx = 0 or inf or -inf sd or 0 sd | |||||
# y * ootz * z = 1 or inf or inf sd or 0^2 sd | |||||
# s = 0 or 1 or inf sd or | |||||
if qpositive(-2*osx*Z) != floop: osx = -osx | if qpositive(-2*osx*Z) != floop: osx = -osx | ||||
s = Y*(ooTZ*Z + osx) | |||||
s = Y*(ooTZ*Z + osx) # | |||||
if not qpositive(s): s = -s | if not qpositive(s): s = -s | ||||
return s | return s | ||||
@@ -1183,13 +1183,14 @@ API_NS(invert_elligator_nonuniform) ( | |||||
gf_mul(b,c,a); | gf_mul(b,c,a); | ||||
gf_sub(b,ONE,b); /* t+1 */ | gf_sub(b,ONE,b); /* t+1 */ | ||||
gf_sqr(c,a); /* s^2 */ | gf_sqr(c,a); /* s^2 */ | ||||
decaf_bool_t is_identity = gf_eq(p->t,ZERO); | |||||
{ /* identity adjustments */ | { /* identity adjustments */ | ||||
/* in case of identity, currently c=0, t=0, b=1, will encode to 1 */ | /* in case of identity, currently c=0, t=0, b=1, will encode to 1 */ | ||||
/* if hint is 0, -> 0 */ | /* if hint is 0, -> 0 */ | ||||
/* if hint is to neg t/s, then go to infinity, effectively set s to 1 */ | /* if hint is to neg t/s, then go to infinity, effectively set s to 1 */ | ||||
decaf_bool_t is_identity = gf_eq(p->x,ZERO); | |||||
cond_sel(c,c,ONE,is_identity & sgn_t_over_s); | cond_sel(c,c,ONE,is_identity & sgn_t_over_s); | ||||
cond_sel(b,b,ZERO,is_identity & ~sgn_t_over_s & ~sgn_s); /* identity adjust */ | cond_sel(b,b,ZERO,is_identity & ~sgn_t_over_s & ~sgn_s); /* identity adjust */ | ||||
//cond_neg(b,is_identity & sgn_ed_T); | |||||
} | } | ||||
gf_mlw(d,c,2*EDWARDS_D-1); /* $d = (2d-a)s^2 */ | gf_mlw(d,c,2*EDWARDS_D-1); /* $d = (2d-a)s^2 */ | ||||
@@ -1203,6 +1204,7 @@ API_NS(invert_elligator_nonuniform) ( | |||||
cond_neg(b, sgn_r0^hibit(b)); | cond_neg(b, sgn_r0^hibit(b)); | ||||
succ &= ~(gf_eq(b,ZERO) & sgn_r0); | succ &= ~(gf_eq(b,ZERO) & sgn_r0); | ||||
succ &= ~(is_identity & sgn_ed_T); /* FIXME: preimages of rotation */ | |||||
gf_encode(recovered_hash, b); | gf_encode(recovered_hash, b); | ||||
/* TODO: deal with overflow flag */ | /* TODO: deal with overflow flag */ | ||||
@@ -168,10 +168,10 @@ static void test_elligator() { | |||||
decaf::SecureBuffer *alts[NHINTS]; | decaf::SecureBuffer *alts[NHINTS]; | ||||
bool successes[NHINTS]; | bool successes[NHINTS]; | ||||
for (int i=0; i<NTESTS && (test.passing_now || i < 100); i++) { | |||||
for (int i=0; i<NTESTS/10 && (test.passing_now || i < 100); i++) { | |||||
size_t len = (i % (2*Point::HASH_BYTES + 3)); // FIXME: 0 | size_t len = (i % (2*Point::HASH_BYTES + 3)); // FIXME: 0 | ||||
decaf::SecureBuffer b1(len); | decaf::SecureBuffer b1(len); | ||||
rng.read(b1); | |||||
if (i!=Point::HASH_BYTES) rng.read(b1); /* special test case */ | |||||
if (i==1) b1[0] = 1; /* special case test */ | if (i==1) b1[0] = 1; /* special case test */ | ||||
if (len >= Point::HASH_BYTES) b1[Point::HASH_BYTES-1] &= 0x7F; // FIXME MAGIC | if (len >= Point::HASH_BYTES) b1[Point::HASH_BYTES-1] &= 0x7F; // FIXME MAGIC | ||||
Point s = Point::from_hash(b1); | Point s = Point::from_hash(b1); | ||||
@@ -203,6 +203,12 @@ static void test_elligator() { | |||||
hexprint("x",b1); | hexprint("x",b1); | ||||
hexprint("X",*alts[j]); | hexprint("X",*alts[j]); | ||||
} | } | ||||
/* | |||||
if (i == Point::HASH_BYTES) { | |||||
printf("Identity, hint = %d\n", j); | |||||
hexprint("einv(0)",*alts[j]); | |||||
} | |||||
*/ | |||||
} | } | ||||
} | } | ||||