• Nenhum resultado encontrado

Figura 4.1: Diagrama de Comunicação

1 # ifndef BASICS_H_

2 # define BASICS_H_

3

4 # include <math .h>

5 # include " bigint .h"

6

7 # endif

Foi denido o tipo bigint, que representará números de até 512bits, apesar de as operações se basearem em 256 bits, operações como a multiplicação de 256 bits necessitam de um armazenamento de 512 bits.

As funções denidas neste módulo denem as operações básicas entre números inteiros necessárias para a implementação do protocolo ECDSA. Elas são:

Para entrada e saída:

• ler_bigint - lê um número na forma de caractere(bytes) e guarda em um bigint

• ler_hex_bigint - lê um número na forma hexadecimal e guarda em um bigint

• er_hex_bigint - lê um número em um arquivo na forma hexadecimal e guarda em um bigint

• ler_decimal - lê um número na forma decimal e guarda em um bigint

• imprime_hex_bigint - imprime um bigint na tela na forma hexadecimal

• mprime_hex_bigint - imprime um bigint em um arquivo na forma hexadecimal

• imprime_char_bigint - imprime um bigint na tela na forma de caractere(byte)

• imprime_decimal - imprime um bigint na tela na forma decimal Para Comparação:

• not_null - testa se um bigint é diferente de zero.

• eq_bigint - Testa se um bigint é igual a outro bigint

• eqi_bigint - Testa se um bigint é igual a um inteiro

• lt_bigint - Testa se um bigint é menor que outro bigint

• ltu_bigint - Testa se um bigint é menor que outro bigint na representação sem sinal

• let_bigint - Testa se um bigint é menor ou igual a outro bigint.

Para operações lógicas:

• append_int_bigint - acrescenta os bits de um inteiro no lado menos signicativo do bigint e descarta o mesmo número de bits adicionados no lado mais signicativo

• srl1_bigint - Dá um shift lógico de 1 bit à direita em um bigint

• sll1_bigint - Dá um shift lógico de 1 bit à esquerda em um bigint Para operações algébricas:

• init_bigint - Inicia um bigint com zero

• neg_bigint - Troca o sinal de um bigint

• random_bigint - Gera um bigint pseudo-aleatório

• atrib_bigint - Atribui o valor de um bigint em outro

• atribi_bigint - Atribui o valor de um inteiro em um bigint

• add_bigint - Soma dois bigint

• addi_bigint - Soma um bigint com um inteiro

• sub_bigint - Subtrai um bigint por outro

• subi_bigint - Subtrai um bigint por um inteiro

• mult_bigint - Multiplica dois bigint

• multi_bigint - Multiplica um bigint com um inteiro

• div_mod_bigint - Divide um bigint por outro, obtendo quociente e resto

• div_mod_i_bigint - Divide um bigint por um inteiro, obtendo quociente e resto

• pow_modp_bigint - Eleva um bigint por outro e este resultado é calculado mó-dulo um terceiro bigint

A seguir a descrição mais detalhada de cada uma.

4.2.1 Tipo bigint

O tipo bigint nada mais é que uma cadeia de bytes, ele é denido da seguinte maneira:

1 typedef unsigned char bigint [ TBITS +1]

Onde a constante TBITS está denido com65, 1 bit para armazenar o sinal do número mantendo 2512 −1 números positivos possíveis. Percebam que é necessário apenas um número positivo máximo de 2256−1, mas na multiplicação de 2 números deste tamanho, precisamos armazenar um número de 64 bytes.

O+1se deve a necessidade da linguagem de um byte para demarcar o m da string 3 sempre que se utiliza uma.

Antes de começar a descrever como foram implementadas as funções a seguir, é bom salientar que tais algoritmos foram retirados em sua maior parte de [14] e de [13].

4.2.2 init_bigint

Esta função tem por objetivo inicializar uma variável bigint com o valor 0. Recebe como parâmetro a variável a ser inicializada a.

Isto é feito em um loop que passa por cada byte da variável atribuindo o valor 0 a cada uma. A denição ca assim:

