| 49 | } |
| 50 | |
| 51 | bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const |
| 52 | { |
| 53 | bool ret = true; |
| 54 | BN_CTX * ctx = BN_CTX_new (); |
| 55 | BN_CTX_start (ctx); |
| 56 | |
| 57 | uint8_t key1[32]; |
| 58 | for (size_t i = 0; i < 16; i++) // from Little Endian |
| 59 | { |
| 60 | key1[i] = key[31 - i]; |
| 61 | key1[31 - i] = key[i]; |
| 62 | } |
| 63 | |
| 64 | BIGNUM * x = BN_CTX_get (ctx); BN_bin2bn (key1, 32, x); |
| 65 | BIGNUM * xA = BN_CTX_get (ctx); BN_add (xA, x, A); // x + A |
| 66 | BN_sub (xA, p, xA); // p - (x + A) |
| 67 | |
| 68 | BIGNUM * uxxA = BN_CTX_get (ctx); // u*x*xA |
| 69 | BN_mod_mul (uxxA, u, x, p, ctx); |
| 70 | BN_mod_mul (uxxA, uxxA, xA, p, ctx); |
| 71 | |
| 72 | if (Legendre (uxxA, ctx) != -1) |
| 73 | { |
| 74 | uint8_t randByte = 0; // random highest bits and high y |
| 75 | if (random) |
| 76 | { |
| 77 | RAND_bytes (&randByte, 1); |
| 78 | highY = randByte & 0x01; |
| 79 | } |
| 80 | |
| 81 | BIGNUM * r = BN_CTX_get (ctx); |
| 82 | if (highY) |
| 83 | { |
| 84 | BN_mod_inverse (r, x, p, ctx); |
| 85 | BN_mod_mul (r, r, xA, p, ctx); |
| 86 | } |
| 87 | else |
| 88 | { |
| 89 | BN_mod_inverse (r, xA, p, ctx); |
| 90 | BN_mod_mul (r, r, x, p, ctx); |
| 91 | } |
| 92 | BN_mod_mul (r, r, iu, p, ctx); |
| 93 | |
| 94 | SquareRoot (r, r, ctx); |
| 95 | bn2buf (r, encoded, 32); |
| 96 | |
| 97 | if (random) |
| 98 | encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte |
| 99 | for (size_t i = 0; i < 16; i++) // To Little Endian |
| 100 | { |
| 101 | uint8_t tmp = encoded[i]; |
| 102 | encoded[i] = encoded[31 - i]; |
| 103 | encoded[31 - i] = tmp; |
| 104 | } |
| 105 | } |
| 106 | else |
| 107 | ret = false; |
| 108 | |