ECC逆模数奇怪的时间执行

时间:2013-04-27 01:41:34

标签: c cryptography biginteger

嗨,大家好,请原谅我的英语 我开发了一个大整数函数c:

#ifndef __BIGINTEGER_H
#define __BIGINTEGER_H
#include <stdlib.h>
#include<stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "biginteger.h"
#define Maxbyte 19
typedef struct { uint32_t num[Maxbyte];
                 char sign ;
                 uint8_t lastblock ;} big_integer;


void init_biginteger(char *string_hex_number, big_integer *a);
big_integer Strassen_Multiplication(big_integer *a , big_integer *b );
big_integer add_biginteger(big_integer *a,big_integer *b );
big_integer sub_biginteger (big_integer *a,big_integer *b);
char  ABS_compare(big_integer *a , big_integer *b);
 void Lsh(big_integer *a , int shift, int bits);
 char div_mod(big_integer *a,big_integer *b,big_integer *Q,big_integer *R);
 char modulo(big_integer *a,big_integer *b,big_integer *c);
 char invers_modulo(big_integer *a ,big_integer *b,big_integer *c);
 void Rsh(big_integer *a , int shift,int bits);
  char zero(big_integer *a);
#endif

这是我的职能:

static void char_to_hex(char s , uint32_t *byte){

switch(s){
    case '0' : *byte = 0x0000000; break;
    case '1' : *byte = 0x0000001; break;
    case '2' : *byte = 0x0000002; break;
    case '3' : *byte = 0x0000003; break;  
    case '4' : *byte = 0x0000004; break; 
    case '5' : *byte = 0x0000005; break; 
    case '6' : *byte = 0x0000006; break; 
    case '7' : *byte = 0x0000007; break; 
    case '8' : *byte = 0x0000008; break; 
    case '9' : *byte = 0x0000009; break;
    case 'A' : *byte = 0x000000a; break;
    case 'B' : *byte = 0x000000b; break;
    case 'C' : *byte = 0x000000c; break; 
    case 'D' : *byte = 0x000000d; break;
    case 'E' : *byte = 0x000000e; break;
    case 'F' : *byte = 0x000000f; break;

} 
}
static uint64_t get_cary_add(uint64_t a , uint64_t b ) {
    uint64_t c,c1,max=0xFFFFFFFFFFFFFFFF;
    if(a>b){ c=a;
    c1=b;
    }else{c=b;
    c1=a;
    }
    if(max-c<c1){return 1;}else{


        return 0;}
}

static uint64_t safe_add64(uint64_t carry,uint64_t a, uint64_t b){
    if(carry==0){
        return a+b;}else{
            uint64_t a1=0,b1=0,c1=0;
            uint64_t a2=a,b2=b,s=0;
        a1= (a2 & 0x8000000000000000)>>63;
        b1= (b2 & 0x8000000000000000)>>63;
        a2=a2 & 0x7FFFFFFFFFFFFFFF;
        b2=b2 & 0x7FFFFFFFFFFFFFFF;
        s= a2+b2;
        c1=(uint64_t)(s)>>63;
        s=s & 0x7FFFFFFFFFFFFFFF;
        c1=(uint64_t) (a1+b1+c1)<<63;
        c1= (uint64_t)(s)| c1  ;
        return c1;

        }

    }

static uint32_t safe_add32(uint32_t carry,uint32_t a, uint32_t b){

    if(carry==0){
        return a+b;}else{
        uint32_t a1=0,b1=0,c1=0,s=0;
         uint32_t a2=a,b2=b;
        a1= (uint32_t) (a2 & 0x80000000) >> 31;
        b1= (uint32_t)((b2 & 0x80000000) >> 31);
        a2=a2 & 0x7FFFFFFF;
        b2=b2 & 0x7FFFFFFF;
        s= a2+b2;
        c1=(uint32_t)(s)>>31;
        s= s &  0x7FFFFFFF;
        c1=(uint32_t)(a1+b1+c1)<<31;
        c1= (uint32_t)(s)| c1  ;
        return c1;

        }

    }




