|
|
|
@ -40,8 +40,9 @@ namespace crypto
@@ -40,8 +40,9 @@ namespace crypto
|
|
|
|
|
BN_free (u); BN_free (iu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const |
|
|
|
|
bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded) const |
|
|
|
|
{ |
|
|
|
|
bool ret = true; |
|
|
|
|
BN_CTX * ctx = BN_CTX_new (); |
|
|
|
|
BN_CTX_start (ctx); |
|
|
|
|
|
|
|
|
@ -56,6 +57,12 @@ namespace crypto
@@ -56,6 +57,12 @@ namespace crypto
|
|
|
|
|
BIGNUM * xA = BN_CTX_get (ctx); BN_add (xA, x, A); // x + A
|
|
|
|
|
BN_sub (xA, p, xA); // p - (x + A)
|
|
|
|
|
|
|
|
|
|
BIGNUM * uxxA = BN_CTX_get (ctx); // u*x*xA
|
|
|
|
|
BN_mod_mul (uxxA, u, x, p, ctx); |
|
|
|
|
BN_mod_mul (uxxA, uxxA, xA, p, ctx); |
|
|
|
|
|
|
|
|
|
if (Legendre (uxxA, ctx) != -1) |
|
|
|
|
{ |
|
|
|
|
BIGNUM * r = BN_CTX_get (ctx); |
|
|
|
|
BN_mod_inverse (r, xA, p, ctx); |
|
|
|
|
BN_mod_mul (r, r, x, p, ctx); |
|
|
|
@ -70,13 +77,18 @@ namespace crypto
@@ -70,13 +77,18 @@ namespace crypto
|
|
|
|
|
encoded[i] = encoded[15 - i]; |
|
|
|
|
encoded[15 - i] = tmp; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
ret = false; |
|
|
|
|
|
|
|
|
|
BN_CTX_end (ctx); |
|
|
|
|
BN_CTX_free (ctx); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Elligator2::Decode (const uint8_t * encoded, uint8_t * key) const |
|
|
|
|
bool Elligator2::Decode (const uint8_t * encoded, uint8_t * key) const |
|
|
|
|
{ |
|
|
|
|
bool ret = true; |
|
|
|
|
BN_CTX * ctx = BN_CTX_new (); |
|
|
|
|
BN_CTX_start (ctx); |
|
|
|
|
|
|
|
|
@ -89,6 +101,8 @@ namespace crypto
@@ -89,6 +101,8 @@ namespace crypto
|
|
|
|
|
|
|
|
|
|
BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r); |
|
|
|
|
|
|
|
|
|
if (BN_cmp (r, p12) < 0) // r < (p-1)/2
|
|
|
|
|
{ |
|
|
|
|
// v = -A/(1+u*r^2)
|
|
|
|
|
BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx); |
|
|
|
|
BN_mod_mul (v, v, u, p, ctx); |
|
|
|
@ -103,7 +117,7 @@ namespace crypto
@@ -103,7 +117,7 @@ namespace crypto
|
|
|
|
|
BN_mod_mul (t, t, vpA, p, ctx); |
|
|
|
|
BN_mod_add (t, t, v, p, ctx); |
|
|
|
|
|
|
|
|
|
int legendre = 0; // TODO:
|
|
|
|
|
int legendre = Legendre (t, ctx); |
|
|
|
|
BIGNUM * x = BN_CTX_get (ctx); |
|
|
|
|
if (legendre == 1) |
|
|
|
|
BN_copy (x, v); |
|
|
|
@ -120,10 +134,14 @@ namespace crypto
@@ -120,10 +134,14 @@ namespace crypto
|
|
|
|
|
key[i] = key[15 - i]; |
|
|
|
|
key[15 - i] = tmp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
ret = false; |
|
|
|
|
|
|
|
|
|
BN_CTX_end (ctx); |
|
|
|
|
BN_CTX_free (ctx); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Elligator2::SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const |
|
|
|
@ -140,6 +158,18 @@ namespace crypto
@@ -140,6 +158,18 @@ namespace crypto
|
|
|
|
|
BN_sub (r, p, r); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int Elligator2::Legendre (const BIGNUM * a, BN_CTX * ctx) const |
|
|
|
|
{ |
|
|
|
|
// assume a < p, so don't check for a % p = 0
|
|
|
|
|
BIGNUM * r = BN_CTX_get (ctx); |
|
|
|
|
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
|
|
|
|
|
if (BN_is_word(r, 1)) |
|
|
|
|
return 1; |
|
|
|
|
else if (BN_is_zero(r)) |
|
|
|
|
return 0; |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static std::unique_ptr<Elligator2> g_Elligator; |
|
|
|
|
std::unique_ptr<Elligator2>& GetElligator () |
|
|
|
|
{ |
|
|
|
|