Algoritmos de pesquisa de números primos

“O maior número primo é 2 32582657 -1 . E afirmo com orgulho que me lembrei de todos os seus números ... em forma binária ".
Karl Pomerance

Um número natural é chamado primo se tiver apenas dois divisores diferentes: um e ele próprio. A tarefa de encontrar números primos assombra os matemáticos há muito tempo. Por um longo tempo, esse problema não teve aplicação prática direta, mas tudo mudou com o advento da criptografia de chave pública. Este artigo discute várias maneiras de procurar números primos, tanto de interesse puramente acadêmico quanto usados ​​atualmente em criptografia.

Peneira de Eratóstenes


Peneira de Eratóstenes - um algoritmo proposto pelo matemático grego antigo Eratóstenes. Este método permite encontrar todos os números primos menores que um número n . A essência do método é a seguinte. Pegue um conjunto de números de 2 a n . Riscar todos os números divisíveis por 2, exceto 2. Do conjunto (eliminamos), passamos para o próximo número “não eliminado” - 3, novamente riscamos tudo o que é divisível por 3. Passamos para o próximo número restante - 5 e assim sucessivamente até chegamos ao n . Depois de executar as etapas acima, apenas os números primos permanecerão na lista original.

O algoritmo pode ser ligeiramente otimizado. Como um dos divisores do número composto n é obrigatório  leqslant sqrtn, o algoritmo pode ser parado após a exclusão dos números divisíveis por  sqrtn.

Ilustração da operação do algoritmo da Wikipedia:

imagem

A complexidade do algoritmo é O(n log logn)ao mesmo tempo, para armazenar informações sobre quais números foram riscados, é necessário O(n)memória.

Há várias otimizações para reduzir esses indicadores. Um truque chamado fatoração de roda é incluir na lista inicial apenas números coprime com os primeiros números primos (por exemplo, menos de 30). Em teoria, propõe-se levar os primeiros simples até cerca de  sqrt logn. Isso reduz a complexidade do algoritmo em  log lognvezes. Além disso, a chamada segmentação é usada para reduzir o consumo de memória. O conjunto inicial de números é dividido em segmentos de tamanho  leqslant sqrtne para cada segmento, a peneira de Eratóstenes é aplicada separadamente. O consumo de memória é reduzido para O( sqrtn).

Peneira Atkin


Um algoritmo melhor para selecionar números compostos foi proposto por Atkin e Bershtein e foi chamado de Peneira de Atkin . Este método é baseado nas três propriedades a seguir dos números primos.

Propriedade 1

Se n for um número positivo que não seja múltiplo do quadrado de um número primo e que n equiv1( mod4). Então n é primo se e somente se o número de raízes da equação 4x2+y2=nestranho.

Propriedade 2

Se n for um número positivo que não seja múltiplo do quadrado de um número primo e que n equiv1( mod6). Então n é primo se e somente se o número de raízes da equação 3x2+y2=nestranho.

Propriedade 3

Se n for um número positivo que não seja múltiplo do quadrado de um número primo e que n equiv11( mod12). Então n é primo se e somente se o número de raízes da equação 3x2y2=nestranho.

As evidências para essas propriedades são fornecidas neste artigo .

No estágio inicial do algoritmo, a peneira de Atkin é uma matriz A do tamanho n preenchida com zeros. Para determinar números primos, todos x,y< sqrtn. Para cada par é calculado 4x2+y2, 3x2+y2, 3x2y2e o valor dos elementos da matriz A[4x2+y2], A[3x2+y2], A[3x2y2]aumenta em um. No final do algoritmo, os índices de todos os elementos da matriz que possuem valores ímpares são números primos ou quadrados de um número primo. Na última etapa do algoritmo, os quadrados dos números restantes no conjunto são riscados.

Da descrição do algoritmo resulta que a complexidade computacional da peneira de Atkin e o consumo de memória são O(n). Ao usar a fatoração e segmentação das rodas, a estimativa de complexidade do algoritmo é reduzida para O(n/ log logn)e consumo de memória até O( sqrtn).