static uint32_t get_carry_add(uint32_t a , uint32_t b ) {
    uint32_t c,c1,max=0xFFFFFFFF;
    if(a>b){ c=a;
    c1=b;
    }else{c=b;
    c1=a;
    }
    if(max-c<c1){return 1;}else{


        return 0;}
}

char  ABS_compare(big_integer *a , big_integer *b){
    int i=a->lastblock,k=-1;
    if(a->lastblock>b->lastblock){return 1;}
    else if (b->lastblock > a->lastblock){return 2;} 
    else{  

        while(k==-1){
        if(a->num[i]>b->num[i]){k=1;}
        else if(b->num[i]>a->num[i]){k=2;}
        else if( i==0 && k==-1){k=0;}
        i=i-1;
        }
         }
    return k;
}

void Lsh(big_integer *a , int shift,int bits){
    int i=0,j=0,k;
    //80000000;
    uint32_t temp=0;
    i=bits/32-1;
    k=i;
    for(j=0;j<shift;j++){

    if(i==0){
    a->num[0]=(a->num[0]<<1);

    }else{
   i=i-1;
    a->num[i+1]=(a->num[i+1]<<1);
    for(;i>=0;i--){
        temp=(a->num[i] & 0x80000000);
        temp=uint32_t(temp>>31);
        a->num[i]=(a->num[i]<<1);

        a->num[i+1]= a->num[i+1] | temp;

    }
    }

    }
    j=0;
    while(a->num[k]==0 && j==0){
        if(k!=0){
            k=k-1;}else {j=1;}

    }
    a->lastblock=k;

}


void Rsh(big_integer *a , int shift,int bits){
    int i=0,j=0,k=0;
    //80000000;
    uint32_t temp=0;
    i=bits/32-1;

    for(j=0;j<shift;j++){

    if(i==0){
    a->num[0]=(a->num[0]>>1);

    }else{

    //a->num[i+1]=(a->num[i+1]<<1);
    for(k=0;k<=i;k++){
        temp=(a->num[k+1] & 0x00000001);
        temp=uint32_t(temp<<31);
        a->num[k]=(a->num[k]>>1);

        a->num[k]= a->num[k] | temp;

    }
    }

    }
    j=0;
    while(a->num[k]==0 && j==0){
        if(k!=0){
            k=k-1;}else {j=1;}

    }
    a->lastblock=k;

}



void init_biginteger(char *string_hex_number, big_integer *a){
int i = strlen(string_hex_number)-1;
memset(a->num,NULL,Maxbyte*sizeof(uint32_t));
uint32_t byte=0;
int j=0,k=0;
for(i;i>=0;i--){
    if(string_hex_number[i]=='-'){a->sign=-1;}else{
    char_to_hex(string_hex_number[i],&byte);
  //  byte = string_hex_number[i] - 0x30;
    byte = (byte << j);
    a->num[k]=byte | a->num[k];
    j=j+4;
    if(j==32){
    k=k+1;
    j=0;
    }
    }

    }
if(string_hex_number[0]!='-') {a->sign = 1;}
if(k!=0){
    if(a->num[k]==0){k=k-1;}}

a->lastblock = k;
}

big_integer add_biginteger(big_integer *a,big_integer *b ){

    big_integer tempa,tempb,result,tempo;
    memset(result.num,NULL,Maxbyte*sizeof(uint32_t));
    tempa=*a;
    tempb=*b;
    int k,i;
    uint32_t carry=0,carry1=0,carry2=0;
    if(tempa.lastblock>tempb.lastblock){
        k=tempa.lastblock+1;
    }else { k=tempb.lastblock+1;}

    if(tempa.sign == tempb.sign){
        for(i=0;i<=k;i++){
            carry=(uint32_t)get_carry_add(tempa.num[i],tempb.num[i]);
            tempo.num[i]=safe_add32(carry,tempa.num[i],tempb.num[i]);
            //tempo.num[i]=(uint32_t)tempa.num[i] + tempb.num[i];
            carry2=(uint32_t)get_carry_add(tempo.num[i],carry1);
            //carry=+carry;
            result.num[i] = safe_add32(carry2, tempo.num[i] , carry1);
            carry1=carry2+carry;
            //carry1=carry;
        //carry1=carry+ get_carry_add(result.num[i],carry);

        } 

        while(result.num[i]==0){ i=i-1;  }
        result.lastblock=i;
        result.sign = tempa.sign;
        return result;
    }else if (tempb.sign==-1){
        tempb.sign=1;
        result = sub_biginteger(&tempa,&tempb);
        return result;
        }else {
            tempa.sign=1;
            result = sub_biginteger(&tempb,&tempa);
        return result;
        }





}