1 void init_bigint ( bigint a){

2 int i;

3 // loop que passa por todos os bytes da variavel

4 for(i=0;i< TBITS ;i++){

5 a[i ]=0;

3cadeia de caracteres.

6 }

7 }

4.2.3 not_null

Esta função recebe uma variável bigint a como o parâmetro e verica se ela é igual a 0 ou não, caso seja, a função retorna falso, caso contrário, retorna verdadeiro.

Isto é feito em um loop que passa por cada byte da variável testando se ela é igual a 0, caso encontre um retornará falso, se depois de todos os testes, não for encontrado um byte igual a 0retorna verdadeiro. O código ca assim:

1 bool not_null ( bigint a){

2 int i;

3 // loop que passa por todos os bytes da variavel

4 for(i=0;i< TBITS ;i++){

5 // caso o byte da vez for nao nulo , retorna verdadeiro

6 if(a[i ]!=0) {

7 return true;

8 }

9 }

10 // caso todos sejam nulos , retorna falso

11 return false;

12 }

4.2.4 neg_bigint

Esta função recebe uma variável bigint e inverte todos os bits do número. Em seguida adiciona 1 ao resultado. Método este que inverte o sinal do número representado pela forma de complemento de 2 4. O código ca assim:

1 void neg_bigint ( bigint a){

2 int i;

3 // loop que passa por todos os bytes da variavel

4 for(i=0;i< TBITS ;i++){

5 // inverte todos os bits de cada byte

6 a[i] = ~a[i];

7 }

8 // adiciona 1 ao valor de a

9 addi_bigint (a,a ,1);

10 }

A explicação da função addi_bigint estará mais adiante.

4representação de número na base 2 em que o primeiro bit além de denir uma parte do valor do número também dene se este é negativo ou positivo.

4.2.5 random_bigint

Esta função como dita anteriormente apenas simula um gerador aleatório, já que o objetivo do módulo é o protocolo do ECDSA implementado de forma simples não foi utilizado um método mais robusto.

Para simular um gerador de números aleatórios foi utilizada a função nativa da bibli-oteca stdlib como base. Para usar esta função é necessário no início do programa iniciar a semente. No código é usada a função rand() em cada byte até o 32o. Eis o código:

1 void random_bigint ( bigint a){

2 int i;

3 // loop que percorre os bytes do numero

4 for(i=0;i< TBITS ;i++){

5 // os 33 mais significativos ficam em 0, para que o numero seja de no maximo 256 bits

6 if(i <=32) {

7 a[i ]=0;

8 }else{

9 // gera um numero aleatorio para cada byte

10 a[i] = rand () %256;

11 }

12 }

13 }

4.2.6 ler_bigint

Esta função recebe como parâmetro a variável bigint que armazenará o número lido em forma de caracteres, ou seja, armazenará exatamente os caracteres lidos. Eis o código:

1 void ler_bigint ( bigint s){

2 int i,j;

3 unsigned char c;

4 i=0;

5 c = getc ( stdin );

6 //o loop ira ler cada caracter enquanto este for diferente de espaco ou enter , ou se passar do tamanho maximo do tipo

7 while(i< TBITS &&(c!='\n'&&c!=' ')){

8 s[i]=c;

9 c = getc ( stdin );

10 i++;

11 }

12 // caso o numero de caracteres forem menor que o tamnho do tipo , os bytes devem ser reposicionados

13 if(i< TBITS ){

14 i = TBITS - i;

15 }

16 // este loop reposiciona os bytes para as posicoes menos significativas .

17 // ao terminar os bytes restantes sao valorizados com zero .

18 for(j=TBITS -1;j >=0;j --){

19 if(j >=i){

20 s[j] = s[j-i];

21 }else{

22 s[j] = 0;

23 }

24 }

25 }

Perceba que ao ler uma seqüência de caracteres como abc estes caracteres cam nos bytes mais signicativos da cadeia que forma o tipo bigint, por isso, depois de ler, reposicionamos estes para os bytes menos signicativos. Como no exemplo:

Tabela 4.1: Tabela de Armazenamento do tipo bigint 0 1 2 ... TBITS-2 TBITS-1

