@@ -518,9 +518,8 @@ void decaf_255_point_debugging_torque ( | |||
* | |||
* @param [in] hashed_data Output of some hash function. | |||
* @param [out] pt The data hashed to the curve. | |||
* @return A "hint" value which can be used to help invert the encoding. | |||
*/ | |||
uint16_t | |||
void | |||
decaf_255_point_from_hash_nonuniform ( | |||
decaf_255_point_t pt, | |||
const unsigned char hashed_data[DECAF_255_SER_BYTES] | |||
@@ -530,13 +529,11 @@ decaf_255_point_from_hash_nonuniform ( | |||
* @brief Inverse of elligator-like hash to curve. | |||
* | |||
* This function writes to the buffer, to make it so that | |||
* decaf_255_point_from_hash_nonuniform(buffer) = pt,hint | |||
* if possible. | |||
* decaf_255_point_from_hash_nonuniform(buffer) = pt if possible. | |||
* | |||
* @param [out] recovered_hash Encoded data. | |||
* @param [in] pt The point to encode. | |||
* @param [in] hint The hint value returned from | |||
* decaf_255_point_from_hash_nonuniform. | |||
* @param [in] which A "hint" that indicates which inverse to return. | |||
* | |||
* @retval DECAF_SUCCESS The inverse succeeded. | |||
* @retval DECAF_FAILURE The pt isn't the image of | |||
@@ -549,7 +546,7 @@ decaf_bool_t | |||
decaf_255_invert_elligator_nonuniform ( | |||
unsigned char recovered_hash[DECAF_255_SER_BYTES], | |||
const decaf_255_point_t pt, | |||
uint16_t hint | |||
uint16_t which | |||
) API_VIS NONNULL2 NOINLINE WARN_UNUSED; | |||
/** | |||
@@ -557,26 +554,21 @@ decaf_255_invert_elligator_nonuniform ( | |||
* | |||
* This function modifies the first DECAF_255_SER_BYTES of the | |||
* buffer, to make it so that | |||
* decaf_255_point_from_hash_uniform(buffer) = pt,hint | |||
* if possible. | |||
* decaf_255_point_from_hash_uniform(buffer) = pt if possible. | |||
* | |||
* @param [out] recovered_hash Encoded data. | |||
* @param [in] pt The point to encode. | |||
* @param [in] hint The hint value returned from | |||
* decaf_255_point_from_hash_nonuniform. | |||
* @param [in] which A "hint" that indicates which inverse to return. | |||
* | |||
* @retval DECAF_SUCCESS The inverse succeeded. | |||
* @retval DECAF_FAILURE The pt isn't the image of | |||
* decaf_255_point_from_hash_uniform with the given hint. | |||
* | |||
* @warning The hinting system is subject to change, especially in corner cases. | |||
* @warning FIXME The hinting system doesn't work for certain inputs which have many 0xFF. | |||
*/ | |||
decaf_bool_t | |||
decaf_255_invert_elligator_uniform ( | |||
unsigned char recovered_hash[2*DECAF_255_SER_BYTES], | |||
const decaf_255_point_t pt, | |||
uint16_t hint | |||
uint16_t which | |||
) API_VIS NONNULL2 NOINLINE WARN_UNUSED; | |||
/** | |||
@@ -586,9 +578,8 @@ decaf_255_invert_elligator_uniform ( | |||
* | |||
* @param [in] hashed_data Output of some hash function. | |||
* @param [out] pt The data hashed to the curve. | |||
* @return A "hint" value which can be used to help invert the encoding. | |||
*/ | |||
uint16_t decaf_255_point_from_hash_uniform ( | |||
void decaf_255_point_from_hash_uniform ( | |||
decaf_255_point_t pt, | |||
const unsigned char hashed_data[2*DECAF_255_SER_BYTES] | |||
) API_VIS NONNULL2 NOINLINE; | |||
@@ -491,19 +491,19 @@ public: | |||
* If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, | |||
* but the buffer will be zero-padded on the right. | |||
*/ | |||
inline unsigned char set_to_hash( const Block &s ) NOEXCEPT { | |||
inline void set_to_hash( const Block &s ) NOEXCEPT { | |||
if (s.size() < HASH_BYTES) { | |||
SecureBuffer b(HASH_BYTES); | |||
memcpy(b.data(), s.data(), s.size()); | |||
return decaf_255_point_from_hash_nonuniform(p,b); | |||
decaf_255_point_from_hash_nonuniform(p,b); | |||
} else if (s.size() == HASH_BYTES) { | |||
return decaf_255_point_from_hash_nonuniform(p,s); | |||
decaf_255_point_from_hash_nonuniform(p,s); | |||
} else if (s.size() < 2*HASH_BYTES) { | |||
SecureBuffer b(2*HASH_BYTES); | |||
memcpy(b.data(), s.data(), s.size()); | |||
return decaf_255_point_from_hash_uniform(p,b); | |||
decaf_255_point_from_hash_uniform(p,b); | |||
} else { | |||
return decaf_255_point_from_hash_uniform(p,s); | |||
decaf_255_point_from_hash_uniform(p,s); | |||
} | |||
} | |||
@@ -493,9 +493,11 @@ static void deisogenize ( | |||
gf_sub ( x, ZERO, x ); | |||
gf_sub ( t, ZERO, t ); | |||
gf DEBUG; | |||
gf_add ( a, p->z, x ); | |||
gf_sub ( b, p->z, x ); | |||
gf_mul ( c, a, b ); /* "zx" = Z^2 - X^2 */ | |||
gf_cpy(DEBUG,c); | |||
gf_mul ( a, p->z, t ); /* "tz" = T*Z */ | |||
gf_sqr ( b, a ); | |||
gf_mul ( d, b, c ); /* (TZ)^2 * (Z^2-X^2) */ | |||
@@ -1082,13 +1084,13 @@ decaf_bool_t API_NS(point_eq) ( const point_t p, const point_t q ) { | |||
return succ; | |||
} | |||
uint16_t API_NS(point_from_hash_nonuniform) ( | |||
void API_NS(point_from_hash_nonuniform) ( | |||
point_t p, | |||
const unsigned char ser[SER_BYTES] | |||
) { | |||
// TODO: simplify since we don't return a hint anymore | |||
gf r0,r,a,b,c,dee,D,N,rN,e; | |||
decaf_bool_t over = ~gf_deser(r0,ser); | |||
decaf_bool_t sgn_r0 = hibit(r0); | |||
gf_deser(r0,ser); | |||
gf_canon(r0); | |||
gf_sqr(a,r0); | |||
//gf_sub(r,ZERO,a); /*gf_mlw(r,a,QUADRATIC_NONRESIDUE);*/ | |||
@@ -1143,9 +1145,6 @@ uint16_t API_NS(point_from_hash_nonuniform) ( | |||
/* Normalize/negate */ | |||
decaf_bool_t neg_s = hibit(a)^~square; | |||
cond_neg(a,neg_s); /* ends up negative if ~square */ | |||
decaf_bool_t sgn_t_over_s = hibit(b)^neg_s; | |||
sgn_t_over_s &= ~gf_eq(N,ZERO); | |||
sgn_t_over_s |= gf_eq(D,ZERO); | |||
/* b <- t */ | |||
cond_sel(b,c,ONE,gf_eq(c,ZERO)); /* 0,0 -> 1,0 */ | |||
@@ -1164,8 +1163,6 @@ uint16_t API_NS(point_from_hash_nonuniform) ( | |||
gf_mul(p->z,a,b); /* (1-s^2)t */ | |||
assert(API_NS(point_valid)(p)); | |||
return (~square & 1) | (sgn_t_over_s & 2) | (sgn_r0 & 4) | (over & 16); | |||
} | |||
decaf_bool_t | |||
@@ -1212,17 +1209,14 @@ API_NS(invert_elligator_nonuniform) ( | |||
return succ; | |||
} | |||
uint16_t API_NS(point_from_hash_uniform) ( | |||
void API_NS(point_from_hash_uniform) ( | |||
point_t pt, | |||
const unsigned char hashed_data[2*SER_BYTES] | |||
) { | |||
point_t pt2; | |||
unsigned char ret1 = | |||
API_NS(point_from_hash_nonuniform)(pt,hashed_data); | |||
unsigned char ret2 = | |||
API_NS(point_from_hash_nonuniform)(pt2,&hashed_data[SER_BYTES]); | |||
API_NS(point_from_hash_nonuniform)(pt,hashed_data); | |||
API_NS(point_from_hash_nonuniform)(pt2,&hashed_data[SER_BYTES]); | |||
API_NS(point_add)(pt,pt,pt2); | |||
return ret1 | ((uint16_t)ret2<<8); | |||
} | |||
decaf_bool_t | |||
@@ -164,30 +164,12 @@ static void test_elligator() { | |||
decaf::SpongeRng rng(decaf::Block("test_elligator")); | |||
Test test("Elligator"); | |||
/* | |||
for (int i=0; i<32; i++) { | |||
decaf::SecureBuffer b1(Point::HASH_BYTES); | |||
Point p = Point::identity(); | |||
for (int j=0; j<i/8; j++) p.debugging_torque_in_place(); | |||
bool succ = p.invert_elligator(b1,i&7); | |||
Point q; | |||
unsigned char hint = q.set_to_hash(b1); | |||
if (succ != ((i&7) != 4) || (q != p) || (succ && (hint != (i&7)))) { | |||
test.fail(); | |||
printf("Elligator test: t=%d, h=%d->%d, q%sp, %s %02x%02x\n", | |||
i/8, i&7, hint, (q==p)?"==":"!=",succ ? "SUCC" : "FAIL", | |||
b1[0], b1[1]); | |||
} | |||
} | |||
*/ | |||
const int NHINTS = 1<<4; | |||
decaf::SecureBuffer *alts[NHINTS]; | |||
bool successes[NHINTS]; | |||
for (int i=0; i<NTESTS && (test.passing_now || i < 100); i++) { | |||
size_t len = 8 + (i % (2*Point::HASH_BYTES + 3)); // FIXME: 0 | |||
size_t len = (i % (2*Point::HASH_BYTES + 3)); // FIXME: 0 | |||
decaf::SecureBuffer b1(len); | |||
rng.read(b1); | |||
if (i==1) b1[0] = 1; /* special case test */ | |||