big_integer sub_biginteger (big_integer *a,big_integer *b){
    big_integer result,tempa,tempb;
    memset(result.num,NULL,Maxbyte*sizeof(uint32_t));
    tempa = *a;
    tempb=*b;
    int i,k;
    if(b->sign==-1 && a->sign==1){
        tempb.sign=1;
        result=add_biginteger(&tempa,&tempb);
        return result;  
    }else if(a->sign==-1 && b->sign==1){
        tempb.sign=-1;
        result=add_biginteger(&tempa,&tempb);
        return result;
    }else{


    k= ABS_compare(&tempa,&tempb);
    if(k==0){          
        result.lastblock=0;
        result.sign=1;
        return result;
    }else if(k==1){
        result.sign=1;
    }else { 
        result=tempb;
        tempb=tempa;
        tempa=result;

        result.sign=-1;}

    uint64_t tempo,temp,carry=0;
    for(i=0;i<tempa.lastblock+1;i++){
        if((uint64_t)tempa.num[i]< (uint64_t) (tempb.num[i]+carry)){

        temp=(uint64_t)tempa.num[i];
        tempo=(uint64_t)tempb.num[i]+carry;
        temp=(uint64_t)(temp+0x100000000 - tempo);
        result.num[i]=(uint32_t)temp;

        carry=1;
        }else{
            result.num[i]=tempa.num[i]-tempb.num[i]-carry;      
        carry=0;
        }}

    }

    while(result.num[i]==0){i=i-1;}
    result.lastblock=i;
    return result;

}



big_integer Strassen_Multiplication(big_integer *a , big_integer *b ){
    big_integer result ;
    big_integer tempa = *a;
    big_integer tempb = *b;
    uint32_t rest=0;
    uint64_t div=0,carry=0,carry1;
    int k,k1,i,j ,j2;
    if(a->lastblock > b->lastblock){ 
        k =tempa.lastblock+1;
        k1=tempb.lastblock+1;
        result= tempa;
        tempa=tempb;
        tempb=result;
    }else{
            k=tempb.lastblock+1;
            k1=tempa.lastblock+1;

        }

   uint64_t **arg=NULL;
   arg= (uint64_t ** ) calloc (k*2+3, sizeof(uint64_t *));
   if(arg==NULL){
   exit(1);
   }
for(i=0;i<k+3;i++){
    arg[i]= (uint64_t * ) calloc (k*2+3, sizeof(uint64_t));
  if(arg[i]==NULL){
   exit(1);
   }

}

j=0;

for(i=0;i<k1;i++){
    j2=0;

    for(j=i;j<k+i;j++){

        arg[i][j]=(uint64_t) tempb.num[j2]*tempa.num[i];
    // tab3[i][j]=arg3[i][j];
    j2=j2+1;
    }

}
memset(result.num,NULL,Maxbyte*sizeof(uint32_t));


for(j=0;j<(k1+k);j++){
for(i=0;i<k1;i++){
    carry=(uint64_t)carry+get_cary_add(arg[k+1][j],arg[i][j]  );
    arg[k+1][j]=(uint64_t)safe_add64 (carry,arg[i][j],arg[k+1][j]);

    }
carry1=get_cary_add(arg[k+1][j],div);
carry=carry+carry1;
arg[k+1][j]=(uint64_t)safe_add64(carry1,arg[k+1][j],div);
 div= (uint64_t) (arg[k+1][j] / 0x100000000) | (carry * 0x100000000) ;
 rest=(uint32_t)(arg[k+1][j] % 0x100000000);
 result.num[j]=(uint32_t)rest;
 carry=0;
}

result.sign = tempa.sign * tempb.sign;
while(result.num[j]==0 && j!=0){j=j-1;}
result.lastblock = j;
for(i=0;i<k*2+3;i++){
    free(arg[i]);}
free(arg);



    return result;
}