Números de Mersenne e teste de Luke-Lemer


Obviamente, com esses indicadores de complexidade, mesmo a peneira otimizada da Atkin não pode ser usada para procurar primos realmente grandes. Felizmente, existem testes rápidos para verificar se um determinado número é primo. Ao contrário dos algoritmos de peneira, esses testes não são projetados para procurar todos os números primos, eles só conseguem dizer com alguma probabilidade se um determinado número é primo.

Um desses métodos de teste é o teste de Luc-Lemer . Este é um teste determinístico e incondicional da simplicidade. Isso significa que a aprovação no teste garante a simplicidade do número. Infelizmente, o teste é destinado apenas a números de um tipo especial 2p1onde p é um número natural. Esses números são chamados de números de Mersenne.

O teste de Luke-Lemer afirma que o número de Mersenne Mp=2p1primo se e somente se p for primo e Mpdivide (p1)membro da sequência Skdefinir recursivamente: S1=4,Sk=Sk122para k>1.

Para o número Mpcomprimento de p bits, a complexidade computacional do algoritmo é  displaystyleO(p3).

Devido à simplicidade e ao determinismo do teste, os maiores números primos conhecidos são os números de Mersenne. O maior número primo conhecido de hoje é 282.589.9331, sua notação decimal consiste em 24.862.048 dígitos. Você pode admirar essa beleza aqui .

Teorema de Fermat e teste de Miller-Rabin


Não são conhecidos muitos números primos de Mersenne; portanto, a criptografia de chave pública requer uma maneira diferente de pesquisar números primos. Um desses métodos é o teste de simplicidade de Fermat . É baseado no pequeno teorema de Fermat, que afirma que se n é primo, então para qualquer a que não seja divisível por n , a igualdade an1 equiv1 pmodn. A prova do teorema pode ser encontrada na Wikipedia .

O teste de simplicidade de Fermat é um teste probabilístico, que consiste em enumerar vários valores de a se pelo menos um deles satisfizer a desigualdade an1 not equiv1 pmodn, o número n é composto. Caso contrário, n é provavelmente primo. Quanto mais valores de um usado no teste, maior a probabilidade de n ser primo.

Infelizmente, existem números compostos n para os quais a comparação an1 equiv1 pmodnvale para todos um primo mutuamente com n . Esses números são chamados de números Carmichael . Os números compostos que passam com êxito no teste de Fermat são chamados Fermat pseudo-simples. O número de Fermat pseudo-simples é infinito; portanto, o teste de Fermat não é a maneira mais confiável de determinar números primos.

Teste de Miller-Rabin

Resultados mais confiáveis ​​podem ser alcançados combinando o pequeno teorema de Fermat e o fato de que para um primo p não há outras raízes da equação x2 equiv1 pmodpexceto 1 e -1. O teste de Miller-Rabin enumera vários valores de a e verifica se as seguintes condições são verdadeiras.

Seja p um primo e p1=2sd, então para qualquer uma de pelo menos uma das condições for verdadeira:

  1. ad equiv pm1 pmodp
  2. Existe um número inteiro r <s tal que a2rd equiv1 pmodp

Pelo teorema de Fermat ap1 equiv1 pmodpe desde p1=2sdda propriedade das raízes da equação x2 equiv1 pmodpsegue-se que, se acharmos que uma das condições não é satisfeita, então p é um número composto. Se uma das condições for cumprida, o número a é chamado de testemunha da simplicidade do número n, de acordo com Miller, e o número n em si é provavelmente primo.

Quanto mais testemunhas de simplicidade forem encontradas, maior a probabilidade de n ser primo. De acordo com o teorema de Rabin, a probabilidade de um número escolhido aleatoriamente a testemunhar a simplicidade do número composto é aproximadamente 1/4.

Portanto, se verificarmos k números aleatórios a , então a probabilidade de tomar o número composto como primo  aprox(1/4)k.