a b c ... 0 0

depois do reposicionamento:

Tabela 4.2: Tabela de Armazenamento Reticado 0 1 ... TBITS-3 TBITS-2 TBITS-1

0 0 ... a b c

4.2.7 ler_hex_bigint

Esta função também é feita para ler do teclado o valor de um tipo bigint, mas o valor esperado na leitura é no formato hexadecimal. Para tal é utilizado uma manipulação da tabela ascii, de tal forma que caso o caracter lido for um algarismo é subtraído de seu valor 48, para que se tenha o valor correto de tal algarismo. No caso das letrasA, B, C, D, E, F, para que seus valores quem iguais a 10,11,12,13,14,15, subtrai-se 55, por m para as letras a, b, c, d, e, f, pelo mesmo motivo, subtrai-se87.

Este valor é somado à variável, inicialmente zerada e depois de cada soma, com ex-ceção da última, multiplica-se o resultado por 16. Assim fazendo a mudança de base de hexadecimal para binário. O código está abaixo:

1 void ler_hex_bigint ( bigint s){

2 unsigned char c;

3 unsigned int n;

4 // inicia -se a variavel com 0

5 init_bigint (s);

6 c = getc ( stdin );

7 // ler os caracteres ate que ache um espaco ou enter

8 while(c!='\n'&&c!=' '){

9 // multiplica o resultado por 16 para mudanca de base

10 multi_bigint (s,s ,16) ;

11 // Analisa qual o caracter e faz a operacao necessaria

12 if(c >47&&c <58) {// algarismos

13 n = c -48;

14 }else if(c >96&&c <103) {//a,b,c,d,e,f

15 n = c -87;

16 }else{//A,B,C,D,E,F

17 n = c -55;

18 }

19 // adiciona o resultado a variavel

20 addi_bigint (s,s,n);

21 c = getc ( stdin );

22 }

23 }

4.2.8 er_hex_bigint

Esta função recebe como parâmetro uma variável tipo bigint s e um ponteiro para um arquivo. Ela funciona do mesmo jeito que a anterior, com a diferença que ao invés de receber os caracteres do teclado, ele lê de um arquivo. O código segue abaixo:

1 void fler_hex_bigint ( bigint s, FILE *fp){

2 unsigned char c;

3 unsigned int n;

4 // inicia a variavel com o valor 0

5 init_bigint (s);

6 c = getc (fp);

7 // le caracter do arquivo enquanto este for diferente de espaco ou enter ou fim de arquivo

8 while(c!='\n'&&c!=' '&&! feof (fp)){

9 // multiplica o valor da variavel por 16 para mudanca de base

10 multi_bigint (s,s ,16) ;

11 // Analisa qual foi o tipo de caracter lido para transforma -lo adequadamente

12 if(c >47&&c <58) {// algarismo

13 n = c -48;

14 }else if(c >96&&c <103) {//a,b,c,d,e,f

15 n = c -87;

16 }else{//A,B,C,D,E,F

17 n = c -55;

18 }

19 // adiciona valor lido a variavel

20 addi_bigint (s,s,n);

21 c = getc (fp);

22 }

23 }

4.2.9 ler_decimal

Esta última função de leitura é semelhante às anteriores, mas a entrada esperada do teclado é um número decimal. Para tal, além de apenas fazer as contas para transformar

os caracteres dos algorismos, multiplica-se a variável a cada algorismo lido por 10, já que a mudança de base agora é de decimal para binário.

Outro caso a ser analisado é se existe o símbolo - no início do número, o que informa que o valor é negativo, para este caso, ao nal do cálculo do valor absoluto, apenas se inverte o valor com a função neg_bigint.