char div_mod(big_integer *a,big_integer *b,big_integer *Q,big_integer *R){
    int k;

    k=ABS_compare(a ,b);
    if(b->lastblock==0 && b->num[0]==0) {return -1;}
    else if(k==2){memset(R->num,NULL,Maxbyte*sizeof(uint32_t));
                  memset(Q->num,NULL,Maxbyte*sizeof(uint32_t));

                  Q->lastblock=0;
                  Q->sign=1;
                  *R=*a;
                  R->sign=a->sign;
                 }
    else if(k==0){memset(R->num,NULL,Maxbyte*sizeof(uint32_t));
                  memset(Q->num,NULL,Maxbyte*sizeof(uint32_t));
                  Q->num[0]=1;
                  Q->lastblock=0;
                  Q->sign = a->sign * b->sign;
                  R->sign=1;
                  R->lastblock=0;
                  R->num[0]=0;

    }

    else { memset(R->num,NULL,Maxbyte*sizeof(uint32_t));
           memset(Q->num,NULL,Maxbyte*sizeof(uint32_t));
           uint8_t lb=a->lastblock;
           big_integer tempa,tempb;
           tempa=*a;
           tempb=*b;
           tempb.lastblock = tempa.lastblock;
           R->lastblock = tempa.lastblock;
           Q->lastblock = tempa.lastblock;
           int i = tempa.lastblock,size = (lb+1)*32,j=0;

           uint32_t bits= 0x80000000,h;
           for(;i>=0;i--){
               for(j=31;j>=0;j--){
               Lsh(R,1,size);
               R->lastblock = lb;
               h=(tempa.num[i]<<(31-j));
               h=h>>31;
              // byte = byte & 0x01;
               R->num[0]=uint32_t(R->num[0] | h);
               if(ABS_compare(R ,&tempb)!=2){
               *R=sub_biginteger(R,&tempb );
               R->lastblock=lb;
               tempb.lastblock=lb;
               Q->num[i]=  Q->num[i] | ( bits>>(31-j));
               }
               }
           }
           Q->sign= a->sign * b->sign;
           R->sign= a->sign;
           j= lb;
           while(Q->num[j]==0 && j!=0){j=j-1;}
           Q->lastblock = j;
           j= lb;
           while(R->num[j]==0 && j!=0){j=j-1;}
           R->lastblock = j;


    }


return 1;
}


char modulo(big_integer *a,big_integer *b,big_integer *c){

    big_integer temp;
    char k;
    k=div_mod(a,b,&temp,c);
    if(k==-1){ return -1;}else{
        if(a->sign==-1){
            *c=add_biginteger(c ,b);}
    }
    return 1;

}

 char zero(big_integer *a){
    if(a->sign==-1){ return -1;       }else {
        /*int i=0,j=0;
        while(i!=a->lastblock && j==0){
            if(a->num[i]!=0){j=1;}
            i=i+1;

        }
        if(j=1){return 1;}else{
            return 0;}*/
        if(a->lastblock >0){return 1;}else{
            if(a->num[0]==0){return 0;}else{
                return 1;}
        }


}
}

 char invers_modulo(big_integer *a ,big_integer *b,big_integer *c){

    if( b->sign==-1){ return -1;}

     big_integer tempa=*a,tempb=*b;
    tempa.sign=1;
     big_integer d,t,x,v,tempo,d1;

    init_biginteger("1",&d);
    init_biginteger("0",&v);
    int conteur=0;

    //clock_t pp;
 //pp = clock();
    while(zero(&tempa)==1){
    x=tempa;
    //conteur = conteur +1;
    /*if(conteur==57){
    conteur = conteur;
    }*/
    //printf("%i \n", conteur);
    div_mod(&tempb,&tempa,&t,&tempo);
    tempa=tempo;
    tempb=x;
    x=d;
    d1=Strassen_Multiplication(&t ,&x );
    d= sub_biginteger (&v,&d1);
    v=x;
    }
    //printf("%i \n",conteur);
    // pp= clock() - pp; 
  //printf ("It took me %d clicks (%f seconds).\n",pp,(((double)pp)/CLOCKS_PER_SEC));
    tempb=*b;
    modulo(&v,&tempb,&tempo);
    if(v.sign==-1){
    modulo(&add_biginteger(&v,&tempb),&tempb,&tempo); }
    *c=tempo;

    //printf("%i \n",conteur);

return 1;

}

