Teoria de números e criptografia RSA Elaine Gouvêa Pimentel 1 o Semestre - 2006 (Última Modificação: 4 de Maio de 2006) 1 Bibliografia e referências Livro texto: S.C. Coutinho Números inteiros e criptografia RSA IMPA/SBM, 2000. Outras referências: Rosen, K. H., Elementary number theory and its applications, Addison- Wesley,1984. Koblitz, N. A course in number theory and criptography, Graduate Texts in Mathematics 97, Springer-Verlag, 1987. Ao longo do curso, serão indicadas leituras complementares. Qualquer dúvida ou comentário, escrever para: elaine@mat.ufmg.br 2 Introdução O objetivo desse curso é estudar o método de criptografia de chaves públicas conhecido como RSA. Para entender como este método funciona, é necessário o estudo de alguns conceitos de uma área da matemática chamada Teoria de números. E, é claro, espera-se desenvolver, ao longo do curso, o raciocínio lógico matemático dos alunos, introduzindo métodos de prova de teoremas como indução matemática e demonstração por absurdo. Deve ficar bem claro que este é um curso de matemática para cientistas da computação. Isto é, o rigor nunca será deixado de lado mas a atenção estará sempre voltada para a aplicação principal proposta: criptografia RSA. 1
2.1 Criptografia Criptografia: estuda os métodos para codificar uma mensagem de modo que só seu destinatário legítimo consiga interpretá-la. Primórdios: Cesar (translação do alfabeto). Criptoanálise: arte de decifrar códigos secretos. Decodificar x Decifrar (quebrar). Substituir letras por símbolos - contagem de frequência: vogais são mais frequentes; letra mais frequente: A; monossílabo de uma letra = vogal; consoantes mais frequentes: S e M Método de contagem de frequência de caracteres pode ser usado para decifrar inscrições antigas. O surgimento dos computadores torna esse método de cifragem completamente inseguro (decifragem polinomial). Internet e criptografia: segurança, assinatura. Chave pública: saber codificar não implica saber decodificar! 2.2 Criptografia RSA RSA: Rivest, Shamir, Adleman (M.I.T.) 1978. Codificação: basta conhecer o produto de dois primos (n = pq). n é chamado chave pública. Decodificação: precisamos conhecer p e q (chave de decodificação). Decifrar RSA = fatoração de n. Se n possui 150 algarismos ou mais, fatorá-lo levaria milhares de anos. Obs: É difícil determinar os fatores primos de um número composto, mas é possível verificar se um número é primo ou composto sem tentar fatorá-lo. Teoria de números: parte da matemática que estuda números inteiros. 2
2.3 Computação algébrica Chave pública do RSA: multiplica-se dois primos muito grandes. Pascal, C: não permitem lidar com números dessa magnitude. Computação algébrica: trata do cálculo exato com inteiros, frações, etc. Exemplo: Mathematica, Maple. Inteiro de tamanho indeterminado: de tamanho flexível, grandes o suficiente. Restrições: tamanho da memória, estruturas de dados (vetores de tamanhos pré-fixados). Inteiros = listas! Algarismos = elemento da lista; operações de soma e multiplicação: usuais, como com lápis e papel. Divisão é mais complicado... 3 Algoritmo da divisão de Euclides 3.1 Algoritmos Algoritmo = processo de cálculo baseado em regras formais. Especificação de um algoritmo: entrada + instruções + saída. Perguntas: ao executarmos um conjunto de instruções, sempre chegaremos a um resultado? (ponto fixo) o resultado obtido é sempre o desejado? (semântica) 3.2 Algoritmo da divisão Objetivo: encontrar o quociente q e o resto r (saída) da divisão entre dois inteiros positivos a e b (entrada): Algoritmo da divisão: Etapa 1: q = 0; r = a a = bq + r 0 r < b. Etapa 2: Se r < b, pare. Nesse caso, o quociente é q e o resto r. Etapa 3: Se r b, faça r := r b, q := q + 1 e volte à Etapa 2. Observações: 3
1. O algoritmo sempre para: sequência decrescente de números inteiros positivos. 2. O resultado da aplicação do algoritmo corresponde às especificações da saída (trivialmente). 3. O algoritmo é extremamente ineficiente, em especial se a >> b. 3.3 Teorema da Divisão Teorema 1 (Teorema de divisão) Sejam a e b inteiros positivos. Existem números inteiros q e r tais que a = bq + r 0 r < b Além disso, q e r são únicos. Prova. Unicidade - Sejam q,q,r,r tais que a = bq + r 0 r < b (1) a = bq + r 0 r < b (2) Subtraindo-se (1) de (2), obtemos: r r = b(q q) Ora, mas 0 r,r < b e portanto 0 r r < b. Ou seja, 0 b(q q) < b Como b > 0, temos 0 q q < 1 ou seja, q q = 0 q = q e r = r. 3.4 Algoritmo Euclideano Objetivo: Calcular o mdc entre dois números inteiros. Definição: o máximo divisor comum que: entre a e b é o número d tal d a (ou d é divisor de a) d b se d é divisor de a e b, então d d (em outras palavras, d é o máximo divisor de a e b. 4
Escrevemos d = mdc(a,b). Se mdc(a,b) = 1, dizemos que a e b são primos entre si. Algoritmo Euclideano: Dados dois números inteiros positivos a e b tais que a b, divide-se a por b, encontrando resto r 1. Se r 1 0, dividimos b por r 1, obtendo resto r 2. Se r 2 0, dividimos r 1 por r 2 e assim por diante. O último resto diferente de zero mdc(a,b). Exemplo: 1234 54 46 8 6 2 46 8 6 2 0 Ou seja, mdc(1234, 54) = 2. Perguntas: 1. Por que o último resto não nulo é o mdc? 2. Por que o algoritmo para? dessa sequência de divisões é o Respostas: a = bq 1 + r 1 e 0 r 1 < b b = r 1 q 2 + r 2 e 0 r 2 < r 1 r 1 = r 2 q 3 + r 3 e 0 r 3 < r 2 r 2 = r 3 q 4 + r 4 e 0 r 4 < r 3.. Segunda pergunta: observe que b > r 1 > r 2 >... 0 Como essa sequência é finita, o algoritmo sempre para. Mais ainda, o número de divisões efetuadas é no máximo b (por que?). Primeira pergunta: demonstração do algoritmo euclideano 3.5 Demonstração do algoritmo euclideano Lema 2 Sejam a e b números inteiros positivos. Se existem inteiros g e s tais que a = bg + s, então mdc(a,b) = mdc(b,s). Prova. Sejam d 1 = mdc(a,b) e d 2 = mdc(b,s). 5
Afirmamos que d 1 d 2. De fato, d 1 é o máximo divisor de a e b. Logo d 1 divide a e b e portanto existem inteiros positivos u e v tais que: a = d 1 u eb = d 1 v Substituindo a e b na equação a = bg + s obtemos s = d 1 u d 1 v = d 1 (u vg). Ou seja, d 1 divide s. Como d 1 também divide b, d 1 é um divisor comum de b e s. Mas d 2 é o maior divisor de b e s e portanto (por definição) d 1 d 2 como queríamos. Seguindo um argumento semelhante, podemos provar o inverso, ou seja, d 2 d 1. Em outras palavras, d 1 = d 2 Teorema 3 Dados a e b inteiros positivos, o último resto diferente de zero da sequência de divisões dada pelo algoritmo euclideano para a e b é o máximo divisor comum entre a e b. Prova. Aplicando o algoritmo a a e b, temos: a = bq 1 + r 1 e 0 r 1 < b b = r 1 q 2 + r 2 e 0 r 2 < r 1 r 1 = r 2 q 3 + r 3 e 0 r 3 < r 2 r 2 = r 3 q 4 + r 4 e 0 r 4 < r 3.. r n 2 = r n 1 q n e r n = 0 Da última linha, temos que r n 1 divide r n 2 e portanto mdc(r n 1,r n 2 ) = r n 1. Aplicando sucessivamente o lema 2, temos que mdc(a,b) = r n 1. 3.6 Algoritmo euclideano estendido O resultado que mais vamos usar durante o curso sobre mdc é o seguinte: Teorema 4 Sejam a e b inteiros positivos e seja d o máximo divisor comum entre a e b. Esxistem inteiros α e β tais que α.a + β.b = d. Para demonstração desse teorema, veja o livro texto, pag 29-31. Vamos ilustrar a demonstração através de um exemplo numérico: 6
Exemplo 1 Sejam a = 1234 e b = 54. Temos que: 1234 = 54.22 + 46 ou seja, 46 = 1234 54.22 Seguindo pelo algoritmo de euclides, 54 = 46.1 + 8 ou seja, 8 = 54 46.1 Agora, observe que sabemos calcular 46 em função de 1234 e 54. Então, substituindo: 8 = 54 46.1 = 54 (1234 54.22).1 = 54(1+22.1)+1234.( 1) = 54.(23)+1234.( 1) Continuando, 46 = 8.5 + 6 6 = 46 8.5 = (1234 54.22) (54.(23) + 1234.( 1)).5 = 1234.(6) + 54.( 22 (23).5) = 1234.(6) + 54.( 137) 8 = 6.1 + 2 2 = 8 6 = (54.(23) + 1234.( 1)) (1234.(6) + 54.( 137)) = 1234( 1 6) + 54(23 + 137) = 1234( 7) + 54(160) Logo, α = 7 e β = 160 uma vez que mdc(1234,54) = 2. Observe que o teorema não diz que os valores de α e β são únicos. Na verdade, existe uma infinidade de números que satisfazem a equação αa + βb = d. Pergunta: para que serve calcular α e β? Resposta: unicidade de fatoração de um inteiro; RSA depende de um método eficiente de cálculo de α e β. 3.7 Exercícios propostos Não deixem de fazer os seguintes exercícios do capítulo 1: 1(1),4,5,7,8,9. 7
4 Fatoração única 4.1 Teorema da fatoração única Dizemos que um número inteiro positivo p é primo divisores de p são p e 1. se p 1 e os únicos Se um número inteiro positivo (diferente de 1) não é primo, então ele é chamado de composto. Teorema 5 (Teorema da fatoração única) Dado um inteiro positivo n 2 podemos sempre escrevê-lo, de maneira única, na forma: n = p e1 1...pe k k onde 1 < p 1 < p 2 <... < p k são números primos e e 1,...,e k são inteiros positivos (multiplicidades). 4.2 Existência da fatoração Algoritmo ingênuo: Dado n 2 inteiro positivo, tente dividir n por cada um dos inteiros de 2 a n 1. Se algum desses inteiros (digamos k) dividir n, então achamos um fator de n. Perguntas: 1. k é primo ou composto? 2. Quando se deve parar a busca? Em n 1? Respostas: 1. k é primo. De fato, suponhamos k composto. Logo, k = a.b com 1 < a,b < k. Como k divide n, existe (por definição) c inteiro tal que n = k.c. Logo, n = a.b.c ou seja, a e b são fatores de n menores que k, o que contraria a hipótese da minimalidade de k. Logo, k é primo. 2. Na verdade, podemos parar o algoritmo em n. De fato, n = k.c ou c = n k. Como k é o menor fator de n, k c. Logo, k n k ou seja, k 2 n k n. Podemos utilizar o algoritmo acima para achar todos os fatores primos de n. Aplicando o algoritmo uma vez, encontramos o fator q 1. Então, aplicamos o 8
algoritmo ao número n q 1, determinando q 2, o segundo fator primo de n. Para n determinar o terceiro fator primo q 3, aplicamos o algoritmo ao número q 1.q 2 e n assim por diante, até chegarmos em q 1.q 2...q s 1 = q s, com q s primo. Observe que q 1 q 2... q s 1 q s e n > n q 1 > ou seja, o algoritmo sempre termina. Exemplo 2 n = 450 = 2.3.3.5.5 n n >... > > 0, q 1.q 2 q 1.q 2...q s 4.3 Eficiência do algoritmo ingênuo de fatoração O algoritmo é simples mas muito ineficiente! Exemplo 3 Seja n um número primo com 100 ou mais algarismos. Logo, n 10 100 e portanto n 10 50. Logo temos que executar pelo menos 10 50 loops para determinar que n é primo. Suponhamos que o nosso computador execute 10 10 divisões por segundo. Logo levaremos 1050 10 = 10 40 segundos, ou 10 seja, 10 31 anos na frente da tela do computador aguardando... Observe que o tempo estimado de existência do universo é 10 11 anos! O algoritmo é bom para números pequenos. É importante ressaltar que não existe (atualmente) algoritmo de fatoração eficiente para todos os inteiros. Disso depende a segurança do RSA! Não se sabe, entretanto, se tal algoritmo não existe mesmo ou se não fomos espertos o suficiente para inventá-lo... 4.4 Fatoração por Fermat Eficiente quando n tem um fator primo não muito menor que n. Idéia: tentar achar números inteiros positivos x e y tais que n = x 2 y 2. Caso mais fácil: n = r 2 (x = r e y = 0). Se y > 0, então x = n + y 2 > n Notação: escrevemos [r] como a parte inteira do número real r. Algoritmo de Fermat: Etapa 1: Faça x = [ n]; se n = x 2, pare. 9
Etapa 2: Incremente x de uma unidade e calcule y = x 2 n. Etapa 3: Repita a etapa 2 até encontrar um valor inteiro para y, ou até que x = n+1 2. No primeiro caso, n tem fatores x + y e x y; no segundo, n é primo. Exemplo 4 Seja n = 1342127. Temos que x = 1158. Mas x 2 = 1158 2 = 1340964 < 1342127 Logo, passamos a incrementar x até que x2 n seja inteiro ou x = n+1 2, que nesse caso vale 671064: x x2 n 1159 33, 97 1160 58, 93 1161 76, 11 1162 90, 09 1163 102, 18 1164 113 Logo, x = 1164 e y = 113. Os fatores procurados são x+y = 1277 e x y = 1051. Faremos aqui apenas a demonstração de que, se n é primo, então o único valor possível para x é x = n+1 2. Relembrando, x e y são inteiros positivos tais que n = x 2 y 2. Ou seja, n = (x y)(x + y) Como estamos supondo n primo, temos que x y = 1 e x + y = n. Logo, como queríamos. x = 1 + n 2 e y = n 1 2 Veja a demonstração completa do algoritmo no livro texto, páginas 41 a 43. Observação: Esse algoritmo diz algo importante sobre o RSA. Se escolhermos p e q muito próximos, então n = p.q é facilmente fatorável pelo algoritmo de Fermat. 4.5 Propriedade fundamental dos primos Lema 6 Sejam a,b,c inteiros positivos e suponhamos que a e b são primos entre si. Então: 1. Se b divide o produto a.c então b divide c. 10
2. Se a e b dividem c então o produto a.b divide c. Prova tais que Então, mdc(a, b) = 1. Pelo Algoritmo euclideano estendido, existem α e β α.a + β.b = 1 α.a.c + β.b.c = c Como b divide a.c pela hipótese (1) e como b divide β.b.c, então b divide c. Para provar a segunda afirmativa, se a divide c, podemos escrever c = at para algum inteiro t. Mas b também divide c. Como mdc(a,b) = 1, pela afirmação (1), b divide t. Logo, t = b.k para algum inteiro k e portanto, c = a.t = a.b.k Podemos usar o lema acima para provar se seguinte propriedade: Propriedade fundamental dos primos Seja p um primo e a e b inteiros positivos. Se p divide o produto a.b, então p divide a ou p divide b. A demonstração fica como exercício (façam!). 4.6 Unicidade A prova de unicidade da fatoração de números primos decorre facilmente da propriedade fundamental dos primos. A demonstração se dá por absurdo. Seja n o menor inteiro positivo que admite duas fatorações distintas. Podemos escrever: n = p e1 1...pe k k = qr1 1...qrs s onde p 1 < p 2 <... < p k e q 1 < q 2 <... < q s são primos e e 1,...,e k,r 1,...,r s são inteiros positivos. Como p 1 divide n, pela propriedade fundamental dos primos p 1 deve dividir um dos fatores do produto da direita. Mas um primo só pode dividir outro se forem iguais. Então p 1 = q j para algum j entre 1 e s. Logo, n = p e1 1...pe k k = q r1 1...qrj j...qrs s = q r1 1...prj 1...qrs s Podemos então cancelar p 1 que aparece em ambos os lados da equação, obtendo m = p e1 1 1...p e k k = qr1 1...prj 1 1...qs rs onde m é um número menor que n que apresenta duas fatorações distintas. ABSURDO pois isso contraria a minimalidade de n. 11
4.7 Exercícios propostos 1. Prove a propriedade fundamental dos primos. 2. Demonstre que, se p é um número primo, então p é um número irracional. 3. Livro texto: 2, 4, 5, 8, 11, 12. 5 Números primos Até agora: propriedades básicas dos números inteiros; dois algoritmos fundamentais; Nessa seção, discutiremos métodos ingênuos para encontrar primos. 5.1 Fórmulas Polinomiais Considere o polinômio: f(x) = a n.x n + a n 1.x n 1 +... + a 1.x + a 0 onde a n,a n 1,...,a 1,a 0 são números inteiros e que satisfaz a condição: f(m) é primo, para todo inteiro positivo m Exemplo 5 Seja f(x) = x 2 + 1 Logo, x ímpar f(x) par; f(8) = 65 composto... x f(x) 1 2 2 5 3 10 4 17 5 26 6 37 7 50 8 65 9 82 2 5 12
A pergunta que surge então é: isso é fruto do azar? Teorema 7 Dado um polinômio f(x) com coeficientes inteiros, existe uma infinidade de inteiros positivos m tais que f(m) é composto. Prova. Vamos Provar o teorema apenas no caso em que o polinômio tem grau 2. Ou seja, consideraremos f do tipo: f(x) = a.x 2 + b.x + c Podemos supor a > 0. Suponhamos que exista m tal que f(m) = p onde p é primo. Calculando f(m + hp): f(m + hp) = a(m + hp) 2 + b(m + hp) + c = (am 2 + bm + c) + p(2amh + aph 2 + bh) = p(1 + 2amh + aph 2 + bh) Ou seja, se 1+2amh+aph 2 +bh é composto então f(m+hp) também é composto. Mas isso é verdade sempre que ou seja, se 1 + 2amh + aph 2 + bh > 1 2amh + aph 2 + bh = h.(2am + aph + b) > 0 Como podemos sempre tomar h positivo, temos: 2am + aph + b > 0 h > b 2am a.p Existe uma infinidade de números dessa forma. Logo, se existe inteiro m tal que f(m) é primo, então existe uma infinidade de tais números. Conclusão: não existe uma fórmula polinomial (em uma variável) para primos. 5.2 Fórmulas exponenciais: números de Mersenne Números de Mersenne são aqueles da forma: onde n é um inteiro não negativo. M(n) = 2 n 1 Números perfeitos são aqueles iguais à metade da soma de seus divisores. Ex: 6 = 12/2 e 12 = 1 + 2 + 3 + 6 13
Nenhum primo é perfeito. Resultado: 2 n 1.(2 n 1) é perfeito se 2 n 1 é primo. Outro resultado: Todo número perfeito par possui a forma acima. Ex: 6 = 2 2 1 (2 2 1) O que não se sabe: se existem números perfeitos ímpares. Pergunta: Quais são os números de Mersenne primos? Exemplos: quando n = 2,3,5,7,13,17,19,31,61... Observe que os expoentes são todos primos, mas nem todos primos fazem parte dessa lista. Por exemplo, M(11) = 2047 = 23.89 5.3 Fórmulas exponenciais: números de Fermat Números de Fermat são aqueles da forma: onde n é um inteiro não negativo. F(n) = 2 2n + 1 Exemplos de números de Fermat primos: n = 0,1,2,3,4. F(5) = 18446744073709551617 é composto! Poucos primos de Fermat são conhecidos.até hoje, não se descobriu nenhum F(n) primo com n 5. 5.4 Fórmulas fatoriais Seja p um primo positivo. Construiremos uma função semelhante ao fatorial, só que apenas os primos são multiplicados. Vamos chamá-la de p #. Ou seja, p # é o produto de todos os primos menores ou iguais a p. Ex: 5 # = 2.3.5 = 30 Observe que se p e q são primos sucessivos, então p # = q #.p Estaremos interessados nos números da forma p # + 1. Embora p # + 1 nem sempre seja primo (Ex. 13 # + 1 = 30031 = 59.509), podemos mostrar que não tem nenhum fator primo menor ou igual a p. Desta forma, temos um algoritmo para calcular primo. Pergunta: qual é o problema de tal algoritmo? Observação final: p # + 1 quase nunca é primo! 14
5.5 Infinidade de primos Teorema 8 Existem uma infinidade de primos Prova. Digamos que exista uma quantidade finita de primos: {p 1,p 2,...,p k } Podemos supor que esses primos estão ordenados, de modo que p k é o maior deles. Considere o número p # k +1. Como vimos, esse número possui fator primo maior que p k. ABSURDO! 5.6 Crivo de Eratóstenes O crivo de Eratóstenes é o mais antigo dos métodos para encontrar primos. Etapa 1: Listamos os números ímpares de 3 a n. Etapa 2: Procure o primeiro número k da lista. Risque os demais números da lista, de k em k. Etapa 3: Repita a etapa 2 até chegar em n. Observações: 1. Podemos parar em n... 2. Podemos começara riscar a partir de k 2... 5.7 Crivo de Eratóstenes revisado Etapa 1: Crie um vetor v de n 1 2 posições, preenchidas com o valor 1; faça P = 3. Etapa 2: Se P 2 > n, escreva os números 2j + 1 para os quais a j-ésima entrada de v é 1 e pare; Etapa 3: Se a posição à Etapa 2. (P 1) 2 de v está preenchida com 0 incremente P de 2 e volte Etapa 4: Atribua o valor P 2 a uma nova variável T; substitua por zero o valor da (T 1) posição 2 e incremente T de 2P; repita até que T > n; incremente P de 2 e volte à Etapa 2. 15
5.8 Exercícios propostos 1. Entenda e implemente o algoritmo da pag 65 do livro texto. 2. Livro texto: 1, 3 a 7, 8 e 10. 6 Aritmética modular Aritmética modular = aritmética dos fenômenos cíclicos. Exemplos: Horas, dias do mês, letras do alfabeto, etc. 6.1 Relações de equivalência Seja X um conjunto e uma relação entre elementos de X. Dizemos que é uma relação de equivalência se, para todos x,y,z X : Reflexiva x x. Simétrica Se x y então y x. Transitiva Se x y e y z então x z. Exemplos: < nos inteiros não satisfaz reflexividade; nos inteiros satisfaz reflexividade, mas não satisfaz simetria; é reflexiva, simétrica mas não transitiva; relação de equivalência: = nos números inteiros. Relações de equivalência: são usadas para classificar os elementos de um conjunto em subconjuntos com propriedades semelhantes. As subdivisões de um conjunto produzidas por uma relação de equivalência são conhecidas como classes de equivalência. Formalmente, seja X um conjunto e uma r.e. definida em X. Se x X então a classe de equivalência de x é o conjunto de elementos de X que são equivalentes a x por. Denotamos: Propriedades: x = {y X : y x}. Qualquer elemento de uma classe de equivalência é um representante de toda a classe. 16
X é a união de todas as classes de equivalência. Duas classes de equivalência distintas não podem ter um elemento em comum. O conjunto das classes de equivalência de em X é chamado de conjunto quociente de X por. Observe que os elementos do conjunto quociente são subconjuntos de X. Isto é, o conjunto quociente não é um subcojunto de X, mas um subconjunto das partes de X. 6.2 Inteiros módulo n Vamos construir uma relação de equivalência no conjunto dos inteiros. Digamos que, pulando de n em n, todos os inteiros são equivalentes. Ou melhor: dois inteiros cuja diferença é um múltiplo de n são equivalentes. Formalmente, dizemos que dois inteiros a e b são congruentes módulo n se a b é múltiplo de n. Escrevemos: a b (mod n) Exemplos: 10 0 (mod 5) 23 1 (mod 11) Observação: Congruência módulo n é uma relação de equivalência: a a (mod n) (trivialmente) Se a b (mod n), então a b é múltiplo de n. Mas b a = (a b); logo, b a também é múltiplo de n. Portanto b a (mod n). Transitividade: exercício. Chamamos de Z n o conjunto de inteiros módulo n. Ou seja, se a Z, então a = {a + kn k Z} Em particular, 0 é o conjunto dos múltiplos de n. Voltemos agora ao algoritmo da divisão de Euclides. Vimos que, dados a e n inteiros positivos, a > n, existem inteiros q e r tais que a = n.q + r o r n 1 Ou seja, a r 0 (mod n) e portanto a r (mod n). Em outras palavras,. Z n = {0,1,...,n 1} 17
6.3 Artimética modular Sejam a e b classes de Z n. Então, a + b = a + b Exemplo: Logo, 5 + 4 9 1 (mod 8) 5 + 4 = 9 = 1 A diferença entre duas classes é definida de maneira análoga. A fórmula para a multiplicação das classes a e b de Z n é: a.b = a.b Propriedades da adição: A1 (a + b) + c = a + (b + c). A2 a + b = b + a. A3 a + 0 = a. A4 a + a = 0. Propriedades da multiplicação: M1 (a.b).c = a.(b.c). M2 a.b = b.a. M3 a.1 = a. AM a.(b + c) = a.b + a.c. Exemplo: em Z 6, 2.3 = 6 = 0!!! 6.4 Critérios de divisibilidade Divisibilidade por 3: 3 a se a soma de todos os algarismos de a é divisível por 3. Prova Seja a = a n.a n 1...a 1.a 0 = a n.10 n + a n 1.10 n 1 +... + a 1.10 + a 0 18
Como 10 1 (mod 3), a a n + a n 1 +... + a 1 + a 0 (mod 3) Logo, a 0 (mod 3) se e somente se a n + a n 1 +... + a 1 + a 0 0 (mod 3) Observe que podemos usar o mesmo argumento para provar que um número inteiro é divisível por 9 se a soma de seus algarismos é divisível por 9 (10 1 (mod 9)). Divisibilidade por 11: 11 a se a soma alternada de todos os algarismos de a é divisível por 11. Prova Observe que 10 1 (mod 11). Portanto, 10 k ( 1) k (mod 11) é igual a 1 ou -1 dependendo da paridade de k. Logo, a ( 1) n.a n + ( 1 n 1 ).a n 1 +... + a 2 a 1 + a 0 (mod 11) 6.5 Potências A aplicação mais importante de congruências no nosso curso é no cálculo de resto da divisão de uma potência por um número qualquer. Vamos ilustrar como isso é feito na prática através de um exemplo. Suponhamos que o objetivo seja calcular 35 15 (mod 20) Em primeiro lugar, escrevemos o expoente 15 na base 2: Logo, 15 = 2 3 + 2 2 + 2 + 1 35 15 = 35 23 +2 2 +2+1 = 35.35 2.35 22.35 23 = 35.(35) 2.(35 2 ) 2.((35 2 ) 2 ) 2 Como 35 15 (mod 20), 15 2 5 (mod 20) e 5 2 5 (mod 20), temos: 35 15 = 35.35 2.35 22.35 23 15.(15) 2.(35 2 ) 2.((35 2 ) 2 ) 2 (mod 20) 15.5.(5) 2.((35 2 ) 2 ) 2 (mod 20) 15.5.5.(5) 2 (mod 20) 15.5.5.5 (mod 20) 15.5 (mod 20) 15 (mod 20) 19
6.6 Equações diofantinas Uma equação diofantina é uma equação em várias incógnitas com coeficientes inteiros. Por exemplo, x n + y n = z n. Estaremos interessados em encontrar as soluções inteiras dessas equações. É claro que tais equações podem ter infinitas soluçẽs. Por exemplo, x + y = 2. Ou nenhuma, como no caso da equação x 3 117y 3 = 5 É muito fácil ver que isso é verdade através da redução módulo 9. De fato, como 117 é divisível por 9, x 3 117y 3 x 3 5 (mod 9) Logo, se a equação acima tivesse solução, deveríamos ter x 3 5 (mod 9). classes módulo 9: 0 1 2 3 4 5 6 7 8 Mas: Ou seja, x cubos módulo 9: 0 1 8 0 1 8 0 1 8 3 5 (mod 9) não tem solução. 6.7 Divisão modular Teorema 9 (Teorema da inversão) A classe a tem inverso em Z n se e somente se a e n são primos entre si. Prova ( ) Suponha que a tem inverso. Então existe b tal que Logo, e portanto mdc(a, n) = 1. a.b 1 (mod n) a.b + k.n = 1 ( ) Suponha mdc(a,n) = 1. Logo existem α e β tais que: Ou seja, e portanto a tem inverso em Z n. α.a + β.n = 1 α.a 1 (mod n) O conjunto dos elementos de Z n que têm inverso é muito importante. Vamos denotá-lo por U(n). Em outras palavras, U(n) = {a Z(n) mdc(a,n) = 1} 20
No caso de n = p ser primo, U(p) = Z(n) \ {0} Uma propriedade importante de U(n) é que esse conjunto é fechado com relação à multiplicação. Em outras palavras, o produto de dois elementos de U(n) é um elemento de U(n). Em particular, podemos dividir a por b em Z(n) somente se b U(n); nesse caso, b 1 também pertencerá a U(n) e a b a.b 1 (mod n). Podemos utilizar o que aprendemos para resolver congruências lineares em Z(n). Uma congruência linear é uma equação do tipo: a.x b (mod n) onde a,b Z. A solução dessa equação é: onde α é o inverso de a módulo n. x α.b (mod n) Conclusão: Se mdc(a,n) = 1 então a congruência linear a.x b (mod n) tem uma e só uma solução em Z n. 6.8 Exercícios propostos 4, 5, 6(b), 7, 10 e 11 7 Primeira Prova de Álgebra A Questão 1 - a) Calcule d = mdc(252,198). b) Encontre dois números inteiros a e b tais que: a.252 + b.198 = d (1) Resolução: 252=198+54 54=252-198 198=3.54+36 36=198-3.54 =198-3.(252-198) =-3.252+4.198 54=36+18 18=54-36 =252-198-(-3.252+4.198) =4.252+(-5).198 Deste modo, mdc(252,198) = 18 e a = 4,b = 5 21
Questão 2 - Verifique se as proposições abaixo são verdadeiras ou falsas. Dê uma demonstração (= justificativa clara e bem escrita) ou um contra-exemplo para justificar a sua conclusão. (a) Se p é um número primo, então p é um número irracional. (b) Se um número inteiro A se escreve em base 8 na forma a n a n 1...a 1 a 0, com 0 a i 7, então 2 A se e somente se a 0 = 0. (c) Se p > 3 é um número primo e p a( (mod 3)), então mdc(a,3) = 1. (d) Todo número inteiro representável com três algarismos iguais na base 10 é divisível por 37. (e) Se x e y são inteiros ímpares, então x 2 + y 2 = p 2 para algum primo p. Resolução: a) V- Suponha que existam a,b ℵ tais que p = a b. Podemos supor mdc(a,b) = 1. Logo, p.b 2 = a 2 e portanto p a 2. Pela propriedade fundamental dos primos, p a. Logo, existe c ℵ tal que a = pc. p.b 2 = p 2.c 2 = b 2 = p.c 2 = p b 2 = p b Mas isso é um absurdo uma vez que estamos supondo mdc(a,b) = 1. b) F - Seja A = a n a n 1...a 1 a 0 um número na base 8. Então 2 A se e somente se A 0 (mod 2). Observe que A = a n.8 n +... + a 1.8 + a 0 a 0 (mod 2) ou seja, 2 A se e somente se 2 a 0. Deste modo, 2 A se e somente se a 0 {0,2,4,6}. c) V - Se p a (mod 3), então o resto da divisão de p e a por 3 é o mesmo. Como p é primo, p > 3, temos que p 1 (mod 3) ou p 2 (mod 3) Logo, a 1 (mod 3) ou a 2 (mod 3), ou seja, a = 3n + k, com k = 1,2 Pelo algoritmo euclideano, mdc(a, 3) = mdc(k, 3) = 1 para k = 1, 2. 22
d) V - Seja n = aaa = a(111). Como 111 = 3.37, aaa a(111) 0 (mod 37) e) F - Se x e y são ímpares, então existem n e m tais que Logo, x = 2n + 1, y = 2m + 1 x 2 + y 2 = 4n 2 + 4n + 1 + 4m 2 + 4m + 1 = 2(2n 2 + 2n + 2m 2 + 2m + 1) = 2k onde k é um número ímpar. Logo não existe p ℵ tal que x 2 + y 2 = p 2 Observe que p não precisa ser primo: vale para qualquer número natural. Questão 3 - Resolva um (e apenas um) dos exercícios abaixo: (a) Seja p um número primo. Mostre que um inteiro positivo a é o seu próprio inverso módulo p (ou seja, a 2 1 (mod p)) se e somente se a 1 (mod p) ou a 1 (mod p). (b) Calcule 12 35 (mod 23). Resolução: a) (= ) Suponhamos a 2 1 (mod p). Logo, (a 2 1) 0 (mod p) = p (a + 1)(a 1) Pela propriedade fundamental dos primos, p (a + 1) ou p (a 1). Logo, ( =) Trivial! a 1 (mod p) ou a 1 (mod p) b) Observe que 35 = 2 5 + 2 + 1. Logo, 12 35 12 25.12 2.12 2.6.12 2.3 6 (mod 23) 23
8 Indução e Fermat 8.1 Indução finita Seja P(n) uma proposição que afirma que uma determinada propriedade vale para cada número natural n. Por exemplo: Se p é um número primo, então n p n é divisível por p para todo natural n. A soma de 1 até n é n(n+1) 2 Para provar P(n), em geral usamos o princípio da indução finita : Princípio da indução finita Para que uma proposição P(n) seja verdadeira para todo n natural, basta que: 1. P(1) seja verdadeira. 2. Se P(k) for verdadeira para algum número natural k, então P(k + 1) também é verdadeira. 8.2 Pequeno teorema de Fermat Lema 10 Seja p um número primo e a,b inteiros. Então, (a + b) p a p + b p (mod p) Prova Veja livro texto, pag 94. Teorema 11 (Teorema de Fermat) Seja p um número primo e a um número inteiro. Então a p a (mod p). Prova Se n = 1, então 1 p 1 (mod p) trivialmente. Suponhamos que n p n (mod p) para algum n inteiro positivo. Usando o lema anterior, (n + 1) p n p + 1 p n p + 1 (mod p) Como pela hipótese de indução temos n p n (mod p), Como queríamos demonstrar. (n + 1) p n p + 1 n + 1 (mod p) 24
Caso geral: veja pag 95 do livro texto. Teorema 12 (Teorema de Fermat II) Seja p um número primo e a um inteiro que não é divisível por p. Então, a p 1 1 (mod p). Prova Como mdc(a,p) = 1, existe a tal que aa 1 (mod p) Multiplicando ambos os membros de a p a a.a.a p 1 a.a (mod p). por a, obtemos: (mod p). Logo, a p 1 1 (mod p). Podemos simplificar algumas contas usando o Teorema de Fermat. De fato, sejam p primo, a inteiro tal que mdc(a,p) = 1 e k um número inteiro tal que k p 1. Dividindo k por p 1, k = (p 1).q + r 0 r < (p 1) Logo, Mas (a p 1 ) 1 a k a (p 1).q+r (a p 1 ) q.a r (mod p) e portanto (mod p). a k a r (mod p). 8.3 Exercícios propostos 1,3,46,7,8,12 9 Pseudoprimos Nesta seção, veremos com usar o pequeno teorema de Fermat para identificar que um número é composto sem fatorá-lo. 25
9.1 Pseudoprimos De acordo com o teorema de Fermat, se p é primo e a é um inteiro qualquer, então a p a (mod p). Desta forma, é claro que, se n é um número composto, então existe um inteiro b tal que b n \ b (mod n) (usaremos o símbolo \ para significar não equivalente). Observe que, na prática, só precisamos considerar os inteiros b no intervalo 1 < b < n 1 (por que?). Desta forma, temos um método para determinar se um número é composto sem termos que fatorá-lo: Teste Se n,b são números inteiros, n > 0 e 1 < b < n 1, tais que b n 1 \ 1 (mod n), então n é composto. A pergunta que surge então é: o teste acima é um procedimento de decisão? Isto é, o fato de não encontrarmos tal b significa que n é primo? Resposta: Observe que, se n é composto, então existe p primo, 1 < p < n 1 tal que p n. Logo, mdc(p,n) = p 1 e portanto p não é inversível módulo n. Desta forma, p n 1 \ 1 (mod n). É claro que esse não é um método eficiente para testar primalidade uma vez que é um método de exaustão. Outra pergunta interessante que surge é a seguinte: será que, se um número ímpar n que satisfaça: b n 1 1 (mod n) para algum 1 < b < n 1 é primo? Infelizmente, a resposta é não. Por exemplo, 2 340 1 (mod 341) mas 341 = 11.31 não é primo! Esses falsos primos são conhecidos como pseudoprimos. Ou seja, um pseudoprimo n para a base b é um número inteiro positivo ímpar e composto tal que b n 1 1 (mod n) Apesar de às vezes dar errado, esse teste (chamado de teste de Leibniz) é muito útil. Tambeém é possível melhorar o resultado do teste se testarmos para duas bases. Exemplo 6 Existem 50.847.534 primos entre 1 e 10 9 ; existem apenas 5597 pseudoprimos na base 2 e 1272 pseudoprimos para as bases 2 e 3. 9.2 Números de Carmichael Como vimos anteriormente, não existem números que sejam pseudoprimos para todas as bases. Entretanto, pode ocorrer que um número composto n seja pseudoprimo para todas as bases b tais que mdc(b,n) = 1. Dizemos que um número composto ímpar é um número de Carmichael se b n b (mod n). 26
Os números de Carmichael possuem duas propriedades muito interessantes, dadas pelo teorema baixo: Teorema 13 (Teorema de Korselt:) Um inteiro positivo ímpar n é um número de Carmichael se, e somente se, cada fator primo p de n satisfaz as seguintes condições: 1. p 2 não divide n; 2. p 1 divide n 1. Prova (= ) Seja p um fator primo de n. Então, b n b (mod p) De fato, se b é divisível por p então ambos os membros da equivalência são congruentes a zero. Se não, pelo teorema de Fermat temos: b p 1 1 (mod p) Pela condição (2) do teorema, n 1 = (p 1).q para algum q. Logo, b n (b p 1 ) q.b b (mod p) Por (1), temos que n = p 1...p k com p 1 < p 2 <... < p k. Como os primos são distintos, b n b é divisível pelo produto p 1.p 2...p k = n. Em outras palavras, b n b (mod n) e portanto n é um número de Carmichael. ( =) Seja n um número de Carmichael e suponhamos que exista p primo tal que p 2 n. Escolha b = p. Então: p n p = p(p n 1 1) Mas p não divide p n 1 1, logo p 2 não pode dividir p n p. Portanto, n não pode dividir p n p. Em outras palavras, p p (mod n). Absurdo. O restante da demonstração depende do teorema da raiz primitiva, que só será vista no capítulo 10... Observações: Para verificar que um número é de Carmichael usando o teorema acima necessitamos fatorá-lo... Muitos números de Carmichael possuem fatores primos pequenos! Existem infinitos números de Carmichael. Entre 1 e 10 9 existem 50.847.534 primos e 646 números de Carmichael. 27
9.3 Teste de Miller Teorema de Fermat: detecta números compostos com uma certa eficiência, mas não é um bom teste de primalidade. Teste de Miller: Calcula-se a sequência de potências módulo n: onde n 1 = 2 k q. O fato é que, se n é primo, então: b q,b 2q,...,b 2k q b 2kq b n 1 1 (mod n) Digamos que j é o menor expoente tal que b 2jq 1 (mod n). Se j 1 podemos escrever b 2jq 1 = (b 2j 1q 1)(b 2j 1q + 1) Se n é primo e divide b 2jq 1, então n deve dividir (b 2j 1q +1) pela minimalidade de j. Logo, b 2j 1q 1 1 (mod n) Ou seja, uma das potências b q,b 2q,...,b 2k q deve ser congruente a 1 módulo n. Se j = 0, então temos apenas que b q 1 (mod n). Se nada disso acontecer, então n deve ser composto. Teste de Miller. Etapa 1 Divida n 1 por 2 até encontrar q ímpar e k tais que n 1 = 2 k q. Etapa 2 Faça i = 0 e r = resto de b q por n. Etapa 3 Se i = 0 e r = 1 ou i 0 e r = n 1: teste inconclusivo. Etapa 4 Faça i = i + 1 e r = r 2 onde r 2 é o resto da divisão de r 2 por n. Etapa 5 Se i < k volte à etapa 3; senão: n é composto. Exemplo 7 Tome o número de Carmichael 561. Temos que 560 = 2 4.35. Calculando as sequências de restos módulo 561 das potências de 2: expoentes 35 2.35 2 2.35 2 3.35 restos 263 166 67 1 28
Logo 561 tem que ser composto. Se um número composto n tem resultado inconclusivo para o teste de Miller com respeito a uma base b, dizemos que n é um pseudoprimo forte para a base b. Observe que pseudoprimo forte pseudoprimo. Existem 1282 pseudoprimos fortes entre 1 e 10 9. 9.4 Primalidade e computação algébrica É importante ressaltar que o teste de Miller é muito usado na prática. O que se faz para ter maior garantia do resultado é fazer o teste para diversas bases. É assim com o Maple, ScratchPad - IBM, Axiom 1.1 - IBM. Vale a observação: dado um número finito qualquer de bases, existem infinitos números de Carmichael que são pseudoprimos fortes para todas essas bases. 9.5 Exercícios propostos 2,5,7,8,10 10 Teorema de Euler O pequeno teorema de Fermat nos diz como trabalhar com certas congruências envolvendo expoentes quando o módulo é primo. Nessa seção, veremos como lidar com congruências módulo um número composto. 10.1 Função de Euler Definição. Seja n um inteiro positivo. A função de Euler φ(n) é definida como o número de inteiros positivos não excedendo n que são relativamente primos com n. A tabela abaixo apresenta os valores de φ(n) para 1 n 12. n 1 2 3 4 5 6 7 8 9 10 11 12 φ(n) 1 1 2 2 4 2 6 4 6 4 10 4 Na seção de aritmética modular, estudamos o conjunto U(n), o conjunto dos elementos de Zscr n que têm inverso. Vimos que U(n) = {a Z n : mdc(a,n) = 1} 29
Desta forma, φ(n) nada mais é do que o número de elementos de U(n). Vamos ver como calcular φ(n). Começamos com alguns casos especiais. Seja p um número primo. Então todos os inteiros positivos menores que p são primos com p. Logo φ(p) = p 1 Também é fácil calcular φ(p k ). Observe que mdc(a,p k ) = 1 se e somente se p não divide a. Então basta contar os inteiros menores que p k que não são divisíveis por p. Se 0 a < p k é divisível por p, então a = p.b onde 0 b < p k 1 Portanto há p k 1 inteiros positivos menores que p k que são divisíveis por p. Logo há p k p k 1 que não são divisíveis por p. Ou seja, φ(p k ) = p k 1 (p 1) Para obtermos a fórmula geral, é necessário provar o seguinte resultado: Teorema. Se m,n são inteiros positivos tais que mdc(m,n) = 1, então φ(mn) = φ(m).φ(n) A demonstração desse teorema é trabalhosa (mas não difícil) e portanto não faremos aqui. Exemplo 8 φ(100) = φ(2 2 ).φ(5 2 ) = (2.1).(5.4) = 40 Pelo teorema acima temos que, se n = p e1 1...pe k k, então, 10.2 Teorema de Euler φ(n) = p e1 1 1...p e k 1 k (p 1 1)...(p k 1) Vai ser necessário, para decodificação de mensagens, saber calcular a função de Euler. Também vamos ter que aplicar o teorema de Euler. O teorema de Euler é uma generalização do teorema de Fermat para o caso em que o módulo não é primo: Teorema de Euler. Se n é um inteiro positivo e a é um inteiro tal que mdc(a, n) = 1, então a φ(n) 1 (mod n) Antes de provar esse teorema, vamos apresentar um exemplo. 30
Exemplo 9 Temos que U(8) = {1,3,5,7} e portanto φ(8) = 4. Observe que, se a,b,c U(8), então a.b U(8) e, se c b, então a.b\ a.c (por que?) Para ver como isso funciona, tome a = 3. Então, Logo, e portanto, 3.1 3 (mod 8) 3.3 1 (mod 8) 3.5 7 (mod 8) 3.7 5 (mod 8) (3.1).(3.3).(3.5).(3.7) 1.3.5.7 (mod 8) 3 4.1.3.5.7 1.3.5.7 (mod 8) Como mdc(1.3.5.7,8) = 1, podemos cortar o termo comum dos dois lados da equivalência: 3 4 1 (mod 8) Teorema 14 (Teorema de Euler) Se n é um inteiro positivo e a um inteiro tal que mdc(n,a) = 1, então a φ(n) 1 (mod n) Prova Escrevendo U(n) = {b 1,...,b φ(n) }, temos que: Logo, (a.b 1 )...(a.b φ(n) ) b 1...b φ(n) (mod n) a φ(n).b 1...b φ(n) b 1...b φ(n) (mod n) Como mdc(b 1...b φ(n),n) = 1, podemos cortar o termo comum dos dois lados e portanto, a φ(n) 1 (mod n) 10.3 Exercícios propostos Capítulo 8: 4,6,8,9,10,18 31
10.4 Tabela Hashing Uma universidade deseja estocar um arquivo para cada um de seus estudantes no seu computador. O número identificador, ou chave para cada arquivo é o número do CPF do estudante. O CPF é um inteiro de 11 dígitos, portanto é praticamente impossível reservar uma posição de memória para cada CPF possível. Deve-se encontrar um método sistemático para arranjar esses arquivos na memória, usando um número razoável de posições de memória. De outra forma, ficaria impossível acessar os arquivos... Um desses métodos é utilizando a tabela hashing, baseada em funções hashing. Existem várias propostas para funções hashing. Vamos discutir (brevemente) o tipo mais utilizado. Seja k a chave do arquivo a ser estocado e seja n um inteiro positivo. Definimos a função hashing h(k) por h(k) k (mod n) onde 0 h(k) < n. É claro que devemos escolher um n adequado de modo que os arquivos fiquem distribuídos de uma maneira razoável entre as n posições possíveis de memória. Por exemplo, n não deve ser uma potência de 10 (10 r ) simplesmente porque o valor da função h seria os r últimos dígitos da chave. Outro exemplo de uma escolha ruim é quando n 10 m ± a onde a e m são pequenos. Por exemplo, se n = 111 (10 3 1) = 999 então 10 3 1 (mod n) e portanto os números: vão para a mesma posição de memória. 64121284868 e 64184821268 Para evitar esses problemas, n deve ser um número primo próximo do número de posições disponíveis. Por exemplo, se existem 5000 posições de memória para o armazenamento de 2000 arquivos de estudantes, podemos escolher n = 4969. Claro que, mesmo assim, colisões podem ocorrer. Existem várias heurísticas para tratamento de colisões. O método mais usado é o de escolher uma posição livre. Existem várias maneiras de fazer isso e as mais complicadas são as mais eficientes. Eu poderia passar o dia falando sobre elas, mas vou citar apenas uma, a mais simples. Consiste em tomar: h j (k) h(k) + j (mod n) Desta forma, a chave k é alocada na posição mais próxima possível de h(k). A eficiência desse método é realmente baixa, pois tende a haver um engarrafamento. Na prática, o mais fácil é atachar uma lista a cada posição de memória. Dessa forma, procede-se por busca sequencial. 32
11 Criptografia RSA 11.1 Pré-codificação Em primeiro lugar, devemos converter a mensagem em uma sequência de números. Essa primeira etapa é chamada de pré-codificação. Há várias maneiras de se fazer isso. Aqui vamos supor que o texto não contém acentuação, pontuação, números etc, apenas as letras A a Z (maiúsculas). Também vamos adicionar espaços em branco entre palavras, que será substituído pelo número 99. A letra A será convertida no número 10, B será 11 e assim por diante, até o Z correspondendo ao número 35. Observe que cada letra corresponde a um número com exatamente dois algarismos. Isso evita ambiguidades. A chave pública é um número n = p.q, onde p e q são primos. Antes de começar devemos, então escolher esses números. O último passo da pré-codificação é quebrar a mensagem em blocos. Esses blocos devem ser números menores que n. A maneira de escolher os blocos não é única, mas é importante evitar duas situações: Nenhum bloco deve começar com o número 0 (problemas na decodificação). Os blocos não devem corresponder a nenhuma unidade linguística (palavra, letra, etc). Assim a decodificação por contagem de frequência fica impossível. 11.2 Codificando e decodificando Para codificar a mensagem precisamos de n = p.q e de um inteiro positivo e que seja inversível módulo φ(n). Em outras palavras, mdc(e,φ(n)) = mdc(e,(p 1).(q 1)) = 1 Chamaremos o par (n,e) a chave de codificação do sistema RSA. Codificaremos cada bloco de mensagem separadamente e a mensagem codificada será a sequência de blocos codificados. Importante: Os blocos já codificados não poderão ser reunidos de modo a formar um longo número. Isso tornaria a decodificação impossível! Vamos agora mostrar como codificar cada bloco b. Chamaremos o bloco codificado de C(b). Em primeiro lugar, lembre-se que b é menor que n. Então: Onde 0 C(b) < n. C(b) b e (mod n) 33
Exemplo 10 Considere a frase Paraty é linda. Convertendo em números, 2510271029349914992118231310 Agora devemos escolher n. Vamos começar com um número pequeno, por exemplo n = 11.13 = 143 Podemos então quebrar a mensagem acima em blocos, que devem ter valor menor que 143: 25 102 7 102 93 49 91 49 92 118 23 13 10 Então temos que φ(143) = 10.12 = 120 e portanto e deve ser um número que não divide 120. O menor valor possível é 7. Logo, C(25) 25 7 25 22.25 2.25 (mod 143) 25 22.53.25 (mod 143) 53 2.53.25 (mod 143) 92.53.25 (mod 143) 14.25 (mod 143) 64 (mod 143) Procedendo dessa maneira com todos os blocos, obtemos a seguinte mensagem cifrada: 64 119 6 119 102 36 130 36 27 79 23 117 10 Vejamos agora como proceder para decodificar um bloco de mensagem codificada. A informação que precisamos para decodificar está contida no par (n,d), onde d é o inverso de e módulo φ(n). Chamaremos (n,d) de chave de decodificação e de D(c) o resultado do processo de decodificação. D(c) é dado por: D(c) c d (mod n) onde 0 D(c) < n. Observe que é muito fácil calcular d, desde que φ(n) e e sejam conhecidos: basta aplicar o algoritmo euclideano estendido. Entretanto, se não conhecemos p e q é praticamente impossível calcular d. Voltando ao nosso exemplo, temos que n = 143 e e = 7. Para calcular d, usamos o algoritmo euclideano estendido: 120 = 7.17 + 1 = 1 = 120 + ( 17).7 Logo o inverso de 7 módulo 120 é 17. Como d deve ser usado como um expoente, precisamos que d seja positivo. Logo tomamos d = 120 117 = 103. 34
11.3 Funciona? A pergunta óbvia que surge agora é: D(C(b)) = b? Ou seja, decodificando um bloco de mensagem codificada, encontramos um bloco da mensagem original? Porque senão todo nosso esforço foi sem sentido... Vamos mostrar nessa seção que a resposta para a pergunta acima é sim. Consideremos então n = p.q. Vamos provar que DC(b) b (mod n) E por que não a igualdade? Observe que DC(b) e b são menores que n 1. Por isso escolhemos b menor que n e mantivemos os blocos separados depois da codificação! Por definição, temos que DC(b) (b e ) d b e.d (mod n) Mas d é o inverso de e módulo φ(n). Logo existe inteiro k tal que ed = 1+kφ(n). Logo, b ed b 1+kφ(n) (b φ(n) ) k.b (mod n) Se mdc(b,n) = 1, então podemos usar o teorema de Euler: b ed (b φ(n) ) k.b b (mod n) Se b e n não são primos entre si, obderve que n = p.q, p e q primos distintos. Logo, b ed b 1+kφ(n) (b (p 1) ) k.(q 1).b (mod p) Se mdc(b,p) = 1, então podemos usar o teorema de Fermat (b p 1 1 Se não, temos que p b e portanto Logo, qualquer que seja b. b ed b 0 (mod p) b ed b (mod p) Fazemos o mesmo para o primo q, obtendo: b ed b (mod q) (mod p)). Portanto, como queríamos. b ed b (mod p.q) 35
11.4 Porque o RSA é seguro Como já vimos, o par de codificação (n,e) é conhecido e acessível a qualquer usuário. O RSA só é seguro se for difícil calcular d quando apenas esse par é conhecido. Observe que só sabemos calcular d se soubermos o valor de φ(n), cujo cálculo depende da fatoração de n. A pergunta que surge então é: será que não existe outro processo para calcular d e φ(n)? Por exemplo, o que aconteceria se alguém inventasse um método para calcular φ(n) a partir de n e e? A resposta é que teríamos, então, um algoritmo rápido de fatoração. Observe que φ(n) = (p 1).(q 1) = pq (p + q) + 1 = n (p + q) + 1 Logo, (p + q) = n φ(n) + 1 é conhecido. Contudo, Logo, (p + q) 2 4n = (p 2 + q 2 + 2pq) 4pq = (p q) 2 p q = (p + q) 2 4n que também é conhecido. Ou seja, conhecemos p+q e p q. Portanto conhecemos p e q e fatoramos n! Deste modo, conhecer φ(n) sem fatorar n significa que, na verdade, sabemos fatorar n! Outro jeito de quebrar o RSA seria achar um algoritmo que calcule d diretamente a partir de n e e. Como ed 1 (mod φ(n)), isto implica que conhecemos um múltiplo de φ(n). Isso também é suficiente para fatorar n (prova complicada). A última alternativa seria achar b a partir da forma reduzida de b e módulo n sem achar d. Bom, ninguém conseguiu fazer isso até agora... Acredita-se que quebrar o RSA e fatorar n sejam problemas equivalentes, apesar disso não ter sido demonstrado. 11.5 Escolhendo primos Suponha que desejamos implementar o RSA de chave pública (n,e), de modo que n seja um inteiro com aproximadamente r algarismos. Para construir n, escolha um primo p entre 4r 10 e 45r 10r 100 algarismos e, em seguida, escolha q próximo de p. O tamanho da chave recomendado atualmente para uso pessoal é de 768 bits. Isso significa que n terá aproximadamente 231 algarismos. Para construir tal número precisamos de dois primos de, digamos, 104 e 127 algarismos respectivamente. Outra coisa a ser observada é que os números p 1,q 1,p+1,p 1 não tenham fatores primos pequenos, pois senão seria fácil fatorar n. Para encontrar p e q, seguiremos a seguinte estratégia: 1. Tome um número s ímpar. 36
2. Verifique se n é divisível por um primo menor que 5.000. 3. Aplique o teste de Miller a s usando como base os 10 primeiros primos. Encontrar tais primos pode ser um processo trabalhoso. Por exemplo, se x é um número da ordem de 10 1 27, no intervalo entre x e x + 10 4 existem aproximadamente 34 primos dentre 560 números que passam a etapa (1) da estratégia acima... 11.6 Assinaturas Apenas codificar mensagens não basta, em geral, pois o sistema é de chave pública. Ou seja, qualquer pessoa pode codificar uma mensagem usando uma chave alheia. Por exemplo, um haker poderia facilmente mandar instruções ao banco para que o seu saldo bancário fosse transferido para uma outra conta. Por isso, o banco precisa de uma garantia de que a mensagem teve origem em um usuário autorizado. Ou seja, a mensagem tem que ser assinada. Vamos chamar de C m e D m as funções de codificação e decodificação do Mário e de C a e D a as funções de codificação e decodificação do Allan. Seja b um bloco de mensagem que o Mário deseja mandar para o Allan. Para mandar uma mensagem assinada, ao invés de C a (b), o Mário envia C a (D m (b)) Ou seja, primeiro ele decodifica a mensagem como só ele pode fazer, depois ele codifica o resultado, como só o Allan pode ler. Para ler a mensagem, primeiro o Allan aplica D a e depois C m. Observe que C m é público. Se a mensagem fizer sentido, é certo que a origem foi mesmo o Mário! Mas cuidado! Esse sistema pode ser usado para quebrar o RSA, como em 1995 por um consultor em assuntos de segurança de computadores... 11.7 Exercícios propostos Capítulo 11: 1,2,3,4,6. 12 1 o trabalho prático O trabalho tem como objetivo a criação de dois números primos grandes (entre 20 e 30 bits). Para isso: Gere dois números ímpares m e k da magnetude acima, de modo que não sejam muito próximos um do outro. 37
Verifique se m,k são divisíveis por um primo menor que 5.000. Aplique o teste de Miller a m,k usando como base os 10 primeiros primos (se você quiser ter uma certeza maior sobre o resultado, façø teste para mais primos). Depois calcule n = m.k e aplique os algoritmos da fatoração e de Fermat a n para ver se sua chave pública é facilmente quebrada. O trabalho deverá ser entregue no dia 06/08/2002 constar de: (sem falta!) e deverá Parte escrita de no máximo duas páginas digitadas. Essa parte deverá conter os resultados do trabalho juntamente com a análise desses resultados (em especial, se foi fácil quebrar a sua chave ou não). Código impresso comentado. Evitem C + +, por favor! Disquete com o executável do programa. Este também pode ser enviado por e-mail. Lembrem-se que eu posso rodar apenas programas em Delphi (4.0) ou qualquer outra linguagem que rode nas estacoes do DCC. Então evitem artifícios gráficos sofisticados... 13 Raízes primitivas 13.1 Teste de Lucas Para determinar se n é primo, podemos verificar se φ(n) = n 1. Ou seja, se mdc(a,n) = 1 para todo a menor que n. Isso só é possível se n é ímpar. Logo precisamos encontrar um jeito de calcular φ(n) sem fatorar n. Mas já vimos que isso é impossível... Teorema da raiz primitiva. Se p é um primo, existe b Z n tal que b p 1 1 (mod p) mas se r < p 1. b r \ 1 (mod p) Em geral, chamaremos de ordem do elemento b em Z n o número k tal que b k 1 (mod n) e b r \ 1 (mod n) se r < k. Observe que se n é primo e 1 < b < n, então a ordem de b é p 1. 38
Teorema de Lagrange. A ordem de b tem que dividir a ordem de U(n), que é igual a φ(n). Logo, dado n ímpar, se existe b tal que b n 1 1 (mod n) e b t \ 1 (mod n) se t < n 1 então n é primo pois teríamos n 1 φ(n) n 1. De acordo com o teorema da raiz primitiva, se n é primo, tal b sempre existe. Encontrá-lo é uma questão de sorte... Para aplicar isso à primalidade, precisamos encontrar uma maneira eficiente de mostrar que a ordem de um elemento de U(n) é exatamente n 1. Teste de Lucas. Sejam n impar e 1 b n 1. Se e b n 1 1 (mod n) b n 1 p \ 1 (mod n) para cada fator primo de n 1, então n é primo. Demonstração: Veja o livro texto pag 168. Continua... Aguardem! 14 Sistemas de congruências O objetivo dessa seção é estudar a solução de sistemas de equações lineares. A aplicação para criptografia é o desenvolvimento de um método para partilhar senhas. 14.1 Equações lineares Já estudamos o caso de uma equação linear ax b (mod n) Se a possui um inverso α em Z n, então multiplicando ambos os lados da equação acima por α: α(ax) αb (mod n) x αb (mod n) Em particular, se n é primo e a\ 0 tem solução. (mod n), então a equação acima sempre 39
Se a não tem inverso em Z n, então mdc(a,n) = d 1. Logo, a equação: ax ny = b só tem solução quando b é divisível por d. Suponhamos então que d divide b. Escreveremos a = da, b = db e n = dn. Cancelando os d s, chegamos à seguinte equação: Ou seja, a x n y = b a x b (mod n ) Observe que agora mdc(a,n ) = 1, e essa equação sempre tem solução. Exemplo 11 Seja 6x 4 (mod 8). Dividindo pelo mdc(6, 8) = 2, obtemos 3x 2 (mod 4) Logo a solução procurada é: x 2 (mod 4) Mas observe que o módulo mudou de 8 para 4... Para consertar isso, vamos escrever a expressão acima em uma expressão de inteiros: Duas possibilidades: k é par. Nesse caso, x 2 x = 2 + 4k k é ímpar (k = 2m+1). Nesse caso, x 6 (mod 8) e 2 é uma solução. Ou seja, uma equação linear possui mais de uma solução. (mod 8) e 6 é outra solução. 14.2 Um exemplo astronômico Três satélites passarão sobre o Rio essa noite. O primeiro à uma hora, o segundo às 4 horas e o terceiro às 8 horas da manhã. O primeiro leva 13 horas para completar uma volta em torno da terra, o segundo 15 horas e o terceiro 19 horas. Determine quantas horas decorrerão, à partir de meia noite, até que os três satélites passem ao mesmo tempo sobre o Rio. Montagem matemática: seja x é o número de horas, contadas a partir da meia noite de hoje, quando os três satélites passarão juntos sobre o Rio. Então: x 1 (mod 13) x 4 (mod 15) x 8 (mod 19) 40
Podemos re-escrever a primeira equação cmo x = 1 + 13t, Substituindo a primeira equação na segunda, obtemos: t 6 (mod 15) Logo x = 79 + 195u. Substituindo essa equação na terceira: Logo, u 1 (mod 19) x = 79 + 195u = 274 + 3705v Logo os satélites passarão juntos pela primeira vez 274 horas depois da meia noite de hoje. 14.3 Algoritmo chinês do resto Observe que, para resolver o problema dos satélites, resolvemos as duas primeiras equações, obtendo x = 79+195u. Isso corresponde a uma nova equação, x 79 (mod 195). Em geral, a solução de um sistema de muitas equações é obtida através da solução de vários sistemas de duas equações. Desta forma, vamos analisar apenas o algoritmo correspondente á solução de um sistema de duas equações. Considere então o sistema x a (mod m) x b (mod n) Podemos re-escrever a primeira equação na forma: x = a + my Substituindo x na segunda equação, obtemos: my (b a) (mod n) Sabemos que essa equação tem solução se e somente se o mdc(n,m) divide b a. Vamos assumir que mdc(n,m) = 1. Seja então α o inverso de m módulo n. Então: y α(b a) (mod n) y = α(b a) + nz x = a + mα(b a) + mnz x = a(1 mα) + mαb + mnz x = aβn + mαb + mnz Observe que essa solução é única. Temos então o seguinte teorema: 41
Teorema Chinês do resto. Sejam n 1,...,n k inteiros positivos, dois a dois primos entre si. Então o sistema x a 1 (mod n 1 ). x a k (mod n k ) sempre tem uma solução única em Z n1...n k. 14.4 Módulos não co-primos Analisaremos esse caso através de um exemplo. Considere o sistema: x 3 (mod 12) x 19 (mod 8) Da primeira equação, obtemos x = 3 + 12y. Substituindo isso na segunda equação, temos 12y 16 (mod 8). Dividindo essa equação por 4, obtemos 3y 4 (mod 2). Logo, x 3 (mod 24) Observe que 24 é o mmc entre 8 e 12... 14.5 Partilha de senhas Suponha que que desejemos partilhar uma senha s entre n pessoas, de modo que a cada pessoa seja dado um elemento (uma parte) da senha. Esse elemento é tal que é escolhido de um conjunto S de n pares de inteiros positivos de modo que, para um inteiro positivo k n previamente escolhido temos: 1. qualquer subconjunto de S com k elementos permite determinar s facilmente; 2. é muito difícil determinar s conhecendo menos de k elementos de S. Começamos escolhendo um conjunto L de n inteiros positivos, dois a dois primos entre si. Seja N o produto dos k menores números de L e M o produto dos k 1 maiores números de L. Dizemos que esse conjunto tem limiar k se N > s > M Observe que essa condição implica que o produto de k ou mais elementos de L é sempre maior que N e o produto de menos de k elementos é sempre menor que M. O conjunto S será formado pelos pares da forma (m,s m ) onde m L e s m é a forma reduzida de s módulo m. Observe que limiar k 1 implica s > m para qualquer m L. Logo s m < s para qualquer m L. 42
Suponhamos que sejan conhecidos, em um dado momento, t elementos, k. Denotaremos esses pares por (m 1,s 1 ),...,(m t,s t ). Vamos resolver o sistema de congruências: x s 1 (mod m 1 ) x s 2 (mod m 2 )... x s t (mod m t ) obtendo x 0 como solução. Pelo teorema chinês do resto, Por que? Sabemos que, como t k, x 0 s (mod m 1...m t ) m 1...m t N > s Pelo teorema chinês do resto, o sistema acima tem uma única solução menor que m 1...m t. Mas s também é solução do sistema e s < m 1...m t. Logo s = x 0. Observações: 1. É possível escolher os módulos de modo que fique praticamente impossível encontrar s através de uma busca. 2. É sempre possível escolher um conjunto L que satisfaça todas as condições. Exemplo 12 Digamos que em um banco há 5 funcionários e pelo menos 2 têm que estar presentes para que o cofre seja aberto. Logo o conjunto L deve ter 5 elementos, e seu limiar deve ser 2. Uma escolha possível escolhendo apenas primos pequenos é L = {11,13,17,19,23} O valor de s pode ser escolhido como sendo qualquer inteiro no intervalo que vai de 23 a 143. Digamos s = 30. Então: S = {(11,19),(13,17),(17,13),(19,11),(23,7)} Se os funcionários que possuem as senhas (17,13) e (23,7) estão no banco, para obter a senha é preciso resolver o sistema A solução é x = 30 + 391k... x 13 (mod 17) x 7 (mod 23) 14.6 Exercícios propostos 1,2,4 43
15 Lógica e ciência da computação 15.1 Motivação Lógica em ciência da computação: Primeira abordagem computação-como-modelo: computações são estruturas matemáticas contendo nodos, estados e transições e a lógica constrói afirmativas sobre essas estruturas. Segunda abordagem computação-como-dedução: estados são descritos através de um conjunto de proposições e mudanças nos estados são modelados por mudanças nas proposições dentro de uma derivação (ou seja, por passos na construção de uma prova) A primeira abordagem tem sido amplamente estudada e faz uso de tópicos da matemática como teoria de conjuntos, teoria das categorias, álgebras, etc. para modelar computações. Em geral, as estruturas matemáticas utilizadas são complexas porque devem lidar com o conceito de infinitude. A segunda abordagem, apesar de lidar com estruturas mais simples (que raramente fazem referência ao infinito) e de estar mais intimamente ligada à computação, tem merecido pouca ou nenhuma atenção nos últimos tempos. Apenas após recentes pesquisas na área de teoria de provas e programação lógica observou-se um crescimento do estudo nessa área de pesquisa. Lógicas expressivas como lógica linear (e Forum - linguagem de programação baseada em lógica linear) passaram a ser utilizadas para modelar estados, transições de estado e algumas primitivas de concorrência. 15.2 Lógica Clássica A verdade de uma afirmativa é absoluta e independe da quaisquer pensamento, entendimento ou ação. Afirmativas são verdadeiras ou falsas, onde falso é a mesma coisa que não verdadeiro. Isso é conhecido com princípio do meio excluído: p p. 15.3 Lógica Intuicionista Em p p nenhuma informação é dada sobre qual realmente vale: 44
Existem dois números irracionais x e y tais que x y é racional. Existem sete 7s consecutivos na representação decimal do número π. Afirmativas só são válidas perante a existência de uma prova ou construção da afirmativa. Essa lógica é de especial interesse porque suas fórmulas estão em correspondência 1 a 1 com tipos em λ-calculus, base das linguagens de programação funcionais: Lisp, ML, Haskell. Ainda, lógica intuicionista é uma lógica de recursos infinitos (mas não de conclusões infinitas). 15.4 Lógica linear Lógica linear é uma lógica de recursos conscientes. No caso de transição de estados: maior tem valor 1 maior tem valor 2 É claro que a proposição { maior tem valor 1} deve deixar de ser válida no estado 2, enquanto que a proposição { maior tem valor 2}, que não era válida no estado 1, passa a valer no estado 2. Esse tipo de comportamento não pode ser descrito em lógicas clássica ou intuicionista, apenas em lógica linear. 15.5 Linguagens lógicas de programação - Prolog Uma definição comum das cláusulas de Horn é dada de acordo com a seguinte gramática: G ::= A G G D ::= A G A xd Ou seja, fórmulas gol são conjunções de fórmulas atômicas e cláusulas de programas são da forma: x 1... x m [A 1... A n A 0 ] Observe que, como implicação e quantificação universal não estão presentes no gol, todas as hipóteses e termos necessários para completar a prova devem estar presentes desde o início do programa: assinaturas e programas são globais. Ou seja, nada de mecanismos para modularização ou construtores de dados! 45
15.6 Linguagens lógicas de programação - λ-prolog As fórmulas de primeira ordem de Harrop estendem as cláusulas de Horn, uma vez que admitem implicações e quantificadores universais no gol: G ::= A G G P G xg D ::= A G A xd Deste modo, o programa pode crescer ao longo da prova (modularização) e novas constantes podem ser adicionadas ao programa (abstract datatypes) Desvantagem: recursos ilimitados para construção de provas. 15.7 Linguagens lógicas de programação - Forum Lógica linear não é uma linguagem abstrata de programação. Forum é uma linguagem lógica de programação baseada em lógica linear. Σ:Ψ; Γ;Υ possui uma prova em Forum se e somente se! Ψ, Γ,?Υ. Além de modularização e abstração de dados também permite encapsulação de estado, concorrência e primitivas de comunicação e sincronização. Cláusulas em Forum possuem a forma: ȳ(g 1 G m G 0 ), (m 0) onde G 0,...,G m são fórmulas arbitrárias em Forum e denota ou. 16 Álgebra e ciência da computação A principal aplicação de matemática em ciência da computação é na definição de semântica formal em linguagens de programação. Semântica é geralmente definida como o estudo da relação entre palavras e sentenças de uma linguagem (escrita ou falada) e os seus significados. É uma área que tem recebido, através dos tempos, muita atenção em lingüística e filosofia, que estudam o significado de sentenças na linguagem natural. Uma segunda área de estudo de semântica se concentra no significado de sentenças em linguagens formais de lógica matemática, originalmente projetada para servir como fundação da matemática. Esta seção visa discutir, brevemente, tópicos de uma terceira área da semântica: aquela que tem por objetivo desenvolver técnicas para expressar a semântica de linguagens utilizadas para programação de computadores. Estaremos especialmente interessados no uso de estruturas matemáticas tais como grupos, domínios e teoria de categorias na descrição de semântica de linguagens imperativas (como o Pascal) e funcionais (como ML, Haskell). 46
17 Semântica Tradicionalmente, linguagens de computadores têm sido baseadas em uma seqüência de comandos, determinados por sentenças imperativas. Em linguagem natural, tais sentenças são aquelas que podem ser encontradas em um livro de receitas: Bata a clara do ovo até ficar dura. (1) Em contraste, sentenças de lógica matemática visam estabelecer verdades absolutas: Quando batida, a clara do ovo fica dura. (2) Muitas pesquisas em métodos para analisar programas em uma certa linguagem procuram formalizar a relação entre os dois exemplos citados acima. Afinal de contas, a sentença lógica (2) garante que uma pessoa que execute o que manda a sentença imperativa (1) vai ter sucesso em terminar a tarefa de mudar a consistência da clara do ovo. Desta forma, uma maneira de descrever comandos (que são sentenças imperativas) de uma linguagem de programação é estabelecendo uma relação entre o estado do computador antes e depois da execução do comando (como descrito por sentenças lógicas). Essa interpretação relacional de fragmentos de programa pode ser formalizada através da semântica denotacional. Vejamos um exemplo da semântica do comando if. Escreveremos C[ ] para denotação de um comando e E[ ] para denotação de uma expressão. Então temos: C[if E then C 1 else C 2 ] = E[E]λv.isBool v (v C[C 1 ], C[C 2 ]) Da mesma forma, podemos escrever a semântica do comando while como: C[while E do C] = E[E]λv.isBool v (v C[C], C[while E do C]) ou, mais simplesmente, podemos escrever: C[while E do C] = C[C]; C[while E do C]) Antes de falarmos um pouco sobre esse tipo de semântica, vamos responder à uma pergunta fundamental: qual é o objetivo de se estudar semântica de linguagens de programação? Bem, quando essa área surgiu, o objetivo era prover uma descrição suficientemente precisa para tornar possível aos implementadores construir um compilador para a linguagem em questão. Hoje em dia, a ênfase está em: 1. fornecer uma descrição precisa para os programadores, tornando possível que estes façam afirmativas rigorosas sobre o comportamento de programas por eles escritos; 47
2. fornecer ferramentas para os designers de linguagens de programação, para que possam sugerir linguagens melhores, confiáveis e com descrições formais simples. Ou seja, a grande vantagem é que desenvolve-se um método matemático (e portanto formal) que garante corretude tanto de programas quanto da linguagens desenvolvidas. 18 Semântica Denotacional É a semântica que mapeia construtores sintáticos de programas em valores abstratos (números, funções, etc) que eles denotam. Esses mapeamentos são usualmente definidos recursivamente (como no cado do while acima). É claro que alguns cuidados devem ser tomados quando trabalhamos com funções recursivas. Em especial, para modelar o espaço de todas as funções recursivas precisaríamos de um conjunto X que contivesse todo o espaço de funções X X. Por questões de cardinalidade, sabemos que isso é impossível. Para lidar com essa dificuldade, foi proposto, em 1969, um modelo para funções recursivas X X restritas a funções contínuas em X (de acordo com uma certa topologia). Esse modelo, chamado de teoria de domínio, é utilizado para descrever a semântica denotacional do λ-calculus, base de linguagens de programação funcionais. E, utilizando o λ-calculus, podemos facilmente descrever a semântica denotacional de linguagens como o Algol60, base do Pascal. Outro tipo de semântica que tem sido muito estudada é a semântica categórica. As idéias básicas desse tópico (muito em moda atualmente) são elegantes e de fácil entendimento para um aluno da graduação com alguma maturidade na área de Álgebra. 19 Segundo trabalho prático O segundo trabalho prático consiste em implementar o algoritmo RSA. Deve ser apresentado o seguinte: 1. A chave pública (n) criada no TP1, juntamente com o número e tal que mdc(e,φ(n)) = 1. 2. Algoritmo para encontrar d, o inverso de e módulo φ(n). 3. Algoritmos de codificação (incluindo o de partição da mensagem em blocos) e decodificação. 48
4. Teste em um texto de, no mínimo, 20 linhas. O texto, os blocos e o texto cifrado deverão estar contidos no trabalho. Como sempre, é necessário um pequeno texto introdutório de no máximo duas páginas. Dessa vez não vou cobrar os executáveis... 49