1 void ler_decimal ( bigint s){

2 unsigned char c;

3 unsigned int n;

4 bool nega =false;

5 // inicia o valor da variavel com 0

6 init_bigint (s);

7 c = getc ( stdin );

8 // testa se o numero lido e negativo

9 if(c=='-'){

10 nega = true;

11 c = getc ( stdin );

12 }

13 // le os algorismos ate que achar um espaco ou o enter

14 while(c!='\n'&&c!=' '){

15 // multiplica o valor da variavel por 10 para mudanca de base

16 multi_bigint (s,s ,10) ;

17 // transforma o caracter no valor do algarismo

18 n = c -48;

19 // adiciona o valor lido a variavel

20 addi_bigint (s,s,n);

21 c = getc ( stdin );

22 }

23 // caso o numero lido tiver o sinal - inverte seu valor

24 if( nega ){

25 neg_bigint (s);

26 }

27 }

4.2.10 imprime_hex_bigint

Esta função recebe como parâmetro uma variável do tipo bigint onde está armazenado o número que será escrito na forma hexadecimal no terminal. Este é feito da seguinte maneira. Do byte mais signicativo, começa-se a percorrer a cadeia enquanto não achar um byte diferente de zero. Caso todos sejam zero, imprime zero, caso contrário a partir do primeiro byte não zero, imprime o byte em forma hexadecimal. A seguir o código:

1 void imprime_hex_bigint ( bigint s){

2 int i;

3 i=0;

4 // procura o primeiro byte nao nulo .

5 while(i< TBITS &&s[i ]==0) {

6 i++;

7 }

8 // caso todos os bytes sejam zeros , imprime zero na tela

9 if(i== TBITS ){

10 printf ("%02x",0);

11 return;

12 }

13 // caso contrario , cada byte sera escrito na forma hexadecimal

14 while(i< TBITS ){

15 printf ("%02x",s[i]);

16 i++;

17 }

18 }

4.2.11 mprime_hex_bigint

A idéia desta função é a mesma da anterior, a diferença está que esta recebe como parâmetro, também, um ponteiro para arquivo, e ao invés de escrever o número em hexadecimal na tela, este será escrito no arquivo a qual o ponteiro está associado.

1 void fimprime_hex_bigint ( bigint s, FILE *fp){

2 int i;

3 i=0;

4 // procura o primeiro byte nao nulo .

5 while(i< TBITS &&s[i ]==0) {

6 i++;

7 }

8 // caso todos os bytes sejam zeros , imprime zero no arquivo

9 if(i== TBITS ){

10 fprintf (fp ,"%02x",0);

11 return;

12 }

13 // caso contrario , cada byte sera escrito na forma hexadecimal no arquivo

14 while(i< TBITS ){

15 fprintf (fp ,"%02x",s[i]);

16 i++;

17 }

18 }

4.2.12 imprime_char_bigint

Esta função novamente escreve o número armazenado na variável bigint passada como parâmetro. Mas desta vez na forma de caracter. A implementação segue a mesma lógica, mas ao invés de imprimir na forma hexadecimal, imprime na forma de caracter.

1 void imprime_char_bigint ( bigint s){

2 int i;

3 i=0;

4 // procura o primeiro byte nao nulo .

5 while(i< TBITS &&s[i ]==0) {

6 i++;

7 }

8 // caso todos os bytes sejam zeros , imprime caractere nulo na tela

9 if(i== TBITS ){

10 putc (0, stdout );

11 return;

12 }

13 // caso contrario , cada byte sera escrito na forma de caractere

14 while(i< TBITS ){

15 putc (s[i], stdout );

16 i++;

17 }

18 }

4.2.13 imprime_decimal

Esta função pega o parâmetro bigint passado para ela e a imprime na tela na forma decimal. Para esse código a lógica é um pouco mais extensa. Primeiramente, é avaliado se o número armazenado é negativo, caso seja, imprime o caracter - na tela e transforma o número em positivo, caso contrário, não faz nada.

Para o próximo passo é necessário duas variáveis bigint para auxiliar. No primeiro passo dividi-se o valor do parâmetro por 10 e guarda o quociente em um dos auxiliares e o resto em outro. Imprime o algarismo relativo ao resto e se o quociente for diferente de zero, inicia-se o seguinte loop:

Dividi-se o quociente por 10 e substitui o novo quociente no lugar do antigo, armaze-nando o novo resto no lugar do antigo também, e novamente imprime o algarismo relativo ao resto na tela. Repete-se até que o quociente seja igual a zero.