现在问题是256位整数逆模数需要0.005 s那太多ECC加密cuz在标量乘法中我将重复至少256次双倍并添加算法

我已经完成了一些关于时间的测试,这个测试主要是在大约10k时间内以0.69秒结束:

#include "biginteger.h"
#include "ECC.h"
#include <time.h>
void main(){

    clock_t t;
 t = clock();
    int p=1;

    big_integer a,b,c,r,q,a1,b1;
    ECC_domaine_parameter domain;
init_biginteger("580EC00D856434334CEF3F31ECAED4965B12AE37FA47055B1965C7B134EE45D0",  &a);
init_biginteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", &b);
while(p!=0 ){  div_mod(&b,&a,&q,&r);
               c=Strassen_Multiplication(&a , &b );
                c=sub_biginteger(&a,&b );

         a1=a;
         b1=b;
         b1=a;
         a1=b;
         a1=b1;
         p=p+1;
     if(p==10001){
         printf("end %i \n",p);
         p=0;}} 
 t = clock() - t; 
  printf ("It took me %d clicks (%f seconds).\n",t,(((double)t)/CLOCKS_PER_SEC));
}

现在是相同的2 256位整数的逆模函数核心:

char invers_modulo(big_integer *a ,big_integer *b,big_integer *c){

    if( b->sign==-1){ return -1;}

     big_integer tempa=*a,tempb=*b;
    tempa.sign=1;
     big_integer d,t,x,v,tempo,d1;

    init_biginteger("1",&d);
    init_biginteger("0",&v);
    int conteur=0;
while(zero(&tempa)==1){ div_mod(&tempb,&tempa,&t,&tempo);
    tempa=tempo;
    tempb=x;
    x=d;
    d1=Strassen_Multiplication(&t ,&x );
    d= sub_biginteger (&v,&d1);
    v=x;
    }tempb=*b;
    modulo(&v,&tempb,&tempo);
    if(v.sign==-1){
    modulo(&add_biginteger(&v,&tempb),&tempb,&tempo); }
    *c=tempo;



return 1;
} 

对于逆模,它需要150次内部而这是测试主要只执行invers模300次:

 void main(){

    clock_t t;
 t = clock();
    int p=1;

    big_integer a,b,c,r,q,a1,b1;
    ECC_domaine_parameter domain;
init_biginteger("580EC00D856434334CEF3F31ECAED4965B12AE37FA47055B1965C7B134EE45D0",  &a);
init_biginteger("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", &b);
 while(p!=0 ){ invers_modulo(&a ,&b,&c);

         a1=a;
         b1=b;
         b1=a;
         a1=b;
         a1=b1;
         p=p+1;
     if(p==300){
         printf("end %i \n",p);
         p=0;}}
 t = clock() - t; 
  printf ("It took me %d clicks (%f seconds).\n",t,(((double)t)/CLOCKS_PER_SEC));
}

反向模数为300时间比执行除法加上1.422次加法和乘法10k时间甚至反模的核心是用相同的除法和子和乘法函数构建的,对于这个数字它只需要做150次内部而帮助plz为什么

1 个答案:

答案 0 :(得分:0)

倒置是一项非常密集的操作。您可以执行多项优化,例如,最大限度地减少必须使用的反转量或优化反演算法。例如,要优化算法,可以实现Itoh-Tsujii Inversion。

要减少所需的反转量,您可以从仿射坐标系中的表示点转换为投影表示。对于ECC系统,常用的投影坐标版本就是所谓的López-Dahab坐标和操作。

相关问题