123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- #include "fpe2scalar.hpp"
- unsigned long long mpz2ull (mpz_class n)
- {
- stringstream str;
- str << n;
- unsigned long long ull;
- str >> ull;
- return ull;
- }
- mpz_class ull2mpz (unsigned long long n)
- {
- stringstream str;
- str << n;
- mpz_class ull;
- str >> ull;
- return ull;
- }
- mpz_class fpe2mpz(const fpe_t op)
- {
-
-
- //fpe_print(stdout,op);
- //jump;
- extern const double bn_v;
- //zout(bn_v);
- //for (int i=0;i<12;i++)
- //{
- //cout << todouble(op->v[i]) << " " ;
- //}
- //cout << endl;
-
-
-
-
- mpz_class poly_at_one=1., increment_factor=6* bn_v;
- for (int i=0;i<12;i++)
- {
- if (i==0)
- {
- poly_at_one=todouble(op->v[0]);
- cout.precision ( 15 ); //NB
- ////zout(std::numeric_limits<double>::digits10);
- }
- if (i>=1 && i<=6) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor*=bn_v;}
- if (i==7) {increment_factor*=6.; poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor*=bn_v;}
- if (i>=8 && i<=11) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor*=bn_v;}
- //if (i<11) {zout(increment_factor);}
- }
- //zout(poly_at_one);
-
-
-
- ///** Méthode fausse 0: division ceil mpz_t, increment_factor=6*bn_v=11208198 l'incrément final est ok avec ce type de division mais on ne part pas du bon incrément au départ. Il faut multiplier, additionner des mpz_class pas des doubles pour le calculer correctement. **/
- //mpz_t v;
- //mpz_init_set_str (v, "1868033", 0);
- //mpz_t six;
- //mpz_init_set_str (six, "6", 0);
- //mpz_class poly_at_one=1;
- //mpz_class increment_factor=36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v; // l'erreur est ici, on peut pas définir un grand nombre en faisant des opérations sur les doubles
- //zout(increment_factor);
- //for (int i=11;i>=0;i--)
- //{
- //if (i>=8 && i<=11) {poly_at_one+=increment_factor*todouble(op->v[i]); mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), v);}
- //if (i==7) {mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), six); poly_at_one+=increment_factor*todouble(op->v[i]); mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), v);}
- //if (i>=2 && i<=6) {poly_at_one+=increment_factor*todouble(op->v[i]); mpz_cdiv_q(increment_factor.get_mpz_t(), increment_factor.get_mpz_t(), v);}
- //if (i==1) {poly_at_one+=increment_factor*todouble(op->v[i]);}
- //if (i==0) {poly_at_one+=todouble(op->v[0]); }
- //if (i>1) {zout(increment_factor);}
- //}
- //zout(poly_at_one);
- //mpz_clear(v);
- //mpz_clear(six);
-
-
- /** Méthode fausse 1 Ca marche presque avec / la division tronquée, mpz_class. increment_factor=11208197 **/
- //mpz_class poly_at_one=1;
- //mpz_class increment_factor=36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v;
- //for (int i=11;i>=0;i--)
- //{
- //if (i>=8 && i<=11) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor/=bn_v;}
- //if (i==7) {increment_factor/=6; poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor/=bn_v;}
- //if (i>=2 && i<=6) {poly_at_one+=increment_factor*todouble(op->v[i]); increment_factor/=bn_v;}
- //if (i==1) {poly_at_one+=increment_factor*todouble(op->v[i]);}
- //if (i==0) {poly_at_one+=todouble(op->v[0]); }
- //zout(poly_at_one,increment_factor);
- //}
- //zout(poly_at_one);
-
- ///** Méthode fausse numéro 2 pour calculer poly_at_one. Tous les opérandes sont des doubles, le résultat est incorrect, la précision est inférieur à 1 sur des doubles de plus de 53 bits. Il faut additionner des mpz_class. **/
- //mpz_class poly_at_one =
- //todouble(op->v[0]) +
- //todouble(op->v[1]) * 6 * bn_v +
- //todouble(op->v[2]) * 6 * bn_v * bn_v +
- //todouble(op->v[3]) * 6 * bn_v * bn_v * bn_v +
- //todouble(op->v[4]) * 6 * bn_v * bn_v * bn_v * bn_v +
- //todouble(op->v[5]) * 6 * bn_v * bn_v * bn_v * bn_v * bn_v +
- //todouble(op->v[6]) * 6 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
- //todouble(op->v[7]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
- //todouble(op->v[8]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
- //todouble(op->v[9]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
- //todouble(op->v[10]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v +
- //todouble(op->v[11]) * 36 * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v * bn_v;
- //zout(poly_at_one);
-
-
- mpz_class bn_u, bn_p;
- bn_u=1;//attention pow(bn_v,3); ne marche pas ni bn_v*bn_v*bn_v
-
- for (int i =0;i<3;i++)
- {
- bn_u*=bn_v;
- }
- bn_p=36 * bn_u * bn_u * bn_u * bn_u+36 * bn_u * bn_u * bn_u+24 * bn_u * bn_u+6 * bn_u + 1;
- //zout(bn_p);
- mpz_class field_element = poly_at_one % bn_p; //32 octets 256 bits le reste n'est pas forcément positif, il est obtenu avec une division dite tronquée, i.e. le reste a le même signe que le divisé, poly_at_one dans ce cas.
- //field_element = (sgn(field_element)>=0)? field_element :field_element+bn_p;
- //if (sgn(field_element)<0)
- //{
- //field_element+=bn_p;
- //}
- //zout(field_element);
- return field_element;
- }
- void fpe2scalar(scalar_t rop, const fpe_t op)
- {
-
- mpz_class field_element=fpe2mpz(op);
-
-
- ///** Technique du modulo **/
- ///** Calcul d'une puissance entière **/
- //mpz_class base=1;
- //for (int i=0; i<64; i++)
- //{
- //base=base*2;
- //}
- ////zout(base); // base 2^64
- //rop[0] = mpz2ull( field_element % base); //décomposition en base 2^64
- //rop[1] = mpz2ull((field_element >> 64) % base);
- //rop[2] = mpz2ull((field_element >> 128) % base);
- //rop[3] = mpz2ull((field_element >> 192) % base);
-
- //mpz_class test_modulo =ull2mpz(rop[0])+ull2mpz(rop[1])*base +ull2mpz(rop[2])*base*base+ull2mpz(rop[3])*base*base*base;
- //zout(test_modulo);
-
- /** Technique du masque en C++**/
- mpz_class mask = 0xffffffffffffffff; // 8 octets 64 bits
- rop[0] = mpz2ull (field_element & mask);
- rop[1] = mpz2ull((field_element >> 64) & mask);
- rop[2] = mpz2ull((field_element >> 128) & mask);
- rop[3] = mpz2ull((field_element >> 192) & mask);
- //mpz_class test_mask =ull2mpz(rop[0])+(ull2mpz(rop[1])<<64) +(ull2mpz(rop[2])<<128)+(ull2mpz(rop[3])<<192); //il faut mettre les parenthèses
- //zout(test_mask); //le test consiste à bien recomposer field_element à partir des rop[]
-
- /** Technique du masque en C**/
- //mpz_t c;
- //mpz_and(c,field_element.get_mpz_t() ,mask.get_mpz_t());
- // pour continuer avec la méthode C, il faut définir une fonction de conversion entre mpz_t et ull
-
-
- //zout(rop[0],rop[1],rop[2],rop[3]);
- }
- mpz_class scalar2mpz( const scalar_t op)
- {
- mpz_class r,rop;
-
- rop = ull2mpz(op[0]);
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 64); //on doit repasser par l'interface C de GMP
- rop += ull2mpz(op[1])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 128);
- rop += ull2mpz(op[2])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 192);
- rop += ull2mpz(op[3])*r;
-
- //zout(mpz_sizeinbase(rop.get_mpz_t(),2));
- if (mpz_sizeinbase(rop.get_mpz_t(),2) == 256) //si le mpz fait 256 bits, le bit de poids fort est pour le signe
- {
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 256);
- rop=rop-r;
- }
- return rop;
- }
- void mpz2scalar1024(scalar1024 rop, mpz_class field_element)
- {
- mpz_class mask = 0xffffffffffffffff; // 8 octets 64 bits
- rop[0] = mpz2ull (field_element & mask);
- rop[1] = mpz2ull((field_element >> 64) & mask);
- rop[2] = mpz2ull((field_element >> 128) & mask);
- rop[3] = mpz2ull((field_element >> 192) & mask);
- rop[4] = mpz2ull((field_element >> 256) & mask);
- rop[5] = mpz2ull((field_element >> 320) & mask);
- rop[6] = mpz2ull((field_element >> 384) & mask);
- rop[7] = mpz2ull((field_element >> 448) & mask);
- rop[8] = mpz2ull((field_element >> 512) & mask);
- rop[9] = mpz2ull((field_element >> 576) & mask);
- rop[10] = mpz2ull((field_element >> 640) & mask);
- rop[11] = mpz2ull((field_element >> 704) & mask);
- rop[12] = mpz2ull((field_element >> 768) & mask);
- rop[13] = mpz2ull((field_element >> 832) & mask);
- rop[14] = mpz2ull((field_element >> 896) & mask);
- rop[15] = mpz2ull((field_element >> 960) & mask);
- }
- mpz_class scalar1024_2mpz( const scalar1024 op)
- {
- mpz_class r,rop;
-
- rop = ull2mpz(op[0]);
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 64); //on doit repasser par l'interface C de GMP
- rop += ull2mpz(op[1])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 128);
- rop += ull2mpz(op[2])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 192);
- rop += ull2mpz(op[3])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 256);
- rop += ull2mpz(op[4])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 320);
- rop += ull2mpz(op[5])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 384);
- rop += ull2mpz(op[6])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 448);
- rop += ull2mpz(op[7])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 512);
- rop += ull2mpz(op[8])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 576);
- rop += ull2mpz(op[9])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 640);
- rop += ull2mpz(op[10])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 704);
- rop += ull2mpz(op[11])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 768);
- rop += ull2mpz(op[12])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 832);
- rop += ull2mpz(op[13])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 896);
- rop += ull2mpz(op[14])*r;
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 960);
- rop += ull2mpz(op[15])*r;
-
- //zout(mpz_sizeinbase(rop.get_mpz_t(),2));
- if (mpz_sizeinbase(rop.get_mpz_t(),2) == 1024) //si le mpz fait 256 bits, le bit de poids fort est pour le signe
- {
- mpz_ui_pow_ui (r.get_mpz_t(), 2, 1024);
- rop=rop-r;
- }
- return rop;
- }
|