O código ca assim:

1 void imprime_decimal ( bigint s){

2 bigint q,m,x;

3 unsigned char num [80];

4 int i;

5 // atribui -se o valor do parametro a outra variavel para preservar o original

6 atrib_bigint (x,s);

7 // se o numero for zero , simplesmente imprime 0

8 if(! not_null (x)){

9 printf ("%d",0);

10 return;

11 }

12 // testa se o bit mais significativo e 1( numero negativo ), caso seja imprime "-" na tela e inverte o sinal do numero

13 if(s [0]&0 x80){

14 printf ("-");

15 neg_bigint (x);

16 }

17 i=1;

18 // armazena o resto modulo 10 do numero num vetor que sera impresso depois

19 div_mod_i_bigint (q,m,x ,10) ;

20 num [0] = m[TBITS -1]+48;

21 // loop que refaz a operacao acima enquanto o quociente for diferente de zero

22 while( not_null (q)){

23 div_mod_i_bigint (q,m,q ,10) ;

24 num[i] = m[TBITS -1]+48;

25 i++;

26 }

27 i --;

28 // imprime o vetor na ordem inversa , gerando na tela o numero correspondente ao armazenado

29 while(i >=0) {

30 putc (num[i], stdout );

31 i --;

32 }

33 }

4.2.14 eq_bigint e eqi_bigint

As funções eq_bigint e eqi_bigint testam se os dois parâmetros passados a elas possuem valores iguais. A primeira é um teste direto entre duas variáveis do tipo bigint, a segunda testa um bigint com um inteiro nativo da linguagem C++. Para esta o que se faz é atribuir o valor do inteiro em uma variável do tipo bigint e chamar a função eq_bigint, agora sim, com dois bigint.

Para testar a igualdade entre dois elementos bigint a função simplesmente percorre cada byte da cadeia de um, comparando-o com o byte correspondente do outro, caso sejam iguais continua o loop, caso contrário, interrompe o loop retornando falso. Se depois de decorrido toda a cadeia não for encontrado par de bytes diferentes retorna verdadeiro.

1 bool eq_bigint ( bigint a, bigint b){

2 int i;

3 // loop que percorre cada byte da cadeia

4 for(i=0;i< TBITS ;i++){

5 // para cada byte testa -se se seu correspondente na outra cadeia e diferente ou igual

6 if(a[i]!=b[i]){

7 // retorna falso caso encontre qualquer igual

8 return false;

9 }

10 }

11 // retorna verdadeiro caso todos sejam iguais

12 return true;

13 }

A função eqi_bigint não terá seu código exposto, visto que não há a necessidade, pois é simplesmente uma atribuição seguida de uma chamada da função acima.

4.2.15 lt_bigint e ltu_bigint

Ambas as funções lt_bigint e ltu_bigint recebem dois parâmetros do tipo bigint, o objetivo de ambas é testar se o primeiro parâmetro tem valor menor que o segundo. A única diferença entre elas é que no primeiro é considerado se os números são positivo ou negativo, enquanto no segundo, considera-se que são não sinalisados 5

Para efeito prático só será mostrado o código do lt_bigint, visto que a outra função é idêntica, apenas tirando o teste de sinal. Como então funciona o algoritmo?

Primeiro, quando há teste de sinal, testa-se se o sinal dos dois parâmetros são diferen-tes, caso sejam e o primeiro tenha sinal negativo, ou seja, bit mais signicativo igual a 1, a função termina retornando verdadeiro, caso seja positivo, ou seja, bit mais signicativo igual a 0, retorna falso.

Caso os sinais sejam iguais, percorre-se cada posição da cadeia, do mais signicativo pro menos signicativo, testando se o byte do primeiro parâmetro é maior que o seu respectivo no segundo, caso seja, signica que o segundo é menor que o primeiro, então retorna falso, se o primeiro for menor que o segundo, retorna verdadeiro. Se depois de todos os bytes testados, não for achado par de bytes diferentes, retorna falso.

