Files
sqisign/src/ec/ref/ecx/basis.c
SQIsign team 28ff420dd0 initial version of SQIsign
Co-authored-by: Jorge Chavez-Saab <jorgechavezsaab@gmail.com>
Co-authored-by: Maria Corte-Real Santos <36373796+mariascrs@users.noreply.github.com>
Co-authored-by: Luca De Feo <github@defeo.lu>
Co-authored-by: Jonathan Komada Eriksen <jonathan.eriksen97@gmail.com>
Co-authored-by: Basil Hess <bhe@zurich.ibm.com>
Co-authored-by: Antonin Leroux <18654258+tonioecto@users.noreply.github.com>
Co-authored-by: Patrick Longa <plonga@microsoft.com>
Co-authored-by: Lorenz Panny <lorenz@yx7.cc>
Co-authored-by: Francisco Rodríguez-Henríquez <francisco.rodriguez@tii.ae>
Co-authored-by: Sina Schaeffler <108983332+syndrakon@users.noreply.github.com>
Co-authored-by: Benjamin Wesolowski <19474926+Calodeon@users.noreply.github.com>
2023-07-09 12:48:54 +02:00

509 lines
14 KiB
C

#include "isog.h"
static void xTPL(ec_point_t* Q, const ec_point_t* P, const ec_point_t* A3)
{
/* ----------------------------------------------------------------------------- *
* Differential point tripling given the montgomery coefficient A3 = (A+2C:A-2C)
* ----------------------------------------------------------------------------- */
fp2_t t0, t1, t2, t3, t4;
fp2_sub(&t0, &P->x, &P->z);
fp2_sqr(&t2, &t0);
fp2_add(&t1, &P->x, &P->z);
fp2_sqr(&t3, &t1);
fp2_add(&t4, &t1, &t0);
fp2_sub(&t0, &t1, &t0);
fp2_sqr(&t1, &t4);
fp2_sub(&t1, &t1, &t3);
fp2_sub(&t1, &t1, &t2);
fp2_mul(&Q->x, &t3, &A3->x);
fp2_mul(&t3, &Q->x, &t3);
fp2_mul(&Q->z, &t2, &A3->z);
fp2_mul(&t2, &t2, &Q->z);
fp2_sub(&t3, &t2, &t3);
fp2_sub(&t2, &Q->x, &Q->z);
fp2_mul(&t1, &t2, &t1);
fp2_add(&t2, &t3, &t1);
fp2_sqr(&t2, &t2);
fp2_mul(&Q->x, &t2, &t4);
fp2_sub(&t1, &t3, &t1);
fp2_sqr(&t1, &t1);
fp2_mul(&Q->z, &t1, &t0);
}
int ec_is_on_curve(const ec_curve_t* curve, const ec_point_t* P){
fp2_t t0, t1, t2;
// Check if xz*(C^2x^2+zACx+z^2C^2) is a square
fp2_mul(&t0, &curve->C, &P->x);
fp2_mul(&t1, &t0, &P->z);
fp2_mul(&t1, &t1, &curve->A);
fp2_mul(&t2, &curve->C, &P->z);
fp2_sqr(&t0, &t0);
fp2_sqr(&t2, &t2);
fp2_add(&t0, &t0, &t1);
fp2_add(&t0, &t0, &t2);
fp2_mul(&t0, &t0, &P->x);
fp2_mul(&t0, &t0, &P->z);
return fp2_is_square(&t0);
}
static void difference_point(ec_point_t* PQ, const ec_point_t* P, const ec_point_t* Q, const ec_curve_t* curve){
// Given P,Q in affine x-only, computes a deterministic choice for (P-Q)
// The points must be normalized to z=1 and the curve to C=1
fp2_t t0, t1, t2, t3;
fp2_sub(&PQ->z, &P->x, &Q->x); // P - Q
fp2_mul(&t2, &P->x, &Q->x); // P*Q
fp_mont_setone(t1.re);
fp_set(t1.im, 0);
fp2_sub(&t3, &t2, &t1); // P*Q-1
fp2_mul(&t0, &PQ->z, &t3); // (P-Q)*(P*Q-1)
fp2_sqr(&PQ->z, &PQ->z); // (P-Q)^2
fp2_sqr(&t0, &t0); // (P-Q)^2*(P*Q-1)^2
fp2_add(&t1, &t2, &t1); // P*Q+1
fp2_add(&t3, &P->x, &Q->x); // P+Q
fp2_mul(&t1, &t1, &t3); // (P+Q)*(P*Q+1)
fp2_mul(&t2, &t2, &curve->A); // A*P*Q
fp2_add(&t2, &t2, &t2); // 2*A*P*Q
fp2_add(&t1, &t1, &t2); // (P+Q)*(P*Q+1) + 2*A*P*Q
fp2_sqr(&t2, &t1); // ((P+Q)*(P*Q+1) + 2*A*P*Q)^2
fp2_sub(&t0, &t2, &t0); // ((P+Q)*(P*Q+1) + 2*A*P*Q)^2 - (P-Q)^2*(P*Q-1)^2
fp2_sqrt(&t0);
fp2_add(&PQ->x, &t0, &t1);
}
void ec_curve_to_basis_2(ec_basis_t *PQ2, const ec_curve_t *curve){
fp2_t x, t0, t1, t2;
ec_point_t P, Q, Q2, P2, A24;
// Curve coefficient in the form A24 = (A+2C:4C)
fp2_add(&A24.z, &curve->C, &curve->C);
fp2_add(&A24.x, &curve->A, &A24.z);
fp2_add(&A24.z, &A24.z, &A24.z);
fp_mont_setone(x.re);
fp_set(x.im, 0);
// Find P
while(1){
fp_add(x.im, x.re, x.im);
// Check if point is rational
fp2_sqr(&t0, &curve->C);
fp2_mul(&t1, &t0, &x);
fp2_mul(&t2, &curve->A, &curve->C);
fp2_add(&t1, &t1, &t2);
fp2_mul(&t1, &t1, &x);
fp2_add(&t1, &t1, &t0);
fp2_mul(&t1, &t1, &x);
if(fp2_is_square(&t1)){
fp2_copy(&P.x, &x);
fp_mont_setone(P.z.re);
fp_set(P.z.im, 0);
}
else
continue;
// Clear odd factors from the order
xMULv2(&P, &P, p_cofactor_for_2f, P_COFACTOR_FOR_2F_BITLENGTH, &A24);
// Check if point has order 2^f
copy_point(&P2, &P);
for(int i = 0; i < POWER_OF_2 - 1; i++)
xDBLv2(&P2, &P2, &A24);
if(ec_is_zero(&P2))
continue;
else
break;
}
// Find Q
while(1){
fp_add(x.im, x.re, x.im);
// Check if point is rational
fp2_sqr(&t0, &curve->C);
fp2_mul(&t1, &t0, &x);
fp2_mul(&t2, &curve->A, &curve->C);
fp2_add(&t1, &t1, &t2);
fp2_mul(&t1, &t1, &x);
fp2_add(&t1, &t1, &t0);
fp2_mul(&t1, &t1, &x);
if(fp2_is_square(&t1)){
fp2_copy(&Q.x, &x);
fp_mont_setone(Q.z.re);
fp_set(Q.z.im, 0);
}
else
continue;
// Clear odd factors from the order
xMULv2(&Q, &Q, p_cofactor_for_2f, P_COFACTOR_FOR_2F_BITLENGTH, &A24);
// Check if point has order 2^f
copy_point(&Q2, &Q);
for(int i = 0; i < POWER_OF_2 - 1; i++)
xDBLv2(&Q2, &Q2, &A24);
if(ec_is_zero(&Q2))
continue;
// Check if point is orthogonal to P
if(is_point_equal(&P2, &Q2))
continue;
else
break;
}
// Normalize points
ec_curve_t E;
fp2_mul(&t0, &P.z, &Q.z);
fp2_mul(&t1, &t0, &curve->C);
fp2_inv(&t1);
fp2_mul(&P.x, &P.x, &t1);
fp2_mul(&Q.x, &Q.x, &t1);
fp2_mul(&E.A, &curve->A, &t1);
fp2_mul(&P.x, &P.x, &Q.z);
fp2_mul(&P.x, &P.x, &curve->C);
fp2_mul(&Q.x, &Q.x, &P.z);
fp2_mul(&Q.x, &Q.x, &curve->C);
fp2_mul(&E.A, &E.A, &t0);
fp_mont_setone(P.z.re);
fp_set(P.z.im, 0);
fp2_copy(&Q.z, &P.z);
fp2_copy(&E.C, &P.z);
// Compute P-Q
difference_point(&PQ2->PmQ, &P, &Q, &E);
copy_point(&PQ2->P, &P);
copy_point(&PQ2->Q, &Q);
}
void ec_complete_basis_2(ec_basis_t* PQ2, const ec_curve_t* curve, const ec_point_t* P){
fp2_t x, t0, t1, t2;
ec_point_t Q, Q2, P2, A24;
// Curve coefficient in the form A24 = (A+2C:4C)
fp2_add(&A24.z, &curve->C, &curve->C);
fp2_add(&A24.x, &curve->A, &A24.z);
fp2_add(&A24.z, &A24.z, &A24.z);
// Point of order 2 generated by P
copy_point(&P2, P);
for(int i = 0; i < POWER_OF_2 - 1; i++)
xDBLv2(&P2, &P2, &A24);
// Find Q
fp_mont_setone(x.re);
fp_set(x.im, 0);
while(1){
fp_add(x.im, x.re, x.im);
// Check if point is rational
fp2_sqr(&t0, &curve->C);
fp2_mul(&t1, &t0, &x);
fp2_mul(&t2, &curve->A, &curve->C);
fp2_add(&t1, &t1, &t2);
fp2_mul(&t1, &t1, &x);
fp2_add(&t1, &t1, &t0);
fp2_mul(&t1, &t1, &x);
if(fp2_is_square(&t1)){
fp2_copy(&Q.x, &x);
fp_mont_setone(Q.z.re);
fp_set(Q.z.im, 0);
}
else
continue;
// Clear odd factors from the order
xMULv2(&Q, &Q, p_cofactor_for_2f, (int)P_COFACTOR_FOR_2F_BITLENGTH, &A24);
// Check if point has order 2^f
copy_point(&Q2, &Q);
for(int i = 0; i < POWER_OF_2 - 1; i++)
xDBLv2(&Q2, &Q2, &A24);
if(ec_is_zero(&Q2))
continue;
// Check if point is orthogonal to P
if(is_point_equal(&P2, &Q2))
continue;
else
break;
}
// Normalize points
ec_curve_t E;
ec_point_t PP;
fp2_mul(&t0, &P->z, &Q.z);
fp2_mul(&t1, &t0, &curve->C);
fp2_inv(&t1);
fp2_mul(&PP.x, &P->x, &t1);
fp2_mul(&Q.x, &Q.x, &t1);
fp2_mul(&E.A, &curve->A, &t1);
fp2_mul(&PP.x, &PP.x, &Q.z);
fp2_mul(&PP.x, &PP.x, &curve->C);
fp2_mul(&Q.x, &Q.x, &P->z);
fp2_mul(&Q.x, &Q.x, &curve->C);
fp2_mul(&E.A, &E.A, &t0);
fp_mont_setone(PP.z.re);
fp_set(PP.z.im, 0);
fp2_copy(&Q.z, &PP.z);
fp2_copy(&E.C, &PP.z);
// Compute P-Q
difference_point(&PQ2->PmQ, &PP, &Q, &E);
copy_point(&PQ2->P, &PP);
copy_point(&PQ2->Q, &Q);
}
void ec_curve_to_basis_3(ec_basis_t* PQ3, const ec_curve_t* curve){
fp2_t x, t0, t1, t2;
ec_point_t P, Q, Q3, P3, A24, A3;
// Curve coefficient in the form A24 = (A+2C:4C)
fp2_add(&A24.z, &curve->C, &curve->C);
fp2_add(&A24.x, &curve->A, &A24.z);
fp2_add(&A24.z, &A24.z, &A24.z);
// Curve coefficient in the form A3 = (A+2C:A-2C)
fp2_sub(&A3.z, &A24.x, &A24.z);
fp2_copy(&A3.x, &A24.x);
fp_mont_setone(x.re);
fp_set(x.im, 0);
// Find P
while(1){
fp_add(x.im, x.re, x.im);
// Check if point is rational
fp2_sqr(&t0, &curve->C);
fp2_mul(&t1, &t0, &x);
fp2_mul(&t2, &curve->A, &curve->C);
fp2_add(&t1, &t1, &t2);
fp2_mul(&t1, &t1, &x);
fp2_add(&t1, &t1, &t0);
fp2_mul(&t1, &t1, &x);
if(fp2_is_square(&t1)){
fp2_copy(&P.x, &x);
fp_mont_setone(P.z.re);
fp_set(P.z.im, 0);
}
else
continue;
// Clear non-3 factors from the order
xMULv2(&P, &P, p_cofactor_for_3g, (int)P_COFACTOR_FOR_3G_BITLENGTH, &A24);
// Check if point has order 3^g
copy_point(&P3, &P);
for(int i = 0; i < POWER_OF_3 - 1; i++)
xTPL(&P3, &P3, &A3);
if(ec_is_zero(&P3))
continue;
else
break;
}
// Find Q
while(1){
fp_add(x.im, x.re, x.im);
// Check if point is rational
fp2_sqr(&t0, &curve->C);
fp2_mul(&t1, &t0, &x);
fp2_mul(&t2, &curve->A, &curve->C);
fp2_add(&t1, &t1, &t2);
fp2_mul(&t1, &t1, &x);
fp2_add(&t1, &t1, &t0);
fp2_mul(&t1, &t1, &x);
if(fp2_is_square(&t1)){
fp2_copy(&Q.x, &x);
fp_mont_setone(Q.z.re);
fp_set(Q.z.im, 0);
}
else
continue;
// Clear non-3 factors from the order
xMULv2(&Q, &Q, p_cofactor_for_3g, (int)P_COFACTOR_FOR_3G_BITLENGTH, &A24);
// Check if point has order 3^g
copy_point(&Q3, &Q);
for(int i = 0; i < POWER_OF_3 - 1; i++)
xTPL(&Q3, &Q3, &A3);
if(ec_is_zero(&Q3))
continue;
// Check if point is orthogonal to P
if(is_point_equal(&P3, &Q3))
continue;
xDBLv2(&P3, &P3, &A24);
if(is_point_equal(&P3, &Q3))
continue;
else
break;
}
// Normalize points
ec_curve_t E;
fp2_mul(&t0, &P.z, &Q.z);
fp2_mul(&t1, &t0, &curve->C);
fp2_inv(&t1);
fp2_mul(&P.x, &P.x, &t1);
fp2_mul(&Q.x, &Q.x, &t1);
fp2_mul(&E.A, &curve->A, &t1);
fp2_mul(&P.x, &P.x, &Q.z);
fp2_mul(&P.x, &P.x, &curve->C);
fp2_mul(&Q.x, &Q.x, &P.z);
fp2_mul(&Q.x, &Q.x, &curve->C);
fp2_mul(&E.A, &E.A, &t0);
fp_mont_setone(P.z.re);
fp_set(P.z.im, 0);
fp2_copy(&Q.z, &P.z);
fp2_copy(&E.C, &P.z);
// Compute P-Q
difference_point(&PQ3->PmQ, &P, &Q, &E);
copy_point(&PQ3->P, &P);
copy_point(&PQ3->Q, &Q);
}
void ec_curve_to_basis_6(ec_basis_t* PQ6, const ec_curve_t* curve){
fp2_t x, t0, t1, t2;
ec_point_t P, Q, Q6, P6, R, T, A24, A3;
// Curve coefficient in the form A24 = (A+2C:4C)
fp2_add(&A24.z, &curve->C, &curve->C);
fp2_add(&A24.x, &curve->A, &A24.z);
fp2_add(&A24.z, &A24.z, &A24.z);
// Curve coefficient in the form A3 = (A+2C:A-2C)
fp2_sub(&A3.z, &A24.x, &A24.z);
fp2_copy(&A3.x, &A24.x);
fp_mont_setone(x.re);
fp_set(x.im, 0);
// Find P
while(1){
fp_add(x.im, x.re, x.im);
// Check if point is rational
fp2_sqr(&t0, &curve->C);
fp2_mul(&t1, &t0, &x);
fp2_mul(&t2, &curve->A, &curve->C);
fp2_add(&t1, &t1, &t2);
fp2_mul(&t1, &t1, &x);
fp2_add(&t1, &t1, &t0);
fp2_mul(&t1, &t1, &x);
if(fp2_is_square(&t1)){
fp2_copy(&P.x, &x);
fp_mont_setone(P.z.re);
fp_set(P.z.im, 0);
}
else
continue;
// Clear non-2 factors and non-3 factors from the order
xMULv2(&P, &P, p_cofactor_for_6fg, (int)P_COFACTOR_FOR_6FG_BITLENGTH, &A24);
// Check if point has order 2^f*3^g
copy_point(&P6, &P);
for(int i = 0; i < POWER_OF_2 - 1; i++)
xDBLv2(&P6, &P6, &A24);
for(int i = 0; i < POWER_OF_3 - 1; i++)
xTPL(&P6, &P6, &A3);
if(ec_is_zero(&P6))
continue;
xDBLv2(&T, &P6, &A24);
if (ec_is_zero(&T))
continue;
xTPL(&T, &P6, &A3);
if (ec_is_zero(&T))
continue;
break;
}
// Find Q
while(1){
fp_add(x.im, x.re, x.im);
// Check if point is rational
fp2_sqr(&t0, &curve->C);
fp2_mul(&t1, &t0, &x);
fp2_mul(&t2, &curve->A, &curve->C);
fp2_add(&t1, &t1, &t2);
fp2_mul(&t1, &t1, &x);
fp2_add(&t1, &t1, &t0);
fp2_mul(&t1, &t1, &x);
if(fp2_is_square(&t1)){
fp2_copy(&Q.x, &x);
fp_mont_setone(Q.z.re);
fp_set(Q.z.im, 0);
}
else
continue;
// Clear non-6 factors from the order
xMULv2(&Q, &Q, p_cofactor_for_6fg, (int)P_COFACTOR_FOR_6FG_BITLENGTH, &A24);
// Check first if point has order 2^f*3^g
copy_point(&Q6, &Q);
for(int i = 0; i < POWER_OF_2 - 1; i++)
xDBLv2(&Q6, &Q6, &A24);
for(int i = 0; i < POWER_OF_3 - 1; i++)
xTPL(&Q6, &Q6, &A3);
if(ec_is_zero(&Q6))
continue;
xDBLv2(&T, &Q6, &A24);
if (ec_is_zero(&T))
continue;
xTPL(&T, &Q6, &A3);
if (ec_is_zero(&T))
continue;
// Check if point P is independent from point Q
xTPL(&R, &P6, &A3);
xTPL(&T, &Q6, &A3);
if(is_point_equal(&R, &T))
continue;
xDBLv2(&R, &P6, &A24);
xDBLv2(&T, &Q6, &A24);
if(is_point_equal(&R, &T))
continue;
break;
}
// Normalize points
ec_curve_t E;
fp2_mul(&t0, &P.z, &Q.z);
fp2_mul(&t1, &t0, &curve->C);
fp2_inv(&t1);
fp2_mul(&P.x, &P.x, &t1);
fp2_mul(&Q.x, &Q.x, &t1);
fp2_mul(&E.A, &curve->A, &t1);
fp2_mul(&P.x, &P.x, &Q.z);
fp2_mul(&P.x, &P.x, &curve->C);
fp2_mul(&Q.x, &Q.x, &P.z);
fp2_mul(&Q.x, &Q.x, &curve->C);
fp2_mul(&E.A, &E.A, &t0);
fp_mont_setone(P.z.re);
fp_set(P.z.im, 0);
fp2_copy(&Q.z, &P.z);
fp2_copy(&E.C, &P.z);
// Compute P-Q
difference_point(&PQ6->PmQ, &P, &Q, &E);
copy_point(&PQ6->P, &P);
copy_point(&PQ6->Q, &Q);
}