<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Primality Test on kenji.blog</title><link>http://kenji.blog/pt/tags/primality-test/</link><description>Recent content in Primality Test on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 22:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/primality-test/index.xml" rel="self" type="application/rss+xml"/><item><title>Fundamentos e Implementação da Criptografia usando o Pequeno Teorema de Fermat</title><link>http://kenji.blog/pt/p/fermats-little-theorem-cryptography-implementation/</link><pubDate>Fri, 11 Sep 2026 22:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/fermats-little-theorem-cryptography-implementation/</guid><description>&lt;img src="http://kenji.blog/p/fermats-little-theorem-cryptography-implementation/img/eyecatch.jpg" alt="Featured image of post Fundamentos e Implementação da Criptografia usando o Pequeno Teorema de Fermat" />&lt;h2 id="1-introdução-o-mistério-matemático-que-sustenta-a-criptografia-moderna">1. Introdução: O mistério matemático que sustenta a criptografia moderna
&lt;/h2>&lt;p>Na sociedade digital moderna, especialmente nas comunicações via Internet, a &amp;ldquo;criptografia&amp;rdquo; tornou-se uma tecnologia fundamental indispensável. O fato de podermos navegar na web de forma segura via HTTPS em nossos navegadores, realizar transações financeiras no internet banking e trocar mensagens privadas em aplicativos de mensagens é possível devido aos protocolos criptográficos apoiados por teorias matemáticas avançadas que operam nos bastidores. Entre eles, o sistema de &amp;ldquo;criptografia de chave pública&amp;rdquo; desempenha um papel particularmente importante, e seu principal representante é a &lt;strong>Criptografia RSA&lt;/strong>.&lt;/p>
&lt;p>A segurança e a validade de muitos algoritmos criptográficos, incluindo o RSA, dependem fortemente de um teorema muito belo e poderoso descoberto pelo matemático francês do século 17, Pierre de Fermat. Esse é o &lt;strong>Pequeno Teorema de Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>. Além disso, o teorema de Leonhard Euler, que generaliza isso, também desempenha um papel decisivo na teoria da criptografia.&lt;/p>
&lt;p>Neste artigo, explicaremos detalhadamente desde o básico como a descoberta do Pequeno Teorema de Fermat, na matemática pura, é aplicada às tecnologias de criptografia práticas modernas, em particular ao &amp;ldquo;teste de primalidade&amp;rdquo; e à &amp;ldquo;criptografia RSA&amp;rdquo;. Este será um guia técnico muito detalhado que cobre provas matemáticas, os mecanismos de criptografia e descriptografia, e implementações de algoritmos específicos em C++ e Python.&lt;/p>
&lt;hr>
&lt;h2 id="2-fundamentos-de-congruências-e-aritmética-modular">2. Fundamentos de Congruências e Aritmética Modular
&lt;/h2>&lt;p>Para entender o Pequeno Teorema de Fermat, primeiro precisamos nos familiarizar com o conceito matemático de &amp;ldquo;aritmética modular (congruências)&amp;rdquo;. A aritmética modular é um sistema de cálculo que foca no &amp;ldquo;resto&amp;rdquo; quando dividido por um número fixo (chamado de módulo). Por ser um cálculo parecido com o mostrador de um relógio (que dá uma volta em 12 horas), também é chamada de &amp;ldquo;matemática do relógio&amp;rdquo;.&lt;/p>
&lt;p>Quando o resto da divisão dos inteiros $a$ e $b$ por um inteiro positivo $n$ é igual, matematicamente, descrevemos da seguinte forma:&lt;/p>
$$
a \equiv b \pmod n
$$
&lt;p>Isso é lido como &amp;ldquo;$a$ e $b$ são congruentes módulo $n$&amp;rdquo;. Por exemplo, o resto da divisão de 17 por 5 é 2, e o resto da divisão de 12 por 5 também é 2. Portanto, podemos escrever:&lt;/p>
$$
17 \equiv 12 \pmod 5 \equiv 2 \pmod 5
$$
&lt;p>Na aritmética modular, as quatro operações aritméticas normais (adição, subtração e multiplicação) valem como são:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Adição&lt;/strong>: Se $a \equiv b \pmod n$ e $c \equiv d \pmod n$, então $a + c \equiv b + d \pmod n$&lt;/li>
&lt;li>&lt;strong>Subtração&lt;/strong>: Se $a \equiv b \pmod n$ e $c \equiv d \pmod n$, então $a - c \equiv b - d \pmod n$&lt;/li>
&lt;li>&lt;strong>Multiplicação&lt;/strong>: Se $a \equiv b \pmod n$ e $c \equiv d \pmod n$, então $a \times c \equiv b \times d \pmod n$&lt;/li>
&lt;li>&lt;strong>Exponenciação&lt;/strong>: Se $a \equiv b \pmod n$, então para qualquer número natural $k$, $a^k \equiv b^k \pmod n$&lt;/li>
&lt;/ol>
&lt;p>No entanto, é necessário ter cuidado com a &lt;strong>divisão&lt;/strong>. Em geral, o fato de que $a \times c \equiv b \times c \pmod n$ não significa que podemos dividir ambos os lados por $c$ para obter $a \equiv b \pmod n$. Isso só é verdadeiro se $c$ e $n$ forem coprimos (o máximo divisor comum for 1). Esse conceito de &amp;ldquo;inverso modular&amp;rdquo; torna-se extremamente importante na geração de chaves da criptografia RSA descrita mais adiante.&lt;/p>
&lt;hr>
&lt;h2 id="3-fundamentação-matemática-e-prova-do-pequeno-teorema-de-fermat">3. Fundamentação Matemática e Prova do Pequeno Teorema de Fermat
&lt;/h2>&lt;p>Agora que entendemos os fundamentos da aritmética modular, vamos analisar o assunto principal: o Pequeno Teorema de Fermat.&lt;/p>
&lt;h3 id="31-definição-do-teorema">3.1 Definição do Teorema
&lt;/h3>&lt;p>O Pequeno Teorema de Fermat é formulado da seguinte maneira:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Pequeno Teorema de Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>
Seja $p$ um número primo e $a$ um número inteiro que não seja um múltiplo de $p$ (ou seja, $a$ e $p$ são coprimos). Então, a seguinte congruência é válida:
&lt;/p>
$$ a^{p-1} \equiv 1 \pmod p $$
&lt;/blockquote>
&lt;p>Também é comum expressá-lo de uma forma que seja válida para todos os inteiros $a$, removendo a condição &amp;ldquo;se $a$ não for múltiplo de $p$&amp;rdquo;. Nesse caso, multiplicando ambos os lados por $a$, temos:&lt;/p>
$$
a^p \equiv a \pmod p
$$
&lt;h3 id="32-confirmação-com-exemplos-específicos">3.2 Confirmação com Exemplos Específicos
&lt;/h3>&lt;p>Vamos confirmar se o teorema é realmente válido usando números específicos.
Seja o número primo $p = 5$. Então $p-1 = 4$. Escolheremos um número inteiro $a$ que não seja um múltiplo de $p$.&lt;/p>
&lt;ul>
&lt;li>Para $a = 2$: $2^{5-1} = 2^4 = 16$. $16 \div 5 = 3$ com resto $1$. Portanto, $16 \equiv 1 \pmod 5$. (Válido)&lt;/li>
&lt;li>Para $a = 3$: $3^{5-1} = 3^4 = 81$. $81 \div 5 = 16$ com resto $1$. Portanto, $81 \equiv 1 \pmod 5$. (Válido)&lt;/li>
&lt;li>Para $a = 4$: $4^{5-1} = 4^4 = 256$. $256 \div 5 = 51$ com resto $1$. Portanto, $256 \equiv 1 \pmod 5$. (Válido)&lt;/li>
&lt;/ul>
&lt;p>Como podemos ver, qualquer $a$ que escolhermos (desde que não seja um múltiplo de 5), o resto após elevá-lo à quarta potência e dividi-lo por 5 será sempre 1. Parece magia, mas isso se origina das belas propriedades que os números primos possuem.&lt;/p>
&lt;h3 id="33-prova-matemática-do-teorema">3.3 Prova Matemática do Teorema
&lt;/h3>&lt;p>Por que isso acontece? Aqui apresentamos uma prova elegante usando conjuntos de classes de resíduos.&lt;/p>
&lt;p>Considere o conjunto $S = \{1, 2, 3, \dots, p-1\}$. Estes são os representantes dos números inteiros cujos restos da divisão por $p$ são de $1$ a $p-1$.
Agora, considere um novo conjunto $T$, formado pela multiplicação de cada elemento por um inteiro $a$, coprimo com $p$.
&lt;/p>
$$ T = \{1a, 2a, 3a, \dots, (p-1)a\} $$
&lt;p>Vamos considerar o resto de cada elemento desse conjunto $T$ quando dividido por $p$. Surpreendentemente, esses restos, embora a ordem possa mudar, coincidem perfeitamente com o conjunto de elementos do conjunto original $S$.
Por que:&lt;/p>
&lt;ol>
&lt;li>Nenhum elemento de $T$ será múltiplo de $p$ (porque nem $a$ nem os elementos originais são múltiplos de $p$).&lt;/li>
&lt;li>Não existem dois elementos diferentes em $T$ que sejam congruentes módulo $p$. Se houvesse $ia \equiv ja \pmod p$ ($i \neq j$), já que $a$ e $p$ são coprimos, poderíamos dividir por $a$ e obter $i \equiv j \pmod p$, o que é uma contradição.&lt;/li>
&lt;/ol>
&lt;p>Portanto, o produto de todos os elementos de $S$ e o produto de todos os elementos de $T$ são congruentes módulo $p$.&lt;/p>
$$
(1a) \times (2a) \times \dots \times ((p-1)a) \equiv 1 \times 2 \times \dots \times (p-1) \pmod p
$$
&lt;p>Organizando o lado esquerdo, como temos $p-1$ fatores $a$, obtemos:&lt;/p>
$$
a^{p-1} \cdot (p-1)! \equiv (p-1)! \pmod p
$$
&lt;p>Como $(p-1)!$ e $p$ são coprimos, podemos dividir ambos os lados por $(p-1)!$, o que nos leva finalmente ao seguinte teorema:&lt;/p>
$$
a^{p-1} \equiv 1 \pmod p
$$
&lt;p>Esta é a prova do Pequeno Teorema de Fermat.&lt;/p>
&lt;hr>
&lt;h2 id="4-a-função-totiente-de-euler-e-o-teorema-de-euler">4. A Função Totiente de Euler e o Teorema de Euler
&lt;/h2>&lt;p>O Pequeno Teorema de Fermat é um teorema sobre um &amp;ldquo;número primo $p$&amp;rdquo;, mas quem o generalizou para &amp;ldquo;qualquer inteiro positivo $n$&amp;rdquo; foi Leonhard Euler. Essa extensão é essencial para compreender a criptografia RSA.&lt;/p>
&lt;h3 id="41-função-totiente-de-euler-phin">4.1 Função Totiente de Euler $\phi(n)$
&lt;/h3>&lt;p>A função totiente de Euler (ou função $\phi$ de Euler) $\phi(n)$ é uma função que representa &amp;ldquo;a quantidade de inteiros de $1$ a $n$ que são coprimos com $n$&amp;rdquo;.&lt;/p>
&lt;ul>
&lt;li>Para um número primo $p$, como todos os inteiros de $1$ a $p-1$ são coprimos com $p$, temos $\phi(p) = p - 1$.&lt;/li>
&lt;li>Para dois números primos distintos $p$ e $q$, o valor de $\phi(n)$ para o seu produto $n = p \times q$ pode ser calculado com uma fórmula muito simples:
$$ \phi(p \times q) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$&lt;/li>
&lt;/ul>
&lt;p>Esta propriedade é a lógica central na geração de chaves da criptografia RSA.&lt;/p>
&lt;h3 id="42-teorema-de-euler">4.2 Teorema de Euler
&lt;/h3>&lt;p>Euler generalizou o Pequeno Teorema de Fermat da seguinte maneira:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Teorema de Euler (Euler&amp;rsquo;s Theorem)&lt;/strong>
Para qualquer inteiro positivo $n$ e um inteiro $a$ coprimo com ele, é válido que:
&lt;/p>
$$ a^{\phi(n)} \equiv 1 \pmod n $$
&lt;/blockquote>
&lt;p>Se $n$ for um número primo $p$, então $\phi(p) = p - 1$, o que o torna exatamente o Pequeno Teorema de Fermat ($a^{p-1} \equiv 1 \pmod p$). Em outras palavras, o Pequeno Teorema de Fermat não passa de um caso especial do Teorema de Euler.&lt;/p>
&lt;hr>
&lt;h2 id="5-encontrando-números-primos-gigantescos-o-teste-de-primalidade-de-fermat">5. Encontrando Números Primos Gigantescos: O Teste de Primalidade de Fermat
&lt;/h2>&lt;p>Na tecnologia criptográfica (como a criptografia RSA e a troca de chaves Diffie-Hellman), é necessário encontrar &amp;ldquo;números primos gigantescos&amp;rdquo; de centenas de dígitos em alta velocidade. No entanto, para testar se um número gigante $N$ é primo através da &amp;ldquo;divisão por tentativa&amp;rdquo; (testando a divisibilidade por todos os números de $2$ a $\sqrt{N}$), levaria tanto tempo quanto a idade do universo.&lt;/p>
&lt;p>Aqui entra o &lt;strong>Teste de Primalidade de Fermat (Fermat Primality Test)&lt;/strong>, um &amp;ldquo;teste de primalidade probabilístico&amp;rdquo; que usa o Pequeno Teorema de Fermat.&lt;/p>
&lt;h3 id="51-o-que-é-um-teste-de-primalidade-probabilístico">5.1 O que é um Teste de Primalidade Probabilístico?
&lt;/h3>&lt;p>De acordo com o Pequeno Teorema de Fermat, se $p$ for um número primo, então, para qualquer $a$ ($1 &lt; a &lt; p$), $a^{p-1} \equiv 1 \pmod p$ é sempre válido.
Tomando a contrapositiva: &amp;ldquo;Se houver algum $a$ para o qual $a^{p-1} \not\equiv 1 \pmod p$, então $p$ &lt;strong>absolutamente não é um número primo (é um número composto)&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>Portanto, se quisermos testar se $N$ é um número primo, escolhemos aleatoriamente alguns valores para $a$, calculamos $a^{N-1} \pmod N$ e verificamos se o resultado é $1$. Se obtivermos uma resposta diferente de $1$ mesmo que seja apenas uma vez, concluímos que $N$ é um número composto. Se o resultado for sempre $1$, independentemente de quantas vezes testarmos, podemos julgar com alta probabilidade que $N$ &amp;ldquo;provavelmente é primo&amp;rdquo;.&lt;/p>
&lt;h3 id="52-explicação-do-algoritmo-e-fluxograma">5.2 Explicação do Algoritmo e Fluxograma
&lt;/h3>&lt;p>O algoritmo do teste de Fermat é o seguinte.&lt;/p>
&lt;div class="mermaid">flowchart TD
Start["Início"] --> Input["Inserir o número a testar p e o número de testes k"]
Input --> LoopStart["Loop de i = 0 até k-1"]
LoopStart --> Condition{"i &lt; k ?"}
Condition -- "Sim" --> RandomA["Escolher um inteiro aleatório a no intervalo 1 &lt; a &lt; p-1"]
RandomA --> Calc["Calcular a exponenciação modular a^(p-1) mod p"]
Calc --> CheckPrime{"O resultado é 1 ?"}
CheckPrime -- "Não" --> ReturnComposite["p é um número composto (Definitivo)"]
CheckPrime -- "Sim" --> Increment["Incrementar i"]
Increment --> Condition
Condition -- "Não" --> ReturnPrime["p é provavelmente primo (Probabilístico)"]
ReturnComposite --> End["Fim"]
ReturnPrime --> End&lt;/div>
&lt;h3 id="53-a-armadilha-dos-números-de-carmichael-pseudoprimos">5.3 A Armadilha dos Números de Carmichael (Pseudoprimos)
&lt;/h3>&lt;p>O teste de Fermat é extremamente rápido, mas tem uma desvantagem séria. Existem números maldosos que, apesar de serem compostos, satisfazem $a^{N-1} \equiv 1 \pmod N$ para todos os valores de $a$. Estes são chamados de &lt;strong>Números de Carmichael (Carmichael numbers)&lt;/strong>. O menor número de Carmichael é $561$ ($3 \times 11 \times 17$).&lt;/p>
&lt;p>Devido à existência dos números de Carmichael, não se pode realizar um teste de primalidade absoluto usando apenas o teste puro de Fermat. Por esta razão, em sistemas criptográficos reais (como o OpenSSL), o &lt;strong>Teste de Primalidade de Miller-Rabin&lt;/strong>, que é um aprimoramento do teste de Fermat, é usado como padrão. O teste de Miller-Rabin consegue detectar os números de Carmichael, reduzindo a probabilidade de falso julgamento praticamente a zero.&lt;/p>
&lt;h3 id="54-exponenciação-modular-rápida-método-de-exponenciação-binária">5.4 Exponenciação Modular Rápida (Método de Exponenciação Binária)
&lt;/h3>&lt;p>No algoritmo de teste de primalidade, precisamos calcular $a^{N-1} \pmod N$, mas se $N$ for enorme, $a^{N-1}$ terá uma quantidade astronômica de dígitos e não caberá na memória do computador.
O que resolve esse problema é a &lt;strong>Exponenciação Binária (Exponentiation by Squaring)&lt;/strong> ou exponenciação modular. Ao aplicar o módulo (mod N) a cada etapa do cálculo, o valor é mantido sempre inferior a $N$, permitindo um cálculo muito rápido (complexidade $O(\log N)$).&lt;/p>
&lt;hr>
&lt;h2 id="6-implementação-do-teste-de-primalidade-e-exponenciação-modular">6. Implementação do Teste de Primalidade e Exponenciação Modular
&lt;/h2>&lt;p>Agora, vamos implementar o teste de primalidade de Fermat e o método de exponenciação binária em C++ e Python.&lt;/p>
&lt;h3 id="61-implementação-em-c">6.1 Implementação em C++
&lt;/h3>&lt;p>Em C++, os tipos de inteiros padrão tendem a transbordar, exigindo bibliotecas de inteiros de precisão arbitrária (como GMP) para lidar com números enormes, mas aqui mostramos uma implementação dentro do limite de um inteiro de 64 bits (&lt;code>unsigned long long&lt;/code>) para entender o algoritmo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;random&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Exponenciação modular rápida (a^b mod m) - Método de exponenciação binária
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="nf">power_mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Se o bit menos significativo de b for 1, multiplica o resultado por a
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">__int128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">result&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Extensão para 128 bits para evitar transbordamento
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Eleva a ao quadrado
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">__int128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Desloca b para a direita (divide por 2)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Teste de primalidade de Fermat
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">bool&lt;/span> &lt;span class="nf">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">iterations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">random_device&lt;/span> &lt;span class="n">rd&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mt19937_64&lt;/span> &lt;span class="n">gen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rd&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uniform_int_distribution&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">dis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">gen&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Se a^(p-1) mod p não for 1, é um número composto
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">power_mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Provavelmente primo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000000007&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Número primo conhecido
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is probably prime.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is composite.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-implementação-em-python">6.2 Implementação em Python
&lt;/h3>&lt;p>O tipo inteiro padrão do Python suporta precisão arbitrária nativamente, de modo que não há necessidade de se preocupar com estouro de dígitos. Além disso, a função interna do Python &lt;code>pow(a, b, m)&lt;/code> usa internamente o método de exponenciação binária, tornando-a muito rápida.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Teste de primalidade probabilístico usando o Teste de Primalidade de Fermat
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">iterations&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Escolhe um número aleatório a entre 2 e p-2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calcula a^(p-1) mod p. A função interna pow é rápida.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span> &lt;span class="c1"># Definitivamente composto&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span> &lt;span class="c1"># Provavelmente primo&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Teste&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">number_to_test&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">104729&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> é provavelmente primo.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> é composto.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="7-aplicação-na-criptografia-rsa-onde-fermat-e-euler-dão-frutos">7. Aplicação na Criptografia RSA: Onde Fermat e Euler dão Frutos
&lt;/h2>&lt;p>A maior aplicação do Pequeno Teorema de Fermat (e do Teorema de Euler) é a &lt;strong>Criptografia RSA&lt;/strong>, desenvolvida por Rivest, Shamir e Adleman em 1977.
A criptografia RSA é um sistema revolucionário de &amp;ldquo;criptografia de chave pública&amp;rdquo;, que consegue um mecanismo onde a chave para criptografar (a chave pública) é revelada a todo o mundo, enquanto a chave para descriptografar (a chave privada) é conhecida apenas pelo destinatário pretendido.&lt;/p>
&lt;p>Essa assimetria é baseada na segurança computacional proporcionada pelo fato de que &amp;ldquo;a fatoração de um número composto gigantesco é extremamente difícil&amp;rdquo;.&lt;/p>
&lt;h3 id="71-como-funciona-a-criptografia-rsa-geração-de-chaves-criptografia-descriptografia">7.1 Como Funciona a Criptografia RSA (Geração de Chaves, Criptografia, Descriptografia)
&lt;/h3>&lt;p>Vamos ver o fluxo geral de comunicação da criptografia RSA com um diagrama de sequência Mermaid.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice["Alice (Destinatário)"]
participant Bob["Bob (Remetente)"]
Alice->>Alice: "Gera os primos gigantescos p e q"
Alice->>Alice: "Calcula N = p * q, φ(N) = (p-1)(q-1)"
Alice->>Alice: "Calcula a chave pública e e a chave privada d (e*d ≡ 1 mod φ(N))"
Alice->>Bob: "Envia a chave pública (N, e)"
Note over Bob: "Prepara o texto simples M (M &lt; N)"
Bob->>Bob: "Calcula o texto cifrado C = M^e mod N"
Bob->>Alice: "Envia o texto cifrado C"
Alice->>Alice: "Calcula o texto simples M = C^d mod N para descriptografar"&lt;/div>
&lt;p>Abaixo, explicaremos os passos matemáticos detalhados.&lt;/p>
&lt;h4 id="passo-1-geração-de-chaves-tarefa-da-destinatária-alice">Passo 1: Geração de Chaves (Tarefa da destinatária Alice)
&lt;/h4>&lt;ol>
&lt;li>Gera dois números primos gigantescos aleatórios $p$ e $q$ (o método de teste de primalidade descrito acima é usado aqui).&lt;/li>
&lt;li>Calcula o seu produto $N = p \times q$. Este $N$ torna-se público.&lt;/li>
&lt;li>Usando a função totiente de Euler, calcula $\phi(N) = (p-1)(q-1)$.&lt;/li>
&lt;li>Escolhe um número inteiro $e$ (expoente público) que seja coprimo com $\phi(N)$ (geralmente $e = 65537$ é usado).&lt;/li>
&lt;li>Calcula o inverso modular $d$ (expoente privado) de $e$. Ou seja, encontra $d$ que satisfaça o seguinte:
$$ e \cdot d \equiv 1 \pmod{\phi(N)} $$
Para esse cálculo, o &lt;strong>Algoritmo de Euclides Estendido&lt;/strong> é usado.&lt;/li>
&lt;/ol>
&lt;p>Com isso, a &lt;strong>chave pública é $(N, e)$&lt;/strong> e a &lt;strong>chave privada é $(N, d)$&lt;/strong>. (Eles descartam imediatamente ou ocultam estritamente $p, q, \phi(N)$).&lt;/p>
&lt;h4 id="passo-2-criptografia-tarefa-do-remetente-bob">Passo 2: Criptografia (Tarefa do remetente Bob)
&lt;/h4>&lt;p>Suponha que Bob queira enviar a mensagem $M$ para Alice ($M$ é uma representação numérica de caracteres, onde $0 \le M &lt; N$).
Bob usa a chave pública de Alice $(N, e)$ para realizar o seguinte cálculo e criar o texto cifrado $C$.&lt;/p>
$$
C \equiv M^e \pmod N
$$
&lt;p>Este $C$ é então enviado para Alice pela rede.&lt;/p>
&lt;h4 id="passo-3-descriptografia-tarefa-da-destinatária-alice">Passo 3: Descriptografia (Tarefa da destinatária Alice)
&lt;/h4>&lt;p>Ao receber o texto cifrado $C$, Alice realiza o seguinte cálculo usando a chave privada $d$ que apenas ela conhece.&lt;/p>
$$
M' \equiv C^d \pmod N
$$
&lt;p>Surpreendentemente, o resultado desse cálculo, $M'$, é exatamente igual à mensagem original $M$.&lt;/p>
&lt;h3 id="72-por-que-pode-ser-descriptografado-prova-matemática">7.2 Por que pode ser Descriptografado? (Prova Matemática)
&lt;/h3>&lt;p>É aqui que o Pequeno Teorema de Fermat (Teorema de Euler) mostra seu verdadeiro valor. Por que $C^d \pmod N$ retorna a $M$?&lt;/p>
&lt;p>Vamos expandir a equação de descriptografia.
Como $C \equiv M^e \pmod N$,
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>No passo de geração da chave, $d$ foi escolhido para que $e \cdot d \equiv 1 \pmod{\phi(N)}$. Isso significa que existe um número inteiro $k$ tal que:
&lt;/p>
$$ e \cdot d = 1 + k \cdot \phi(N) $$
&lt;p>Substituindo isso na equação acima:
&lt;/p>
$$ M^{ed} = M^{1 + k \cdot \phi(N)} = M \cdot M^{k \cdot \phi(N)} = M \cdot (M^{\phi(N)})^k \pmod N $$
&lt;p>Aqui, entra o &lt;strong>Teorema de Euler&lt;/strong> ($M^{\phi(N)} \equiv 1 \pmod N$). (&lt;em>Rigorosamente, $M$ e $N$ precisam ser coprimos, mas em RSA, a probabilidade de que $M$ e $N$ não sejam coprimos é astronomicamente baixa, e pelo Teorema Chinês do Resto, pode-se provar que é válido mesmo se não forem coprimos&lt;/em>).&lt;/p>
&lt;p>Aplicando o Teorema de Euler, como $M^{\phi(N)} \equiv 1$, temos:
&lt;/p>
$$ M \cdot (1)^k \equiv M \pmod N $$
&lt;p>$M$ foi perfeitamente restaurado! As propriedades dos números que Fermat e Euler descobriram há centenas de anos garantem perfeitamente a confidencialidade das comunicações digitais modernas.&lt;/p>
&lt;hr>
&lt;h2 id="8-implementação-da-criptografia-rsa-de-brinquedo-python">8. Implementação da Criptografia RSA de Brinquedo (Python)
&lt;/h2>&lt;p>Uma vez que é difícil ter uma noção de como isso funciona baseando-se apenas na teoria, vamos usar o Python para implementar o processo de geração de chaves, criptografia e descriptografia da criptografia RSA na prática. Esta é uma &amp;ldquo;implementação de brinquedo&amp;rdquo; educacional, mas a matemática subjacente é exatamente a mesma.&lt;/p>
&lt;p>O &amp;ldquo;Algoritmo de Euclides Estendido&amp;rdquo; para encontrar o inverso modular $d$ também será incluído na implementação.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Encontrar o máximo divisor comum&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Algoritmo de Euclides Estendido (encontra x e y para ax + by = gcd(a,b))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Usado para encontrar d para e*d ≡ 1 (mod φ(N))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">Exception&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;O inverso não existe&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">phi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Função de geração de primos (Versão simples: gera números primos pequenos)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getrandbits&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Substitui o teste de Fermat acima por um teste simplificado&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">p&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Geração de par de chaves RSA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">16&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Evita que p e q sejam iguais&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># e costuma usar um número primo como 65537, mas vamos escolher aleatoriamente aqui&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Cálculo da chave privada d&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Chave pública (e, n), chave privada (d, n)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">plaintext&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calcula plaintext^e mod n&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cipher&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">plaintext&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">cipher&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ciphertext&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calcula cipher^d mod n e reverte para um caractere&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">plain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">chr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">ciphertext&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">plain&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Exemplo de execução&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;--- Implementação da Criptografia RSA de Brinquedo ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">private_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">12&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># Usa um número primo de 12 bits&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Chave pública (e, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">public_key&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Chave privada (d, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">private_key&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Hello Math!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">Mensagem original: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Criptografia&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">encrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Texto cifrado: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">encrypted_msg&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Descriptografia&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">private_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">encrypted_msg&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Mensagem descriptografada: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted_msg&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Quando você executa este código, você pode confirmar como a matriz de caracteres é convertida em um array de números estranhos (texto cifrado), e como isso é restaurado perfeitamente para a string original através da chave privada.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusão-a-intersecção-entre-a-beleza-da-matemática-e-a-praticidade">9. Conclusão: A Intersecção entre a Beleza da Matemática e a Praticidade
&lt;/h2>&lt;p>Quando Pierre de Fermat descobriu este &amp;ldquo;pequeno teorema&amp;rdquo; no século 17, ninguém pensou que isso pudesse ser útil de alguma forma. O próprio Fermat conduziu suas pesquisas em teoria dos números com curiosidade puramente matemática.&lt;/p>
&lt;p>No entanto, nos anos 1970, cerca de 300 anos depois, nos primórdios das redes de computadores, o teorema de Fermat fez um retorno dramático como uma tecnologia de criptografia essencial para estabelecer protocolos de comunicação seguros. A tecnologia do teste de primalidade baseada no Pequeno Teorema de Fermat e a Criptografia RSA, com base no Teorema de Euler, sustentam literalmente a infraestrutura moderna da internet.&lt;/p>
&lt;p>Até mesmo a mensagem no LINE que enviamos casualmente todos os dias e nossas compras na Amazon, estão todas dançando no topo desta simples e bela fórmula: $a^{p-1} \equiv 1 \pmod p$. O Pequeno Teorema de Fermat nos ensina que, não importa o quão abstrata seja a matemática, o momento em que ela for útil para a humanidade sem dúvida chegará algum dia.&lt;/p>
&lt;p>Ao aprender programação e teoria criptográfica, compreender a estrutura matemática em seus fundamentos será uma grande arma para o profundo entendimento do comportamento das bibliotecas fornecidas como caixas-pretas e para o design de sistemas mais seguros.&lt;/p></description></item></channel></rss>