1 bool lt_bigint ( bigint a, bigint b){

2 int i;

3 // testa se os sinais sao diferentes

4 if((a [0]&0 x80)!=(b [0]&0 x80)){

5 if((a [0]&0 x80) !=0) {//a e negativo , logo menor que b

6 return true;

7 }else{//a e positivo , logo maior que b

8 return false;

9 }

10 }

11 // para sinais iguais , testa -se do byte mais significativo ate o menos , qual e o maior

12 for(i=0;i< TBITS ;i++) {

13 if(a[i]<b[i]){// byte de a menor que o de b, a menor que b

14 return true;

15 }else if(a[i]>b[i]){// byte de a menor que o de b, a maior que b

16 return false;

17 }

18 }

19 // se nenhum par de bytes for diferente , a e igual a b

20 return false;

21 }

5tradução livre para unsigned, sem sinal.

4.2.16 let_bigint

Esta função testa se o primeiro dos dois parâmetros do tipo bigint que ela recebe é menor ou igual ao segundo parâmetro. Para tal, simplesmente é testado se este dois parâmetros mandados na mesma ordem que foram recebidos retornam verdadeiro para as funções eq_bigint ou lt_bigint. Caso sim retorna verdadeiro, senão falso. Visto a simplicidade da função, é desnecessário mostrar o código.

4.2.17 atrib_bigint e atribi_bigint

As funções atrib_bigint e atribi_bigint recebem dois parâmetros cada, a primeira recebe dois bigint's, a segunda recebe um bigint e um inteiro de 32 bits. Nas duas o objetivo é passar o valor do segundo parâmetro para o primeiro.

Para tal no atrib_bigint apenas se percorre cada byte da cadeia copiando o valor do byte do segundo parâmetro para seu respectivo no primeiro parâmetro, ca então assim:

1 void atrib_bigint ( bigint a, bigint b){

2 int i;

3 // loop que passa byte a byte os valores da cadeia b para a cadeia a

4 for(i=0;i< TBITS ;i++){

5 a[i] = b[i];

6 }

7 }

Para a função atribi_bigint, onde passamos um valor de um inteiro para o bigint é necessário algo mais. Primeiramente, sabe-se que na arquitetura da linguagem C++, o tipo inteiro possui 32 bits, ou seja, 4 bytes. Estes que serão copiados nos 4 bytes menos signicativos do parâmetro bigint.

Entretanto, é necessário analisar primeiro o sinal do inteiro, guarda-se a informação se este é positivo ou negativo, caso seja negativo, multiplica-se ele por -1, passando ele para o valor absoluto.

Depois simplesmente inicia-se o bigint com o valor 0. Em seguida é atribuído o valor dos 4 bytes do inteiro nos 4 bytes menos signicativos do bigint.

Ao terminar este passo, analisa-se a informação guardada sobre o inteiro, a que diz se este é positivo ou negativo, caso seja negativo, inverte-se o sinal do bigint com a função neg_bigint. O código ca assim:

1 void atribi_bigint ( bigint a, int n){

2 bool nega = false;

3 // inicia a com valor 0

4 init_bigint (a);

5 // testa se a e negativo

6 if(n <0){

7 // caso seja armazena esta informacao e transforma o numero em positivo

8 nega = true;

9 n*= -1;

10 }

11 // atribui os 4 bytes do inteiro nos 4 bytes menos significativos do bigint

12 a[TBITS -1] = n&0 xff;

13 a[TBITS -2] = (n > >8) &0 xff;

14 a[TBITS -3] = (n > >16) &0 xff;

15 a[TBITS -4] = (n > >24) &0 xff;

16 // caso o numero fosse inicialmente negativo , transforma o bigint em negativo

17 if( nega ){

18 neg_bigint (a);

19 }

20 }

4.2.18 append_int_bigint

Esta função recebe 2 parâmetros, o primeiro um bigint, o segundo um inteiro sem sinal, a idéia é concatenar os bits do bigint com os bits do inteiro. Pelo fato de ter o limite de tamanho do tipo bigint os 4 bytes mais signicativos deste serão descartados. Como ilustrado na tabela 4.3, ondea é a variável bigint e n é a variável inteira.

