Skip to content

Commit

Permalink
Merge pull request #45 from geovandro/master
Browse files Browse the repository at this point in the history
Add online computation when Elligator tables run out of elements.
  • Loading branch information
patricklonga authored May 27, 2021
2 parents 215dfc7 + dab6ceb commit 7ae013c
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 70 deletions.
3 changes: 3 additions & 0 deletions src/P434/P434_compressed.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ const uint64_t u_entang[2*NWORDS64_FIELD] = {
const uint64_t u0_entang[2*NWORDS64_FIELD] = {
0x742C,0x0,0x0,0xB90FF404FC000000,0xD801A4FB559FACD4,0xE93254545F77410C,0xECEEA7BD2EDA,0x742C,0x0,0x0,0xB90FF404FC000000,0xD801A4FB559FACD4,0xE93254545F77410C,0xECEEA7BD2EDA};

// Elligator constant U = min{u0+k} for k=1,2... such that u0+k is a square in F_p^2 for generating 3^n torsion bases
const uint64_t U3[2*NWORDS64_FIELD] = {0xE858,0x0,0x0,0x721FE809F8000000,0xB00349F6AB3F59A9,0xD264A8A8BEEE8219,0x1D9DD4F7A5DB5,0x742C,0x0,0x0,0xB90FF404FC000000,0xD801A4FB559FACD4,0xE93254545F77410C,0xECEEA7BD2EDA};

// Tables for quadratic residues and quadratic non residues v with 17 elements each.

const uint64_t table_r_qr[TABLE_R_LEN][NWORDS64_FIELD] =
Expand Down
5 changes: 5 additions & 0 deletions src/P503/P503_compressed.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ const uint64_t u0_entang[2 * NWORDS64_FIELD] = {
0x3F9,0x0,0x0,0xB400000000000000,0x63CB1A6EA6DED2B4,0x51689D8D667EB37D,0x8ACD77C71AB24142,0x26FBAEC60F5953,0x3F9,0x0,0x0,0xB400000000000000,
0x63CB1A6EA6DED2B4,0x51689D8D667EB37D,0x8ACD77C71AB24142,0x26FBAEC60F5953 };


// Elligator constant U = min{u0+k} for k=1,2... such that u0+k is a square in F_p^2 for generating 3^n torsion bases
const uint64_t U3[2*NWORDS64_FIELD] = {0x7F3,0x0,0x0,0xBC00000000000000,0xB48DD9032BABBDC8,0x87354452517EE94B,0xB55528D05AECDDB4,0xD90684A9D9488,0x3F9,0x0,0x0,0xB400000000000000,0x63CB1A6EA6DED2B4,0x51689D8D667EB37D,0x8ACD77C71AB24142,0x26FBAEC60F5953};


// Tables for quadratic residues and quadratic non residues v with 17 elements each.

const uint64_t table_r_qr[TABLE_R_LEN][NWORDS64_FIELD] =
Expand Down
4 changes: 4 additions & 0 deletions src/P610/P610_compressed.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ const uint64_t u0_entang[2*NWORDS64_FIELD] = {
0x670CC8E6,0x0,0x0,0x0,0x9A34000000000000,0x4D99C2BD28717A3F,0xA4A1839A323D41C,0xD2B62215D06AD1E2,0x1369026E862CAF3D,0x10894E964,0x670CC8E6,0x0,0x0,0x0,0x9A34000000000000,
0x4D99C2BD28717A3F,0xA4A1839A323D41C,0xD2B62215D06AD1E2,0x1369026E862CAF3D,0x10894E964};


// Elligator constant U = min{u0+k} for k=1,2... such that u0+k is a square in F_p^2 for generating 3^n torsion bases
const uint64_t U3[2*NWORDS64_FIELD] = {0x2033FEC80,0x0,0x0,0x0,0x2700000000000000,0x211031E0758202E1,0xFDA2FA9626933136,0xB8E34478F08DCF14,0x5DECEAA3FB0FBB1B,0x32FB4023,0x670CC8E6,0x0,0x0,0x0,0x9A34000000000000,0x4D99C2BD28717A3F,0xA4A1839A323D41C,0xD2B62215D06AD1E2,0x1369026E862CAF3D,0x10894E964};

// Tables for quadratic residues and quadratic non residues v with 17 elements each.

const uint64_t table_r_qr[TABLE_R_LEN][NWORDS64_FIELD] =
Expand Down
5 changes: 5 additions & 0 deletions src/P751/P751_compressed.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ const uint64_t u0_entang[2*NWORDS64_FIELD] = {
0x00000000000249ad, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8310000000000000,
0x5527b1e4375c6c66, 0x697797bf3f4f24d0, 0xc89db7b2ac5c4e2e, 0x4ca4b439d2076956, 0x10f7926c7512c7e9, 0x00002d5b24bce5e2};


// Elligator constant U = min{u0+k} for k=1,2... such that u0+k is a square in F_p^2 for generating 3^n torsion bases
const uint64_t U3[2*NWORDS64_FIELD] = {0x926B5,0x0,0x0,0x0,0x0,0x1D90000000000000,0x70B2310B937938F1,0xCB48C3E2E944C6CA,0x1A284662DA855042,0xAD301BE2EB6B4E13,0x35CBB9123C90433E,0x4586BDB1A06C,0x249AD,0x0,0x0,0x0,0x0,0x8310000000000000,0x5527B1E4375C6C66,0x697797BF3F4F24D0,0xC89DB7B2AC5C4E2E,0x4CA4B439D2076956,0x10F7926C7512C7E9,0x2D5B24BCE5E2};


// Tables for quadratic residues and quadratic non residues v with 17 elements each.

const uint64_t table_r_qr[][NWORDS64_FIELD] =
Expand Down
226 changes: 156 additions & 70 deletions src/compression/torsion_basis.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,33 @@

static void Elligator2(const f2elm_t a24, const unsigned int r, f2elm_t x, unsigned char *bit, const unsigned char COMPorDEC)
{ // Generate an x-coordinate of a point on curve with (affine) coefficient a24
// Use a precomputed Elligator table of size TABLE_V3_LEN and switch to online computations if table runs out of elements.
// Use the counter r
int i;
felm_t one_fp, a2, b2, N, temp0, temp1;
f2elm_t A, y2, *t_ptr;
felm_t one_fp, a2, b2, N, temp0, temp1, rmonty = {0}, *U;
f2elm_t A, y2, *t_ptr, v;

fpcopy((digit_t*)&Montgomery_one, one_fp);
fp2add(a24, a24, A);
fpsub(A[0], one_fp, A[0]);
fp2add(A, A, A); // A = 4*a24-2

// Elligator computation
t_ptr = (f2elm_t *)&v_3_torsion[r];
fp2mul_mont(A, (felm_t*)t_ptr, x); // x = A*v; v := 1/(1 + U*r^2) table lookup
fp2neg(x); // x = -A*v;
fp2add(A, A, A); // A = 4*a24-2

// Elligator computation
if (r < TABLE_V3_LEN) {
t_ptr = (f2elm_t *)&v_3_torsion[r];
fp2copy((felm_t*)t_ptr, v);
} else { // Compute v = 1/(1+U*r^2)
U = (felm_t *)U3;
rmonty[0] = r;
to_mont(rmonty, rmonty);
fpsqr_mont(rmonty, rmonty);
fpmul_mont(U[0], rmonty, v[0]);
fpmul_mont(U[1], rmonty, v[1]);
fpadd(v[0], (digit_t*)&Montgomery_one, v[0]);
fp2inv_mont_bingcd(v); // TODO: check if it is possible to avoid this inversion
}
fp2mul_mont(A, v, x); // x = A*v; v := 1/(1 + U*r^2) table lookup
fp2neg(x); // x = -A*v;

if (COMPorDEC == COMPRESSION) {
fp2add(A, x, y2); // y2 = x + A
Expand Down Expand Up @@ -229,7 +242,7 @@ static void FirstPoint3n(const f2elm_t a24, const f2elm_t As[][5], f2elm_t x, po
bool b = false;
point_proj_t P;
felm_t zero = {0};
*r = 0;
*r = 0;

while (!b) {
*bitEll = 0;
Expand Down Expand Up @@ -363,48 +376,68 @@ static void BuildOrdinary3nBasis_Decomp_dual(const f2elm_t A24, point_proj_t *Rs
}


static void get2mPointonEA(const f2elm_t A, f2elm_t x, felm_t r, f2elm_t t, unsigned char *vqnr, unsigned char *ind)
{// Given a Montgomery curve EA, find a point of order 2^m using precomputed tables of size TABLE_R_LEN and switch to online computations if table runs out of elements.
f2elm_t *tv_ptr, v, tmp;
felm_t *tr_ptr, *u;

static void BuildEntangledXonly(const f2elm_t A, point_proj_t *R, unsigned char *qnr, unsigned char *ind)
{
felm_t s;
f2elm_t *t_ptr, r, t;

// Select the correct table
if (is_sqr_fp2(A, s)) {
t_ptr = (f2elm_t *)table_v_qnr;
*qnr = 1;
u = (felm_t *)u_entang;
// Select the correct tables, i.e., if A is a QR then v must be QNR, and vice-versa
if (is_sqr_fp2(A, tmp[0])) {
tv_ptr = (f2elm_t *)table_v_qnr;
tr_ptr = (felm_t *)table_r_qnr;
*vqnr = 1;
} else {
t_ptr = (f2elm_t *)table_v_qr;
*qnr = 0;
tv_ptr = (f2elm_t *)table_v_qr;
tr_ptr = (felm_t *)table_r_qr;
*vqnr = 0;
}

// Get x0
*ind = 0;
do {
fp2mul_mont(A, (felm_t *)*t_ptr++, R[0]->X); // R[0]->X = A*v
fp2neg(R[0]->X); // R[0]->X = -A*v
fp2add(R[0]->X, A, t);
fp2mul_mont(R[0]->X, t, t);
fpadd(t[0], (digit_t*)Montgomery_one, t[0]);
fp2mul_mont(R[0]->X, t, t); // t = R[0]->X^3 + A*R[0]->X^2 + R[0]->X
*ind += 1;
} while (!is_sqr_fp2(t, s));
if (*ind <= TABLE_R_LEN-1) {
fp2copy((felm_t *)*tv_ptr++, v);
fpcopy(tr_ptr[*ind], r);
} else {
do {
fpadd(r, (digit_t*)Montgomery_one, r);
fpmul_mont(r, r, tmp[1]);
fpmul_mont(u[0], tmp[1], tmp[0]);
fpmul_mont(u[1], tmp[1], tmp[1]);
fpadd(tmp[0], (digit_t*)Montgomery_one, tmp[0]);
fp2inv_mont_bingcd(tmp);
fp2copy(tmp, v); // v = 1/(1 + u*r^2)
*ind += 1; // store the number of attempts for r so that we skip them during decompression
} while (is_sqr_fp2(v, tmp[0]) == *vqnr);
}
fp2mul_mont(A, v, x);
fp2neg(x); // x = -A*v
fp2add(x, A, tmp);
fp2mul_mont(x, tmp, tmp);
fpadd(tmp[0], (digit_t*)Montgomery_one, tmp[0]);
fp2mul_mont(x, tmp, t); // t = x^3 + A*x^2 + x
if (*ind < TABLE_R_LEN)
*ind += 1;
} while (!is_sqr_fp2(t, tmp[0]));
*ind -= 1;
}

if (*qnr)
fpcopy((digit_t*)table_r_qnr[*ind], r[0]);
else
fpcopy((digit_t*)table_r_qr[*ind], r[0]);

// Get x1
static void BuildEntangledXonly(const f2elm_t A, point_proj_t *R, unsigned char *qnr, unsigned char *ind)
{
f2elm_t r, t;

get2mPointonEA(A, R[0]->X, r[0], t, qnr, ind);

// Get x1 = -x-A
fp2add(R[0]->X, A, R[1]->X);
fp2neg(R[1]->X); // R[1]->X = -R[0]->X-A
fp2neg(R[1]->X);

// Get difference x2, z2
fp2sub(R[0]->X, R[1]->X, R[2]->Z);
fp2sqr_mont(R[2]->Z, R[2]->Z);

fpcopy(r[0], r[1]); // (1+i)*ind
fpcopy(r[0], r[1]); // (1+i)*r
fpadd((digit_t*)Montgomery_one, r[0], r[0]);
fp2sqr_mont(r, r);
fp2mul_mont(t, r, R[2]->X);
Expand All @@ -421,6 +454,7 @@ static void BuildOrdinary2nBasis_dual(const f2elm_t A, const f2elm_t Ds[][2], po

// Generate x-only entangled basis
BuildEntangledXonly(A, xs, qnr, ind);

fpcopy((digit_t*)Montgomery_one, (xs[0]->Z)[0]);
fpcopy((digit_t*)Montgomery_one, (xs[1]->Z)[0]);

Expand All @@ -442,42 +476,94 @@ static void BuildOrdinary2nBasis_dual(const f2elm_t A, const f2elm_t Ds[][2], po
}


static void getrvOf2mPoint_Decomp(const f2elm_t A, const unsigned char vqnr, const unsigned char ind, felm_t r, f2elm_t v)
{// Given a Montgomery curve EA, find Elligator values r, v leading to a point of order 2^m.
// Use precomputed tables of size TABLE_R_LEN and switch to online computations if table runs out of elements.
f2elm_t *tv_ptr, tmp;
felm_t *tr_ptr, *u;

static void BuildEntangledXonly_Decomp(const f2elm_t A, point_proj_t *R, unsigned char qnr, unsigned char ind)
{
f2elm_t *t_ptr, r, t;

// Select the correct table
if ( qnr == 1 )
t_ptr = (f2elm_t *)table_v_qnr;
else
t_ptr = (f2elm_t *)table_v_qr;

if (ind >= TABLE_V_LEN/2)
ind = 0;
// Get x0
fp2mul_mont(A, t_ptr[ind], R[0]->X); // x1 = A*v
fp2neg(R[0]->X); // R[0]->X = -A*v
fp2add(R[0]->X, A, t);
fp2mul_mont(R[0]->X, t, t);
fpadd(t[0], (digit_t*)Montgomery_one, t[0]);
fp2mul_mont(R[0]->X, t, t); // t = R[0]->X^3 + A*R[0]->X^2 + R[0]->X

if (qnr == 1)
fpcopy((digit_t*)table_r_qnr[ind], r[0]);
else
fpcopy((digit_t*)table_r_qr[ind], r[0]);
u = (felm_t *)u_entang;
// Select the correct tables
if (vqnr == 1) {
tv_ptr = (f2elm_t *)table_v_qnr;
tr_ptr = (felm_t *)table_r_qnr;
} else {
tv_ptr = (f2elm_t *)table_v_qr;
tr_ptr = (felm_t *)table_r_qr;
}

// Get x1
fp2add(R[0]->X, A, R[1]->X);
fp2neg(R[1]->X); // R[1]->X = -R[0]->X-A
if (ind < TABLE_R_LEN) {
fp2copy(tv_ptr[ind], v);
fpcopy(tr_ptr[ind], r);
} else {
fpcopy(tr_ptr[TABLE_R_LEN-1], r);
for (int k = 0; k < ind - TABLE_R_LEN + 1; k++)
fpadd(r, (digit_t*)Montgomery_one, r);

fpmul_mont(r, r, tmp[1]);
fpmul_mont(u[0], tmp[1], tmp[0]);
fpmul_mont(u[1], tmp[1], v[1]);
fpadd(tmp[0], (digit_t*)Montgomery_one, v[0]); // v^-1 = (1 + u*r^2)
}
}

// Get difference x2,z2
fp2sub(R[0]->X, R[1]->X, R[2]->Z);
fp2sqr_mont(R[2]->Z, R[2]->Z);

fpcopy(r[0],r[1]); // (1+i)*ind
fpadd((digit_t*)Montgomery_one, r[0], r[0]);
fp2sqr_mont(r, r);
fp2mul_mont(t, r, R[2]->X);
static void BuildEntangledXonly_Decomp(const f2elm_t A, point_proj_t *R, unsigned char qnr, unsigned char ind)
{
f2elm_t r, t, v;

getrvOf2mPoint_Decomp(A, qnr, ind, r[0], v);

if (ind < TABLE_R_LEN) {
// Get x0 = -A*v
fp2mul_mont(A, v, R[0]->X);
fp2neg(R[0]->X);
fp2add(R[0]->X, A, t);
fp2mul_mont(R[0]->X, t, t);
fpadd(t[0], (digit_t*)Montgomery_one, t[0]);
fp2mul_mont(R[0]->X, t, t); // t = x0^3 + A*x0^2 + x0

// Get x1 = -x0-A
fp2add(R[0]->X, A, R[1]->X);
fp2neg(R[1]->X);

// Get difference x2,z2
fp2sub(R[0]->X, R[1]->X, R[2]->Z);
fp2sqr_mont(R[2]->Z, R[2]->Z);

fpcopy(r[0],r[1]); // (1+i)*r
fpadd((digit_t*)Montgomery_one, r[0], r[0]);
fp2sqr_mont(r, r);
fp2mul_mont(t, r, R[2]->X);
} else {
// Get X0, Z0
fp2copy(A, R[0]->X);
fp2neg(R[0]->X);
fp2copy(v, R[0]->Z);

// Get X1, Z1
fp2copy(v, R[1]->X);
fp2neg(R[1]->X);
fpadd((digit_t*)Montgomery_one, R[1]->X[0], R[1]->X[0]);
fp2mul_mont(R[1]->X, A, R[1]->X);
fp2copy(v, R[1]->Z);

// Get difference X2,Z2
fpcopy(r[0],r[1]); // (1+i)*r
fpadd((digit_t*)Montgomery_one, r[0], r[0]);
fp2sqr_mont(r, R[2]->X);
fp2copy(v, r);
fpsub(r[0], (digit_t*)Montgomery_one, r[0]);
fp2sqr_mont(A, t);
fp2mul_mont(t, r, r);
fp2sqr_mont(v, t);
fp2sub(r, t, r);
fp2mul_mont(R[2]->X, r, R[2]->X);
fp2mul_mont(A, v, R[2]->Z);
fp2copy(v, r);
fpsub(r[0], (digit_t*)Montgomery_one, r[0]);
fpsub(r[0], (digit_t*)Montgomery_one, r[0]);
fp2sqr_mont(r, r);
fp2mul_mont(R[2]->Z, r, R[2]->Z);
}
}

0 comments on commit 7ae013c

Please sign in to comment.