A complexidade do algoritmo O(k log3p)onde k é o número de verificações.

Devido à sua velocidade e alta precisão, o teste de Miller-Rabin é amplamente utilizado na busca de números primos. Muitas bibliotecas criptográficas modernas usam apenas esse teste para verificar a simplicidade de grandes números e, como Martin Albrecht mostrou em seu trabalho , isso nem sempre é suficiente.

Ele foi capaz de gerar esses números compostos que foram aprovados no teste de simplicidade nas bibliotecas OpenSSL, CryptLib, JavaScript Big Number e muitos outros.

Teste de Luke e Baillie - Teste PSW


Para evitar vulnerabilidades relacionadas a situações em que um número composto gerado por um invasor é apresentado como primo, Martin Albrecht sugere o uso do teste Baillie - PSW . Apesar do teste Baillie - PSW ser probabilístico, até o momento, não foram encontrados números compostos que passem com êxito nesse teste. Por encontrar esse número em 1980, os autores do algoritmo prometeram uma recompensa de US $ 30. O prêmio ainda não foi reivindicado.

Vários pesquisadores verificaram todos os números até 264e nenhum número composto passou no teste Baillie - PSW. Portanto, para números menos 264o teste é considerado determinístico.

A essência do teste é verificar consistentemente o número em um tempo de inatividade por dois métodos diferentes. Um desses métodos é o teste de Miller-Rabin já descrito acima. O segundo é o teste de Lucas para uma forte pseudo-simplicidade .

Teste de pseudo-simplicidade de Luke Strong

Sequências de Lucas são pares de sequências de recorrência \ {U_ {n} (P, Q) \}, \ {V_ {n} (P, Q) \} descrito pelas expressões:

 displaystyleU0(P,Q)=0, quadU1(P,Q)=1, quadUn+2(P,Q)=P cdotUn+1(P,Q)Q cdotUn(P,Q),n geq0


 displaystyleV0(P,Q)=2, quadV1(P,Q)=P, quadVn+2(P,Q)=P cdotVn+1(P,Q)Q cdotVn(P,Q),n geq0


Vamos Un(P,Q)e Vn(P,Q)São sequências de Lucas, onde os números inteiros P e Q satisfazem a condição  displaystyleD=P24Q neq0

Calculamos o símbolo de Jacobi :  left( fracDp right)= varepsilon.

Encontre tais r, s para os quais a igualdade nε=2rs

Para prime n , uma das seguintes condições é válida:

  1. n divide Us
  2. n divide V2jspor algum j <r

Caso contrário, n é composto.

A probabilidade de um número composto n ser aprovado no teste Luc para um determinado par de parâmetros P, Q não excede 4/15. Portanto, após a aplicação do teste k vezes, essa probabilidade é (4/15)k.

Os testes de Miller-Rabin e Luke produzem conjuntos disjuntos de números pseudo-simples, respectivamente, se o número p passou nos dois testes, é simples. É nessa propriedade que se baseia o teste Baillie - PSW.

Conclusão


Dependendo da tarefa, vários métodos para encontrar números primos podem ser usados. Por exemplo, ao procurar primos grandes de Mersenne, primeiro, usando a peneira de Eratóstenes ou Atkin, uma lista de primos é determinada até um certo limite, suponha que até 108. Em seguida, para cada número p da lista, usando o teste Luc-Lemer, é verificado se há simplicidade Mp=2p1.

Para gerar um grande número primo para fins criptográficos, um número aleatório a é selecionado e verificado pelo teste de Miller-Rabin ou pelo Baillie - PSW mais confiável. De acordo com o teorema da distribuição de números primos , para um número selecionado aleatoriamente de 1 a n, a chance de ser primo é aproximadamente igual  frac1 lnn. Portanto, para encontrar um número primo de 1024 bits, basta classificar cerca de mil opções.

Fontes PS


A implementação de todos os algoritmos descritos no Go pode ser visualizada no GitHub .

Source: https://habr.com/ru/post/pt468833/


All Articles