Tabela 4.3: Concatenação com descarte

a[0] a[1] ... a[TBITS-5] a[TBITS-4] a[TBITS-3] a[TBITS-2] a[TBITS-1]

a[4] a[5] ... a[TBITS-1] n[0] n[1] n[2] n[3]

Perceba que os bytes a[0], a[1], a[2], a[3]foram descartados.

O algoritmo para tal função funciona da seguinte forma: percorre-se o parâmetro bigint do byte 0, o mais signicativo, até o byte T BIT S−5 e para cada um deles será atribuído o valor do byte que está 4 posições a frente, assim na prática move-se todos os bytes 4 posições em direção ao lado mais signicativo. Depois apenas atribui-se nos 4 bytes menos signicativos os bytes do parâmetro inteiro inteiro.

O código ca assim:

1 void append_int_bigint ( bigint a, unsigned int n){

2 int i;

3 // move -se todos os bytes de a, 4 posicoes no sentido mais significativo

4 for(i=TBITS -32;i<TBITS -4;i++){

5 a[i] = a[i +4];

6 }

7 // atribuimos o valor de n nos bytes menos significativos de a

8 a[TBITS -4] = (n > >24) &0 xff;

9 a[TBITS -3] = (n > >16) &0 xff;

10 a[TBITS -2] = (n > >8) &0 xff;

11 a[TBITS -1] = (n)&0 xff;

12 }

4.2.19 srl1_bigint e sll1_bigint

Estas funções tem como objetivo mover todos os bits do parâmetro passado para elas uma posição à direita(lado mais signicativo) no caso da srl1_bigint ou a esquerda(lado menos signicativo) no caso da sll1_bigint.

No primeiro caso, em que se quer mover os bits para direita, percorre-se byte a byte do bigint, começando do mais signicativo, e para cada um é dado um shift 6 de 1 posição à direita, antes armazenando o bit que seria descartado.

Para o primeiro byte apenas opera-se o shift à direita, para os outros, logo depois de faze-lo, coloca-se o bit descartado no byte anterior no espaço 7obtido após o movimento.

Para o caso do sll1_bigint a idéia é a mesma, as alterações são: ao invés de para cada byte ser dado um shift a direita, é dado à esquerda, e percorre-se os bytes do bigint pelo byte menos signicativo. Assim será mostrado apenas o código referente ao srl1_bigint, visto que as alterações do outro código são triviais.

1 void srl1_bigint ( bigint a){

2 char out ,out2 ,aux;

3 int i;

4 out = 0;

5 // percorre cada byte de "a" a partir do byte mais significativo .

6 for(i=0;i< TBITS ;i++){

7 out2 = out;

8 out = a[i]<<7;// guarda o bit a ser descartado pelo shift

9 aux = a[i]>>1;// shift a direita de 1 posicao

10 //a sera a concatenacao do bit descartado

anteriormente e ele proprio dado um shift de 1 posicao a direita

11 a[i] = out2 |aux;

12 }

13 }

4.2.20 add_bigint e addi_bigint

Nas próximas funções serão implementadas as funções algébricas básicas, para estas deve-se dizer que os algoritmos usados estão descritos em [14], e especicamente os algo-ritmos de multiplicação e potenciação, foram retirados de [13]

A função add_bigint recebe 3 parâmetros, o primeiro, denominado de c, será onde será armazenado o resultado da soma, os outros dois, denominados de a e b, são os operandos da soma. Logo se tem que c=a+b. Para tal percorre-se byte a byte, a partir do menos signicativo e soma-se os bytes correspondentes de a e de b e de uma variável denominada carry, inicialmente zerada. Guarda-se a soma dos bytes em uma variável auxiliar short 8, onde o primeiro byte será posto no byte correspondente de c e o outro

6movimento lógico que signica mover todos os bits de uma variável tantas posições para algum lado.

7o shift automaticamente bota um bit 0 no bit que não tem antecessor, dizemos aqui que este é o

"espaço"obtido após o shift.

8inteiro de 2 bytes

No documento Estudo e implementação do protocolo ECDSA (páginas 51-72)

Documentos relacionados