Números Primos – algoritmos e aplicações AULA 4 Análise de Algoritmos Pós-graduação em Ciência da Computação e Bacharelado em Ciência da Computação - UFU Profa. Sandra de Amo Primos Definição: Um número natural n é primo se os únicos divisores de p são 1 e p. Problema importante: detectar se um dado número natural n é primo. Algoritmo ‘ingênuo’: Input: um número n de k bits Output: ‘sim’ se n é primo, ‘não’ caso contrário. 1. 2. 3. For i = 2, ... , n/2 Se i divide n pára e retorna ‘não’ Retorna ‘sim’ Qual a complexidade deste algoritmo (em função do TAMANHO DO INPUT n ?) Complexidade Complexidade = O(n) onde n = grandeza do número Precisamos relacionar n com k = tamanho da representação binária de n n = O(2k ). Logo k = O(log2n) Portanto a complexidade do algoritmo ingênuo é O(n) = O(2k ) Algoritmo ingênuo é exponencial no tamanho do input !! Problema: O problema de testar a primalidade de um número n é polinomial ? Isto é, existe algoritmo de complexidade polinomial que resolva este problema ? Primos é polinomial ! Somente em 2003 este problema foi resolvido. Ver artigo: Primes is in P - Manindra Agrawal, Neeraj Kayal, Nitin Saxena. Annals of Mathematics, 160 (2004), pp. 781-793. Um primeiro projeto de algoritmo Probabilístico para resolver o problema dos Primos • O ponto onde o algoritmo ingênuo é custoso está no loop For i = 1, ... , n/2 Passo 2 é executado um número exponencial de vezes ! • • Ideia : técnica Monte Carlo – – – Ao invés de executar o passo 2 para cada valor de i = 1,...,n/2, sorteia-se um número p qualquer entre 1 e n/2 e executa o passo 2 uma única vez para p (testa se p divide n) Se a resposta for ‘sim’, pára e responde ‘não’. Caso contrário, pára e responde ‘sim’. Complexidade = O(k2) onde k = tamanho de n Exemplo Testar se 34 é primo utilizando esta “técnica” de MC (Monte Carlo). Quantos números entre 2 e 17 ? 16 Sorteia um destes números. Por exemplo: 15. Testa se 15 divide 34. Como a resposta é ‘não’, o algoritmo retorna ‘sim, é primo’ = resposta ERRADA Se o número sorteado fosse o 17, o algoritmo retorna ‘não, não é primo’ = resposta CERTA. Qual a probabilidade do algoritmo retornar uma resposta CERTA para o input n = 34 : 2/16 = 1/8 = 12,5 % Qual a probabilidade do algoritmo retornar uma resposta errada para o input n = 34 : 1- 12,5 = 87,5% Exemplo Testar se 12 é primo utilizando esta “técnica” de MC (Monte Carlo). Quantos números entre 2 e 6 ? 5 Sorteia um destes números. Por exemplo: 5. Testa se 5 divide 12. Como a resposta é ‘não’, o algoritmo retorna ‘sim, é primo’ = resposta ERRADA. Se o número sorteado fosse o 3, o algoritmo retorna ‘não, não é primo’ = resposta CERTA. Qual a probabilidade do algoritmo retornar uma resposta CERTA para o input n = 12 : 3/5= 60% Qual a probabilidade do algoritmo retornar uma resposta errada para o input n = 12 : 1- 0,6 = 40% Exercício Preencher a tabela: O teste da primalidade de MC tem probabilidade de falhar quando o input NÃO É PRIMO. A probabilidade de falhar varia muito de número para número. Depende muito do número de valores intermediários para os quais o teste de divisão retorna ‘sim’, que é onde o algoritmo pára e retorna ‘Não, não é primo’. Quanto maior for este número de valores, maior a probabilidade de acerto da resposta negativa ‘Não, não é primo’ Input 34 12 30 55 22 13 17 5 42 Prob. acerto Prob. erro 12,5 % 87,5% 60% 40% 36% 64% 100% 100% 100% 0 0 0 O que seria interessante ? • Um algoritmo MC que utilizasse um outro teste (de complexidade polinomial) no lugar da divisão e que: – tivesse pelo menos 50% de probabilidade de acertar, caso o input não fosse primo. – Tivesse 100% de probabilidade de acertar, caso o input é primo. Teste de Fermat (1640) • Se n é primo então para todo a, 1 ≤ a < n tal que mdc(a,n) = 1, então an-1 ≡ 1 mod n O teste de Fermat (que substitui a divisão) consiste em testar se an-1 ≠ 1 mod n Teste da divisão que permite concluir que um número não é primo: Se a divide n n não é primo Teste de Fermat que permite concluir que um número não é primo: Se an-1 ≠ 1 mod n n não é primo Probabilidade de acerto do Teste de Fermat • • Para inputs n primo: 100% Para inputs n não primo: probabilidade de acerto depende do número de elementos intermediários a com mdc(a,n) = 1 e para os quais o teste de Fermat falha: an-1 ≠ 1 mod n Lema: se n não é primo: • ou não existe nenhum a intermediário para o qual o teste de Fermat falha, – Que números são estes ? Parecem muito com os primos mas não são ! Números de Carmichael : Ex. 561 = 3.11.17 • ou pelo menos a metade dos valores intermediários falha no teste de Fermat Prova • Suponha que exista a com mdc(a,n) = 1 tal que o TF (teste de Fermat) falha: a.b’ a.b b’ b a Falha no TF Sucede no TF Para todo b tal que bn-1 = 1 mod n, temos que (a.b)n-1 ≠ 1 mod n Além disto se (a.b)n-1 = (a.b’)n-1 b = b’ Logo: |Sucede| <= |Falha| Portanto, podemos concluir que pelo menos a metade dos elementos entre 1 e n com mdc(a,n) = 1 falham no TF. Se não houvesse números de Carmichael ... • Se N é primo então todos os a entre 1 e n sucedem no TF. • Se N não é primo então no máximo metade dos a entre 1 e n sucedem no TF • Probabilidade de acerto do algoritmo quando N é primo: 100% • Probabilidade de erro do algoritmo quando N não é primo (e não é de Carmichael) ≤ ½ • Probabilidade de acerto quando N não é primo ≥ ½ • Para números de Carmichael, a probabilidade de erro é 100% Um algoritmo probabilistico para testar probabilidade com probabilidade de erro bem baixa para números compostos não de Carmichael. Probabilidade de erro quando n não é primo: precisa sortear k valores intermediários que falham no TF simultaneamente. 1o sorteio = falha ≤ ½ 2o sorteio = falha ≤ ½ .... K-ésimo sorteio = falha ≤ ½ Probabilidade ≤ (½)(½)... (½) = (½) k Números Primos são úteis em Criptografia • Algoritmo RSA para criptografar e descriptografar mensagens. 1. Gera dois números primos grandes p,q de n bits 2. N = p.q 3. N1 = (p-1).(q-1) 4. Considera um número e < N tal que mdc(e,N1) = 1 5. Chave pública = (e,N) permite codificar mensagens x cod(x) = xe mod n 6. Todo mundo que conhece a chave pública pode codificar mensagens usando esta chave. 7. Chave privada = número d que permite decodificar cod(x) e reobter x (xe)d 8. A chave privada não é facilmente obtida por quem desconhece os números p e q. Só é conhecida do dono da chave pública. 9. d = inverso de e mod (p-1)(q-1), isto é d.e = 1 mod (p-1)(q-1) Chave privada d realmente decodifica ! • (xe)d = x para todo x entre 0 e N-1 ??? • Como ed = 1 mod(p-1)(q-1), então ed = 1 + k(p-1)(q-1) Logo xed – x = x1 + k(p-1)(q-1) – x = 0 mod p xed – x = x 1 + k(p-1)(q-1) - x = x.(x(p-1))k(q-1) – x = 0 mod p xed – x é divisivel por p pois xp-1 = 1 mod p Logo p divide xed – x Analogamente, podemos mostrar que q divide xed – x Logo N = p.q divide xed – x e portanto xed – x = 0 mod N . Como decodificar ? • Conhecendo a chave privada d • Sem conhecer a chave privada, como fazer ? – Advinhar p, q e construir a chave privada – Advinhar p, q corresponde a fatorar N em fatores primos: problema intratável, muito dificil, NP-hard. Que algoritmos faltam para implementar o RSA ? 1. Gera dois números primos grandes p,q de n bits 2. N = p.q 3. N1 = (p-1).(q-1) 4. Considera um número e < N tal que mdc(e,N1) = 1 5. Chave pública = (e,N) permite codificar mensagens x cod(x) = xe mod n 6. Todo mundo que conhece a chave pública pode codificar mensagens usando esta chave. 7. Chave privada = número d que permite decodificar cod(x) e reobter x (xe)d 8. A chave privada não é facilmente obtida por quem desconhece os números p e q. Só é conhecida do dono da chave pública. 9. d = inverso de e mod (p-1)(q-1), isto é d.e = 1 mod (p-1)(q-1) Números Primos são úteis em Criptografia • Algoritmo RSA para criptografar e descriptografar mensagens. 1. Gera dois números primos grandes p,q de n bits 2. N = p.q 3. N1 = (p-1).(q-1) 4. Considera um número e < N tal que mdc(e,N1) = 1 5. Chave pública = (e,N) permite codificar mensagens x cod(x) = xe mod n 6. Todo mundo que conhece a chave pública pode codificar mensagens usando esta chave. 7. Chave privada = número d que permite decodificar cod(x) e reobter x (xe)d 8. A chave privada não é facilmente obtida por quem desconhece os números p e q. Só é conhecida do dono da chave pública. 9. d = inverso de e mod (p-1)(q-1), isto é d.e = 1 mod (p-1)(q-1) Exponencial modular Complexidade = O(n3) se y tem n bits também Exemplo • Ver planilha de cálculos Como encontrar o inverso de um número mod n ? • Através do algoritmo estendido de Euclides para calcular o mdc entre dois números. Algoritmo de Euclides para mdc(a,b) • Input: a,b inteiros de n bits, a ≥ b ≥ 0 • Output : mdc(a,b) Quantas chamadas são necessárias para obter a mod b = 0 ? A PROVAR : Se a ≥ b então a mod b < a/2 Logo número de chamadas recursivas = 2n (número de chamadas até alcançar o caso base b = 0) cada chamada recursiva envolve uma operação de divisão O(n2) Complexidade = O(n3) Por que ? Se a ≥ b então a mod b < a/2 ? Caso 1: b ≤ a/2 Caso 2: b > a/2 Algoritmo estendido de Euclides • Retorna d = mcd (a,b) e x, y tais que d = x.a + y.b • Se d = 1 então x = inverso de a mod b