<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cryptography on kenji.blog</title><link>http://kenji.blog/pt/tags/cryptography/</link><description>Recent content in Cryptography on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 21:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/cryptography/index.xml" rel="self" type="application/rss+xml"/><item><title>A intuição matemática da criptografia baseada em reticulados (Lattice-based cryptography)</title><link>http://kenji.blog/pt/p/lattice-based-cryptography-math-intuition/</link><pubDate>Fri, 11 Sep 2026 21:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/lattice-based-cryptography-math-intuition/</guid><description>&lt;img src="http://kenji.blog/p/lattice-based-cryptography-math-intuition/img/eyecatch.jpg" alt="Featured image of post A intuição matemática da criptografia baseada em reticulados (Lattice-based cryptography)" />&lt;h1 id="1-introdução-o-alvorecer-da-criptografia-pós-quântica-pqc-e-a-ascensão-da-criptografia-baseada-em-reticulados">1. Introdução: O alvorecer da Criptografia Pós-Quântica (PQC) e a ascensão da criptografia baseada em reticulados
&lt;/h1>&lt;p>A infraestrutura digital da sociedade moderna é sustentada por tecnologias de criptografia de chave pública, como a criptografia RSA e a Criptografia de Curva Elíptica (ECC). Esses métodos criptográficos baseiam sua segurança na dificuldade matemática de problemas como o &amp;ldquo;Problema de Fatoração de Inteiros&amp;rdquo; e o &amp;ldquo;Problema do Logaritmo Discreto&amp;rdquo;, que se acredita não poderem ser resolvidos eficientemente (exigindo tempo exponencial) pelos computadores clássicos convencionais.&lt;/p>
&lt;p>No entanto, o &amp;ldquo;Algoritmo de Shor&amp;rdquo;, publicado por Peter Shor em 1994, enviou ondas de choque através do mundo da criptografia. Este algoritmo provou matematicamente que, uma vez realizados computadores quânticos de grande escala, problemas de fatoração de inteiros e logaritmos discretos serão resolvidos em tempo polinomial. Isso significa que a criptografia de chave pública amplamente utilizada hoje se tornará completamente decifrável no futuro.&lt;/p>
&lt;p>Para combater essa &amp;ldquo;Ameaça Quântica (Quantum Threat)&amp;rdquo;, a pesquisa em novos métodos criptográficos que sejam difíceis de quebrar, mesmo usando computadores quânticos, tornou-se uma questão urgente. Este é o campo conhecido como &amp;ldquo;Criptografia Pós-Quântica (Post-Quantum Cryptography: PQC)&amp;rdquo; ou &amp;ldquo;Criptografia resistente a quantum&amp;rdquo;.&lt;/p>
&lt;p>Existem vários candidatos fortes para PQC. Estes incluem criptografia baseada em hash, criptografia baseada em código, criptografia polinomial multivariada e criptografia baseada em isogenia. Entre eles, o que atualmente atrai mais atenção e é fundamental para o processo de padronização PQC do NIST (Instituto Nacional de Padrões e Tecnologia dos EUA) é a &amp;ldquo;Criptografia baseada em reticulados (Lattice-based cryptography)&amp;rdquo;. Em comparação com outros métodos, a criptografia baseada em reticulados possui velocidades de criptografia e descriptografia extremamente rápidas e exibe uma característica notável em sua prova de segurança: uma redução da &amp;ldquo;complexidade do pior caso (Worst-case complexity)&amp;rdquo; para a &amp;ldquo;complexidade do caso médio (Average-case complexity)&amp;rdquo;, que é extremamente poderosa na teoria criptográfica.&lt;/p>
&lt;p>Neste artigo, começaremos pela definição matemática fundamental de um &amp;ldquo;Reticulado (Lattice)&amp;rdquo;, que é a base da criptografia baseada em reticulados, e explicaremos profundamente problemas difíceis em reticulados como SVP (Problema do Vetor Mais Curto) e CVP (Problema do Vetor Mais Próximo), e o núcleo da criptografia de reticulados moderna, o &amp;ldquo;Problema LWE (Learning With Errors)&amp;rdquo;, usando fórmulas, intuição geométrica e exemplos numéricos concretos.&lt;/p>
&lt;h1 id="2-definição-matemática-e-intuição-geométrica-do-reticulado-lattice">2. Definição Matemática e Intuição Geométrica do Reticulado (Lattice)
&lt;/h1>&lt;h2 id="21-espaço-vetorial-e-reticulados">2.1 Espaço Vetorial e Reticulados
&lt;/h2>&lt;p>Em matemática, um &amp;ldquo;Reticulado (Lattice)&amp;rdquo; é um conjunto de pontos discretos dispostos regularmente em um espaço vetorial real de dimensão $n$, $\mathbb{R}^n$. É semelhante a um espaço vetorial (Vector Space) aprendido em álgebra linear, mas há uma diferença crucial. Enquanto um espaço vetorial é um espaço contínuo representado por combinações lineares com &amp;ldquo;coeficientes reais&amp;rdquo; dos vetores de base, um reticulado é um espaço discreto representado por combinações lineares com &amp;ldquo;coeficientes inteiros&amp;rdquo; dos vetores de base.&lt;/p>
&lt;p>Vamos dar uma definição matemática rigorosa. Considere $n$ vetores linearmente independentes ($n \le m$) $\mathbf{b}_1, \mathbf{b}_2, \dots, \mathbf{b}_n$ em um espaço vetorial real de dimensão $m$, $\mathbb{R}^m$. Considere uma matriz cujos vetores coluna são esses vetores: $B = [\mathbf{b}_1, \mathbf{b}_2, \dots, \mathbf{b}_n] \in \mathbb{R}^{m \times n}$. Esta $B$ é chamada de &amp;ldquo;Base (Basis)&amp;rdquo; do reticulado.&lt;/p>
&lt;p>O reticulado $\mathcal{L}(B)$ gerado por esta base $B$ é definido da seguinte forma:&lt;/p>
$$
\mathcal{L}(B) = \left\{ \sum_{i=1}^{n} x_i \mathbf{b}_i \mathrel{\bigg|} x_i \in \mathbb{Z} \right\} = \{ B \mathbf{x} \mid \mathbf{x} \in \mathbb{Z}^n \}
$$
&lt;p>O ponto importante aqui é que os coeficientes $x_i$ são restritos a inteiros $\mathbb{Z}$, e não a números reais $\mathbb{R}$. Isso forma um &amp;ldquo;conjunto de pontos discretos&amp;rdquo; semelhante a cruzamentos espaçados uniformemente, em vez dos infinitos pontos contínuos no espaço.&lt;/p>
&lt;h2 id="22-imagem-geométrica">2.2 Imagem Geométrica
&lt;/h2>&lt;p>Vamos considerar um exemplo em um plano bidimensional $\mathbb{R}^2$. Se escolhermos $\mathbf{b}_1 = \begin{pmatrix} 1 \\ 0 \end{pmatrix}$ e $\mathbf{b}_2 = \begin{pmatrix} 0 \\ 1 \end{pmatrix}$ como vetores de base, o reticulado gerado por eles será o conjunto de todas as coordenadas inteiras $(x, y) \in \mathbb{Z}^2$ no plano cartesiano. Este é o &amp;ldquo;reticulado quadrado&amp;rdquo; mais simples.&lt;/p>
&lt;p>No entanto, reticulados nem sempre são ortogonais. Por exemplo, considerando a base $\mathbf{b}_1 = \begin{pmatrix} 2 \\ 1 \end{pmatrix}$ e $\mathbf{b}_2 = \begin{pmatrix} 1 \\ 3 \end{pmatrix}$, os pontos gerados serão como as interseções de uma malha distorcida diagonalmente.&lt;/p>
&lt;h2 id="23-não-unicidade-da-base-e-transformação-unimodular">2.3 Não Unicidade da Base e Transformação Unimodular
&lt;/h2>&lt;p>Há uma propriedade importante relacionada ao núcleo da segurança da criptografia baseada em reticulados. É que &amp;ldquo;existem infinitas bases que geram o mesmo reticulado&amp;rdquo;.&lt;/p>
&lt;p>Por exemplo, a base anterior $\mathbf{b}_1 = (1, 0)^T, \mathbf{b}_2 = (0, 1)^T$ que gera o reticulado $\mathbb{Z}^2$ também gerará exatamente o mesmo reticulado $\mathbb{Z}^2$ se usarmos a base $\mathbf{b}'_1 = (1, 1)^T, \mathbf{b}'_2 = (2, 3)^T$.&lt;/p>
&lt;p>A condição necessária e suficiente para uma certa base $B$ e outra base $B'$ gerarem o mesmo reticulado é que exista uma matriz com componentes inteiros $U \in \mathbb{Z}^{n \times n}$ tal que seu determinante seja $\det(U) = \pm 1$, e possa ser expressa como:
&lt;/p>
$$ B' = B U $$
&lt;p>
Tal matriz $U$ é chamada de &amp;ldquo;matriz unimodular (Unimodular matrix)&amp;rdquo;.&lt;/p>
&lt;p>A ideia básica em aplicações criptográficas é usar uma &amp;ldquo;boa base (uma base próxima de ser ortogonal, consistindo de vetores curtos)&amp;rdquo; como chave privada, e uma &amp;ldquo;base ruim (uma base consistindo de vetores extremamente oblíquos entre si e muito longos)&amp;rdquo; como chave pública. Calcular uma boa base a partir de uma base ruim torna-se extremamente difícil à medida que a dimensão aumenta. Esta é a intuição básica da criptografia baseada em reticulados.&lt;/p>
&lt;h1 id="3-problemas-computacionalmente-difíceis-em-reticulados">3. Problemas Computacionalmente Difíceis em Reticulados
&lt;/h1>&lt;p>A segurança da criptografia baseada em reticulados depende da dificuldade de resolver certos problemas matemáticos sobre reticulados. Aqui, introduziremos os dois problemas mais fundamentais e famosos.&lt;/p>
&lt;h2 id="31-problema-do-vetor-mais-curto-shortest-vector-problem-svp">3.1 Problema do Vetor Mais Curto (Shortest Vector Problem: SVP)
&lt;/h2>&lt;p>SVP é o problema mais clássico e famoso na teoria dos reticulados.&lt;/p>
&lt;p>&lt;strong>Definição (SVP):&lt;/strong>
Dada qualquer base de reticulado $B$, encontre o vetor não nulo $\mathbf{v}$ pertencente ao reticulado $\mathcal{L}(B)$ cuja norma euclidiana (comprimento) seja mínima.&lt;/p>
&lt;p>Expressando em fórmula, é o problema de encontrar $\mathbf{v}$ tal que $\min_{\mathbf{v} \in \mathcal{L}(B) \setminus \{\mathbf{0}\}} \| \mathbf{v} \|$. Este comprimento mínimo é denotado como $\lambda_1(\mathcal{L})$ e é chamado de &amp;ldquo;Primeiro mínimo sucessivo (First successive minimum)&amp;rdquo; do reticulado.&lt;/p>
&lt;p>Em dimensões baixas, como 2D ou 3D, você pode desenhar uma figura e encontrar visualmente o vetor mais curto. Alternativamente, algoritmos de redução de base de Gauss podem resolvê-lo eficientemente. No entanto, sabe-se que em altas dimensões (por exemplo, dimensão $n$ na casa das centenas a milhares), resolver o SVP de forma exata é NP-difícil.&lt;/p>
&lt;p>Em criptografia do mundo real, em vez do vetor mais curto exato, é usado o SVP aproximado ($\gamma$-SVP) para encontrar um &amp;ldquo;vetor aproximadamente curto&amp;rdquo;. Se o fator de aproximação $\gamma$ for de tamanho polinomial, este problema ainda é considerado extremamente difícil.&lt;/p>
&lt;h2 id="32-problema-do-vetor-mais-próximo-closest-vector-problem-cvp">3.2 Problema do Vetor Mais Próximo (Closest Vector Problem: CVP)
&lt;/h2>&lt;p>CVP também é um problema extremamente importante na criptografia baseada em reticulados.&lt;/p>
&lt;p>&lt;strong>Definição (CVP):&lt;/strong>
Dada qualquer base de reticulado $B$ e qualquer vetor alvo no espaço $\mathbf{t} \in \mathbb{R}^m$ (não necessariamente um ponto do reticulado), encontre o ponto do reticulado $\mathbf{v} \in \mathcal{L}(B)$ que seja o mais próximo de $\mathbf{t}$.&lt;/p>
&lt;p>Expressando em fórmula, é o problema de procurar o ponto do reticulado $\mathbf{v}$ que resulta em $\min_{\mathbf{v} \in \mathcal{L}(B)} \| \mathbf{v} - \mathbf{t} \|$.&lt;/p>
&lt;p>O CVP também é NP-difícil em altas dimensões, semelhante ao SVP. Do ponto de vista das aplicações criptográficas, o problema LWE, descrito posteriormente, está intimamente relacionado a uma variante especial do CVP (Bounded Distance Decoding: BDD).&lt;/p>
&lt;h2 id="33-por-que-não-pode-ser-resolvido-em-altas-dimensões-os-limites-do-lll-e-bkz">3.3 Por que não pode ser resolvido em altas dimensões? (Os Limites do LLL e BKZ)
&lt;/h2>&lt;p>Um algoritmo famoso para resolver problemas de reticulados em altas dimensões é o algoritmo LLL (algoritmo de Lenstra-Lenstra-Lovász). O algoritmo LLL opera em tempo polinomial e pode reduzir a base do reticulado a uma &amp;ldquo;boa base&amp;rdquo; em certa medida. No entanto, o vetor mais curto encontrado pelo algoritmo LLL tem um fator de aproximação exponencial ($2^{\mathcal{O}(n)}$) em relação ao comprimento do vetor mais curto verdadeiro, portanto, não chega ao ponto de quebrar a segurança criptográfica.&lt;/p>
&lt;p>Usar algoritmos de redução de base mais poderosos como o algoritmo BKZ (Block Korkine-Zolotarev), que é uma melhoria do LLL, permite encontrar vetores mais curtos, mas seu tempo de computação aumenta exponencialmente em relação ao tamanho do bloco. Na criptografia baseada em reticulados, parâmetros seguros (como o tamanho da dimensão $n$) são determinados estimando o tempo de execução deste algoritmo BKZ. Nos parâmetros padrão atuais da PQC, são escolhidos valores entre 500 e 1000 ou mais para a dimensão $n$, e estima-se que levaria mais tempo do que a idade do universo para decifrá-los, mesmo com supercomputadores ou computadores quânticos futuros.&lt;/p>
&lt;h1 id="4-formulação-matemática-do-problema-lwe-learning-with-errors">4. Formulação Matemática do Problema LWE (Learning With Errors)
&lt;/h1>&lt;p>A maior parte da criptografia moderna baseada em reticulados é baseada no &amp;ldquo;Problema LWE (Learning With Errors)&amp;rdquo;, proposto por Oded Regev em 2005. A beleza do problema LWE reside na simplicidade de sua formulação e em ter uma prova matemática poderosa: a &amp;ldquo;redução da complexidade do pior caso para a complexidade do caso médio&amp;rdquo;.&lt;/p>
&lt;h2 id="41-equações-lineares-simultâneas-sem-ruído">4.1 Equações lineares simultâneas sem ruído
&lt;/h2>&lt;p>Para entender o problema LWE, vamos primeiro considerar equações lineares simultâneas simples sem ruído.
Suponha que haja um vetor secreto desconhecido $\mathbf{s} \in \mathbb{Z}_q^n$ (cada componente é um número inteiro de $0$ a $q-1$). Aqui, $q$ é considerado um número primo.&lt;/p>
&lt;p>Escolhemos vetores de coeficientes aleatórios $\mathbf{a}_1, \mathbf{a}_2, \dots \in \mathbb{Z}_q^n$, e calculamos seu produto escalar com o vetor secreto $\mathbf{s}$ módulo $q$.
$b_1 = \langle \mathbf{a}_1, \mathbf{s} \rangle \pmod q$
$b_2 = \langle \mathbf{a}_2, \mathbf{s} \rangle \pmod q$
$\vdots$&lt;/p>
&lt;p>Se nos derem um número suficiente (pelo menos $n$) de pares $(\mathbf{a}_i, b_i)$, podemos restaurar facilmente o vetor secreto $\mathbf{s}$ usando a &amp;ldquo;Eliminação Gaussiana (Gaussian elimination)&amp;rdquo; em álgebra linear. Este é um problema que pode ser resolvido facilmente em tempo polinomial.&lt;/p>
&lt;h2 id="42-definição-do-problema-lwe-adicionando-ruído">4.2 Definição do problema LWE: Adicionando Ruído
&lt;/h2>&lt;p>Então, o que acontece se adicionarmos um pouco de &amp;ldquo;ruído (erro)&amp;rdquo; a este problema?
Esta é a essência do problema LWE.&lt;/p>
&lt;p>Para o vetor secreto desconhecido $\mathbf{s} \in \mathbb{Z}_q^n$, adicionamos um pequeno erro $e_i \in \mathbb{Z}_q$ ao resultado de cada equação.
$b_i = \langle \mathbf{a}_i, \mathbf{s} \rangle + e_i \pmod q$&lt;/p>
&lt;p>Aqui, $e_i$ é um número inteiro pequeno com média 0 e desvio padrão relativamente pequeno (por exemplo, retirado de uma distribuição Gaussiana discreta, como uma distribuição normal).
A informação fornecida é uma lista de pares do vetor aleatório $\mathbf{a}_i$ e $b_i$ calculado adicionando o erro.
$( \mathbf{a}_1, b_1 ), ( \mathbf{a}_2, b_2 ), \dots, ( \mathbf{a}_m, b_m )$&lt;/p>
&lt;p>Expressar isso em forma de matriz o torna muito claro.
Usando uma matriz aleatória $A \in \mathbb{Z}_q^{m \times n}$, um vetor secreto $\mathbf{s} \in \mathbb{Z}_q^n$, e um vetor de erro $\mathbf{e} \in \mathbb{Z}_q^m$,
&lt;/p>
$$ \mathbf{b} = A \mathbf{s} + \mathbf{e} \pmod q $$
&lt;p>
pode ser escrito. Apenas $A$ e $\mathbf{b}$ são fornecidos. Encontrar $\mathbf{s}$ a partir disso é o &amp;ldquo;Problema de busca LWE (Search LWE problem)&amp;rdquo;.&lt;/p>
&lt;p>Como o erro $e_i$ está incluído, ao tentar usar a eliminação gaussiana, o erro será amplificado exponencialmente durante o processo de adição e subtração de equações, tornando impossível chegar à resposta correta. À primeira vista, parecem equações lineares simultâneas simples, mas apenas adicionando esse pequeno ruído, o nível de dificuldade do problema salta para um nível NP-difícil.&lt;/p>
&lt;h2 id="43-problema-lwe-de-decisão-decision-lwe">4.3 Problema LWE de decisão (Decision LWE)
&lt;/h2>&lt;p>O que é frequentemente usado em provas na teoria criptográfica é uma variação do problema de busca LWE chamado de &amp;ldquo;Problema LWE de decisão (Decision LWE problem)&amp;rdquo;.&lt;/p>
&lt;p>O problema de decisão LWE é o problema de determinar de qual de duas distribuições uma lista de amostras fornecida se origina.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Distribuição LWE&lt;/strong>: Intencionalmente calculada $(A, \mathbf{b} = A\mathbf{s} + \mathbf{e} \pmod q)$&lt;/li>
&lt;li>&lt;strong>Distribuição aleatória uniforme&lt;/strong>: $(A, \mathbf{u})$ que consiste em uma matriz completamente escolhida aleatoriamente $A$ e vetor $\mathbf{u}$&lt;/li>
&lt;/ol>
&lt;p>Surpreendentemente, se os parâmetros do problema LWE forem escolhidos de forma apropriada, pares de dados da distribuição LWE tornam-se &amp;ldquo;computacionalmente indistinguíveis (Computationally Indistinguishable)&amp;rdquo; de pares de dados completamente aleatórios. Esta propriedade é a base pela qual os cifradores baseados em LWE podem gerar &amp;ldquo;textos cifrados indistinguíveis de números aleatórios&amp;rdquo;.&lt;/p>
&lt;h2 id="44-redução-da-complexidade-do-pior-caso-para-a-complexidade-do-caso-médio-teorema-de-regev">4.4 Redução da complexidade do pior caso para a complexidade do caso médio (Teorema de Regev)
&lt;/h2>&lt;p>A maior conquista de Oded Regev foi ter vinculado matematicamente a dificuldade deste problema LWE à dificuldade dos problemas de reticulados (SVP e CVP) mencionados acima.&lt;/p>
&lt;p>Ele usou a redução quântica (Quantum reduction) para provar que &amp;ldquo;Se existe um algoritmo de tempo polinomial que pode resolver o problema LWE na média (para $A$ e $\mathbf{e}$ escolhidos aleatoriamente), então existe um algoritmo quântico de tempo polinomial que pode resolver o Gap-SVP no pior caso (o caso mais difícil) para qualquer reticulado&amp;rdquo;. (Mais tarde, Peikert e outros também mostraram a redução clássica).&lt;/p>
&lt;p>Esta é uma propriedade dos sonhos na teoria criptográfica. Porque dissipa a preocupação de que &amp;ldquo;a criptografia possa ser quebrada porque por acaso escolhemos uma chave fraca (uma parte do caso médio)&amp;rdquo; e nos dá a poderosa garantia de que &amp;ldquo;Se o LWE médio puder ser resolvido, todos os problemas difíceis do reticulado poderão ser resolvidos (portanto, o LWE é absolutamente difícil)&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">graph TD
A["Problemas de Reticulado de Pior Caso (Gap-SVP, SIVP)"] -->|Redução Quântica/Clássica| B["Problema LWE de Caso Médio"]
B -->|Construção Criptográfica| C["Sistemas Criptográficos baseados em LWE (PKE, KEM, FHE)"]
style A fill:#ffcccc,stroke:#ff0000,stroke-width:2px,color:#000
style B fill:#ccffcc,stroke:#00aa00,stroke-width:2px,color:#000
style C fill:#ccccff,stroke:#0000ff,stroke-width:2px,color:#000&lt;/div>
&lt;h1 id="5-construção-do-cifrador-de-chave-pública-usando-lwe-cifrador-regev">5. Construção do Cifrador de Chave Pública usando LWE (Cifrador Regev)
&lt;/h1>&lt;p>Agora que entendemos a dificuldade do problema LWE, vamos ver a criptografia de chave pública básica proposta por Oded Regev para ver como ela é usada para criptografia e descriptografia. Aqui, explicaremos o mecanismo mais básico para criptografar uma mensagem de 1 bit $M \in \{0, 1\}$.&lt;/p>
&lt;h2 id="51-geração-de-chaves-key-generation">5.1 Geração de chaves (Key Generation)
&lt;/h2>&lt;ol>
&lt;li>Determine o módulo primo $q$, a dimensão $n$, e o número de equações $m$ ($m > n \log q$) como parâmetros do sistema.&lt;/li>
&lt;li>Como uma chave privada, escolha um vetor $\mathbf{s} \in \mathbb{Z}_q^n$ aleatoriamente.&lt;/li>
&lt;li>Gere uma matriz aleatória $A \in \mathbb{Z}_q^{m \times n}$.&lt;/li>
&lt;li>Escolha um vetor de erro pequeno $\mathbf{e} \in \mathbb{Z}_q^m$ a partir de uma distribuição de erro como a distribuição gaussiana discreta.&lt;/li>
&lt;li>Calcule o vetor $\mathbf{b} = A \mathbf{s} + \mathbf{e} \pmod q$.&lt;/li>
&lt;li>A chave pública (Public Key) será $(A, \mathbf{b})$.&lt;/li>
&lt;li>A chave privada (Secret Key) será $\mathbf{s}$.&lt;/li>
&lt;/ol>
&lt;p>A chave pública é exatamente a &amp;ldquo;instância do problema LWE&amp;rdquo; em si. Uma vez que encontrar a chave privada $\mathbf{s}$ a partir da chave pública $(A, \mathbf{b})$ é equivalente a resolver o problema de busca LWE, a segurança é garantida.&lt;/p>
&lt;h2 id="52-criptografia-encryption">5.2 Criptografia (Encryption)
&lt;/h2>&lt;p>Alice usa a chave pública de Bob $(A, \mathbf{b})$ para criptografar a mensagem de 1 bit $M \in \{0, 1\}$.&lt;/p>
&lt;ol>
&lt;li>Escolha um vetor binário aleatório (composto de zeros ou uns) $\mathbf{r} \in \{0, 1\}^m$.&lt;/li>
&lt;li>Como a primeira metade do texto cifrado, calcule o vetor $\mathbf{u} = A^T \mathbf{r} \pmod q$. ($A^T$ é a matriz transposta de $A$. Em outras palavras, está somando as linhas de $A$ onde os componentes de $\mathbf{r}$ são 1).&lt;/li>
&lt;li>Como a segunda metade do texto cifrado, calcule o escalar $v = \mathbf{b}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor \pmod q$.
(Se a mensagem $M$ for 0, nada é adicionado; se for $1$, é adicionado o valor exatamente da metade de $q$, $\lfloor \frac{q}{2} \rfloor$).&lt;/li>
&lt;li>O texto cifrado (Ciphertext) será $(\mathbf{u}, v)$.&lt;/li>
&lt;/ol>
&lt;p>O significado intuitivo da criptografia é pegar a &amp;ldquo;soma de um subconjunto aleatório&amp;rdquo; para a matriz de chave pública $A$ e o vetor $\mathbf{b}$. Devido à dificuldade do problema LWE de decisão, esse texto cifrado $(\mathbf{u}, v)$ parece indistinguível de um vetor completamente aleatório e um número aleatório uniforme (Segurança semântica: Semantic Security).&lt;/p>
&lt;div class="mermaid">flowchart LR
M["Mensagem M em {0,1}"] --> Enc
PK["Chave Pública (A, b)"] --> Enc
r["Vetor binário aleatório r"] --> Enc
subgraph Enc ["Processo de Criptografia"]
direction TB
u_calc["u = A^T * r mod q"]
v_calc["v = b^T * r + M * floor(q/2) mod q"]
end
Enc --> CT["Texto Cifrado (u, v)"]&lt;/div>
&lt;h2 id="53-descriptografia-decryption">5.3 Descriptografia (Decryption)
&lt;/h2>&lt;p>Bob descriptografa o texto cifrado $(\mathbf{u}, v)$ usando a chave secreta $\mathbf{s}$.&lt;/p>
&lt;ol>
&lt;li>Calcule o seguinte valor: $D = v - \mathbf{s}^T \mathbf{u} \pmod q$&lt;/li>
&lt;li>Se o resultado calculado estiver mais próximo de $0$, a saída é $M=0$; se estiver mais próximo de $\lfloor \frac{q}{2} \rfloor$, a saída é $M=1$.&lt;/li>
&lt;/ol>
&lt;p>Vamos expandir matematicamente para ver por que isso permite a descriptografia.
Lembre-se de que $\mathbf{b} = A \mathbf{s} + \mathbf{e}$.&lt;/p>
$$
\begin{aligned}
v - \mathbf{s}^T \mathbf{u} &amp;= (\mathbf{b}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor) - \mathbf{s}^T (A^T \mathbf{r}) \\
&amp;= ((A \mathbf{s} + \mathbf{e})^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor) - \mathbf{s}^T A^T \mathbf{r} \\
&amp;= (\mathbf{s}^T A^T \mathbf{r} + \mathbf{e}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor) - \mathbf{s}^T A^T \mathbf{r} \\
&amp;= \mathbf{e}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor \pmod q
\end{aligned}
$$
&lt;p>Aqui, $\mathbf{s}^T A^T \mathbf{r}$ foi perfeitamente cancelado e desapareceu da fórmula!
O que restou foi $\mathbf{e}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor$.&lt;/p>
&lt;p>$\mathbf{e}$ é um vetor de ruído cujos componentes são extremamente pequenos, e $\mathbf{r}$ é um vetor binário cujos componentes são 0 ou 1. Portanto, o produto escalar deles, $\mathbf{e}^T \mathbf{r}$, também permanece em um valor relativamente pequeno (se os parâmetros forem escolhidos apropriadamente).&lt;/p>
&lt;ul>
&lt;li>Se $M=0$, o resultado é $\mathbf{e}^T \mathbf{r}$, o que será um valor pequeno próximo de $0$.&lt;/li>
&lt;li>Se $M=1$, o resultado é $\mathbf{e}^T \mathbf{r} + \lfloor \frac{q}{2} \rfloor$, o qual ficará próximo da metade do valor de $q$, $\lfloor \frac{q}{2} \rfloor$.&lt;/li>
&lt;/ul>
&lt;p>Se os parâmetros forem desenhados para que o valor absoluto do erro $\mathbf{e}^T \mathbf{r}$ fique abaixo de $\frac{q}{4}$, Bob pode determinar (descriptografar) com precisão a mensagem $M$ apenas olhando se o resultado do cálculo está mais próximo de $0$ ou $\lfloor \frac{q}{2} \rfloor$. Este é o belo mecanismo pelo qual os cifradores baseados em LWE funcionam.&lt;/p>
&lt;div class="mermaid">flowchart LR
CT["Texto Cifrado (u, v)"] --> Dec
SK["Chave Secreta s"] --> Dec
subgraph Dec ["Processo de Descriptografia"]
direction TB
calc["Calcular D = v - s^T * u mod q"]
check["Verificar se D está mais próximo de 0 ou q/2"]
end
calc --> check
Dec --> M_out["Mensagem Recuperada M"]&lt;/div>
&lt;h1 id="6-exemplo-prático-toy-example-de-criptografia-lwe-com-valores-numéricos-específicos">6. Exemplo Prático (Toy Example) de Criptografia LWE com Valores Numéricos Específicos
&lt;/h1>&lt;p>Pode ser difícil ter uma noção apenas listando equações, então vamos tentar definir parâmetros numéricos muito pequenos e seguir o cálculo desde a criptografia até a descriptografia.
(*Em sistemas criptográficos do mundo real, são utilizados valores para $n$ superiores a 500 e $q$ superiores a milhares para garantir a segurança.)&lt;/p>
&lt;p>&lt;strong>[Configuração de Parâmetros]&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Módulo $q = 17$ (Número primo. Assim, os valores variam de $0$ a $16$)&lt;/li>
&lt;li>Dimensão $n = 2$&lt;/li>
&lt;li>Número de equações $m = 4$&lt;/li>
&lt;li>Suponha que vamos criptografar a mensagem $M = 1$.&lt;/li>
&lt;li>Quantidade de deslocamento da mensagem: $\lfloor \frac{q}{2} \rfloor = \lfloor \frac{17}{2} \rfloor = 8$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[1. Fase de Geração de Chaves]&lt;/strong>
Bob seleciona a chave privada $\mathbf{s}$, a matriz $A$ e o vetor de erro $\mathbf{e}$ aleatoriamente.
&lt;/p>
$$ \mathbf{s} = \begin{pmatrix} 3 \\ 4 \end{pmatrix} \in \mathbb{Z}_{17}^2 $$
$$ A = \begin{pmatrix} 2 &amp; 15 \\ 1 &amp; 8 \\ 14 &amp; 5 \\ 9 &amp; 10 \end{pmatrix} \in \mathbb{Z}_{17}^{4 \times 2} $$
$$ \mathbf{e} = \begin{pmatrix} 1 \\ -1 \\ 0 \\ 2 \end{pmatrix} \equiv \begin{pmatrix} 1 \\ 16 \\ 0 \\ 2 \end{pmatrix} \pmod{17} $$
&lt;p>Em seguida, ele calcula a chave pública $\mathbf{b}$.
&lt;/p>
$$ A \mathbf{s} = \begin{pmatrix} 2 &amp; 15 \\ 1 &amp; 8 \\ 14 &amp; 5 \\ 9 &amp; 10 \end{pmatrix} \begin{pmatrix} 3 \\ 4 \end{pmatrix} = \begin{pmatrix} 2\times 3 + 15\times 4 \\ 1\times 3 + 8\times 4 \\ 14\times 3 + 5\times 4 \\ 9\times 3 + 10\times 4 \end{pmatrix} = \begin{pmatrix} 6 + 60 \\ 3 + 32 \\ 42 + 20 \\ 27 + 40 \end{pmatrix} = \begin{pmatrix} 66 \\ 35 \\ 62 \\ 67 \end{pmatrix} $$
&lt;p>
Calculando isto no módulo 17 (por exemplo, $66 = 17 \times 3 + 15$):
&lt;/p>
$$ A \mathbf{s} \pmod{17} = \begin{pmatrix} 15 \\ 1 \\ 11 \\ 16 \end{pmatrix} $$
&lt;p>
Adicionando o vetor de erro $\mathbf{e}$:
&lt;/p>
$$ \mathbf{b} = A \mathbf{s} + \mathbf{e} = \begin{pmatrix} 15 \\ 1 \\ 11 \\ 16 \end{pmatrix} + \begin{pmatrix} 1 \\ 16 \\ 0 \\ 2 \end{pmatrix} = \begin{pmatrix} 16 \\ 17 \\ 11 \\ 18 \end{pmatrix} \equiv \begin{pmatrix} 16 \\ 0 \\ 11 \\ 1 \end{pmatrix} \pmod{17} $$
&lt;p>A chave pública será $A$ e $\mathbf{b} = (16, 0, 11, 1)^T$.&lt;/p>
&lt;p>&lt;strong>[2. Fase de Criptografia]&lt;/strong>
Alice criptografa a mensagem $M = 1$.
Ela escolhe um vetor aleatório $\mathbf{r}$. Aqui, assumiremos $\mathbf{r} = (1, 0, 1, 0)^T$.&lt;/p>
&lt;p>Calculando $\mathbf{u}$:
&lt;/p>
$$ \mathbf{u} = A^T \mathbf{r} = \begin{pmatrix} 2 &amp; 1 &amp; 14 &amp; 9 \\ 15 &amp; 8 &amp; 5 &amp; 10 \end{pmatrix} \begin{pmatrix} 1 \\ 0 \\ 1 \\ 0 \end{pmatrix} = \begin{pmatrix} 2 \times 1 + 14 \times 1 \\ 15 \times 1 + 5 \times 1 \end{pmatrix} = \begin{pmatrix} 16 \\ 20 \end{pmatrix} \equiv \begin{pmatrix} 16 \\ 3 \end{pmatrix} \pmod{17} $$
&lt;p>Calculando $v$:
&lt;/p>
$$ \mathbf{b}^T \mathbf{r} = (16, 0, 11, 1) \begin{pmatrix} 1 \\ 0 \\ 1 \\ 0 \end{pmatrix} = 16 \times 1 + 11 \times 1 = 27 \equiv 10 \pmod{17} $$
&lt;p>
Ela adiciona o valor $\lfloor 17/2 \rfloor = 8$ correspondente à mensagem $M=1$.
&lt;/p>
$$ v = \mathbf{b}^T \mathbf{r} + M \cdot 8 = 10 + 1 \times 8 = 18 \equiv 1 \pmod{17} $$
&lt;p>Alice envia o texto cifrado $(\mathbf{u}, v) = \left( \begin{pmatrix} 16 \\ 3 \end{pmatrix}, 1 \right)$ para Bob.&lt;/p>
&lt;p>&lt;strong>[3. Fase de Descriptografia]&lt;/strong>
Ao receber o texto cifrado, Bob descriptografa usando a chave secreta $\mathbf{s} = (3, 4)^T$.
Fórmula do processo de descriptografia: Ele calcula $D = v - \mathbf{s}^T \mathbf{u} \pmod{17}$.&lt;/p>
$$ \mathbf{s}^T \mathbf{u} = (3, 4) \begin{pmatrix} 16 \\ 3 \end{pmatrix} = 3 \times 16 + 4 \times 3 = 48 + 12 = 60 \equiv 9 \pmod{17} $$
$$ D = v - \mathbf{s}^T \mathbf{u} = 1 - 9 = -8 \pmod{17} $$
&lt;p>Aqui, no mundo de módulo 17, $-8$ é equivalente a $9$ ($-8 + 17 = 9$).
Ele verifica se o valor obtido $D = 9$ está mais próximo de $0$ ou $8$ ($\lfloor 17/2 \rfloor$).
Uma vez que $9$ é claramente mais próximo de $8$ do que de $0$, Bob conseguiu recuperar corretamente $M = 1$!&lt;/p>
&lt;p>Por que se tornou $9$? Lembre-se da prova anterior.
A parte do erro é $\mathbf{e}^T \mathbf{r} = (1, -1, 0, 2) (1, 0, 1, 0)^T = 1 \times 1 + 0 \times 1 = 1$.
Portanto, o resultado do cálculo é $\mathbf{e}^T \mathbf{r} + M \cdot 8 = 1 + 8 = 9$, confirmando que o valor teórico foi calculado.&lt;/p>
&lt;h1 id="7-evolução-para-a-prática-ring-lwe-e-module-lwe">7. Evolução para a Prática: Ring-LWE e Module-LWE
&lt;/h1>&lt;p>O problema LWE Padrão (Standard LWE) explicado até agora possui provas de segurança muito fortes, mas tem uma fraqueza fatal na prática. Esta é o &amp;ldquo;tamanho da chave torna-se enorme&amp;rdquo; e &amp;ldquo;os custos de computação são elevados&amp;rdquo;.&lt;/p>
&lt;p>No Standard LWE, a chave pública contém uma matriz enorme $A \in \mathbb{Z}_q^{m \times n}$. Quando o parâmetro $n$ atinge centenas ou milhares, o tamanho dessa matriz chega a vários megabytes, o que a torna muito pesada para transmissão através de protocolos de comunicação na internet (como TLS) todas as vezes. Além disso, a multiplicação entre matrizes e vetores requer complexidade computacional de $\mathcal{O}(n^2)$.&lt;/p>
&lt;p>Para resolver esse problema, &amp;ldquo;Ring-LWE (RLWE)&amp;rdquo; e &amp;ldquo;Module-LWE (MLWE)&amp;rdquo; foram introduzidos, incorporando a estrutura algébrica dos anéis de polinômios (Polynomial rings) aos reticulados.&lt;/p>
&lt;h2 id="71-a-intuição-do-ring-lwe">7.1 A Intuição do Ring-LWE
&lt;/h2>&lt;p>No Ring-LWE, vetores e matrizes são substituídos por elementos (polinômios) em um anel de polinômios $\mathcal{R}_q = \mathbb{Z}_q[X]/(X^n + 1)$. (Aqui, $n$ é escolhido como uma potência de 2).&lt;/p>
&lt;p>Enquanto a chave pública no LWE Padrão era uma matriz $A$, o Ring-LWE usa um único polinômio $a(x)$. A chave privada $s(x)$ e o erro $e(x)$ também se tornam polinômios.
A equação fica assim:
&lt;/p>
$$ b(x) = a(x) \cdot s(x) + e(x) \pmod q $$
&lt;p>Por ser uma multiplicação polinomial, ao usar a &amp;ldquo;Transformada Numérica de Teoria (Number Theoretic Transform: NTT)&amp;rdquo;, que é análoga à Transformada Rápida de Fourier (FFT), o custo computacional pode ser drasticamente reduzido para $\mathcal{O}(n \log n)$. Além disso, dado que o tamanho da chave pública é reduzido de uma matriz para um único polinômio, o tamanho dos dados é reduzido para $\mathcal{O}(n)$. Isso traz uma vantagem esmagadora na largura de banda de comunicação.&lt;/p>
&lt;p>Matematicamente falando, o Ring-LWE não é sobre reticulados gerais, mas reduz-se a problemas em um reticulado especial simétrico chamado &amp;ldquo;Reticulado Ideal (Ideal Lattice)&amp;rdquo;.&lt;/p>
&lt;h2 id="72-module-lwe-e-a-padronização-do-nist-kyber--ml-kem">7.2 Module-LWE e a Padronização do NIST (Kyber / ML-KEM)
&lt;/h2>&lt;p>Embora o Ring-LWE seja eficiente, houve alguma preocupação de que a estrutura algébrica especial dos reticulados ideais pudesse se tornar a base para ataques futuros. Portanto, foi criado o &amp;ldquo;Module-LWE (MLWE)&amp;rdquo; para obter &amp;ldquo;o melhor dos dois mundos&amp;rdquo;, combinando a segurança conservadora do LWE Padrão com a eficiência do Ring-LWE.&lt;/p>
&lt;p>No Module-LWE, consideramos pequenos vetores e matrizes cujos elementos são polinômios. Ou seja, lidamos com módulos (modules) sobre um anel.
Atualmente, o &amp;ldquo;CRYSTALS-Kyber&amp;rdquo; (nome padronizado: ML-KEM), selecionado pelo NIST como o padrão para algoritmos de compartilhamento de chaves (KEM) da PQC, é construído exatamente sobre a dificuldade desse problema Module-LWE.&lt;/p>
&lt;h1 id="8-por-que-é-seguro-contra-computadores-quânticos">8. Por que é seguro contra computadores quânticos?
&lt;/h1>&lt;p>Por fim, tocaremos na questão central: &amp;ldquo;Por que se acredita que a criptografia baseada em reticulados não pode ser decifrada nem mesmo por computadores quânticos?&amp;rdquo;.&lt;/p>
&lt;p>O algoritmo de Shor, que permite aos computadores quânticos quebrar a criptografia RSA ou a criptografia de curvas elípticas, é essencialmente um algoritmo para resolver o &amp;ldquo;Problema do Subgrupo Oculto (Hidden Subgroup Problem: HSP)&amp;rdquo;. As estruturas matemáticas subjacentes à RSA e à ECC (grupos abelianos finitos) possuem periodicidade, e usando a operação específica de algoritmos quânticos chamada Transformada de Fourier Quântica (QFT), esse período (subgrupo oculto) pode ser extraído de uma vez.&lt;/p>
&lt;p>Contudo, os problemas de reticulados são fundamentalmente diferentes. Embora os reticulados também tenham periodicidade, o que é requerido em problemas como SVP e CVP são propriedades geométricas não-lineares, como &amp;ldquo;a distância mais curta&amp;rdquo; e &amp;ldquo;a remoção de ruído&amp;rdquo;. Mesmo que se aplique a &amp;ldquo;transformada de Fourier quântica sobre grupos abelianos&amp;rdquo; como no algoritmo de Shor diretamente, informações úteis que poderiam ser a resposta a problemas de reticulados não podem ser extraídas eficientemente. Até o momento, não foram descobertos algoritmos quânticos que resolvam SVP ou LWE em tempo polinomial e acredita-se amplamente que, mesmo com a capacidade de computação paralela dos computadores quânticos, não exista meio eficaz além de uma busca por força bruta (com uma aceleração na raiz quadrada pelo algoritmo de Grover).&lt;/p>
&lt;h1 id="9-conclusão">9. Conclusão
&lt;/h1>&lt;p>Neste artigo, explicamos em detalhes a intuição matemática da criptografia baseada em reticulados, começando pela definição geométrica de um reticulado, a formulação do problema LWE e culminando na construção da criptografia de chave pública.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Reticulado (Lattice)&lt;/strong> é um espaço discreto expresso por uma combinação linear com coeficientes inteiros de vetores de base, e em dimensões altas, torna-se difícil encontrar uma &amp;ldquo;boa base&amp;rdquo; quase ortogonal (SVP).&lt;/li>
&lt;li>O &lt;strong>Problema LWE (Learning With Errors)&lt;/strong> é o problema de resolver um sistema de equações lineares com ruído, e por estar vinculado à dificuldade do caso mais difícil dos problemas de reticulados, oferece uma poderosa garantia de segurança.&lt;/li>
&lt;li>Ao usar o problema LWE, a criptografia e descriptografia (&lt;strong>Cifrador Regev&lt;/strong>) são alcançadas através de um mecanismo inteligente de adição e cancelamento intencional de ruídos.&lt;/li>
&lt;li>Em protocolos do mundo real, o &lt;strong>Ring-LWE&lt;/strong> e o &lt;strong>Module-LWE&lt;/strong> usando anéis de polinômios são adotados para aumentar a eficiência de comunicação e velocidade computacional, formando a base do padrão NIST &lt;strong>ML-KEM&lt;/strong>.&lt;/li>
&lt;/ol>
&lt;p>À medida que nos aproximamos de uma mudança de paradigma computacional sem precedentes chamada computador quântico, é uma história muito romântica que a &amp;ldquo;Criptografia baseada em reticulados&amp;rdquo;, nascida das profundezas da álgebra linear clássica e da teoria dos números, apoiará a fundação da segurança da internet no futuro. A matemática que fundamenta a criptografia de reticulados não é excessivamente complexa, e com conhecimentos básicos de álgebra linear e probabilidade, pode-se entender completamente sua bela estrutura. Esperamos que este artigo ajude na compreensão da criptografia baseada em reticulados, que é o cerne da PQC.&lt;/p></description></item><item><title>A Hipótese de Riemann e a Distribuição dos Números Primos: A Profunda Relação com a Criptografia Moderna</title><link>http://kenji.blog/pt/p/riemann-hypothesis-prime-distribution-cryptography/</link><pubDate>Fri, 11 Sep 2026 16:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/riemann-hypothesis-prime-distribution-cryptography/</guid><description>&lt;img src="http://kenji.blog/p/riemann-hypothesis-prime-distribution-cryptography/img/eyecatch.jpg" alt="Featured image of post A Hipótese de Riemann e a Distribuição dos Números Primos: A Profunda Relação com a Criptografia Moderna" />&lt;h1 id="1-introdução-o-mistério-cósmico-dos-números-primos-e-a-hipótese-de-riemann">1. Introdução: O Mistério Cósmico dos Números Primos e a Hipótese de Riemann
&lt;/h1>&lt;p>Os &amp;ldquo;Números Primos&amp;rdquo; (Prime Numbers) são números naturais divisíveis apenas por 1 e por si mesmos, sendo frequentemente chamados de &amp;ldquo;átomos&amp;rdquo; do mundo da matemática. Essa sequência que segue como 2, 3, 5, 7, 11, 13&amp;hellip; parece, à primeira vista, desordenada e aleatória. Desde que o matemático grego antigo Euclides provou que &amp;ldquo;os números primos são infinitos&amp;rdquo;, incontáveis matemáticos têm tentado desvendar os padrões ocultos nessa disposição de primos.&lt;/p>
&lt;p>Aquele que chegou mais perto de desvendar esse mistério dos números primos foi o matemático alemão Bernhard Riemann, que propôs a &lt;strong>&amp;ldquo;Hipótese de Riemann&amp;rdquo; (Riemann Hypothesis)&lt;/strong> em 1859. A Hipótese de Riemann é um dos problemas mais importantes e não resolvidos da matemática moderna, com um prêmio de 1 milhão de dólares oferecido pelo Instituto de Matemática Clay como um dos Problemas do Prêmio Millennium.&lt;/p>
&lt;p>À primeira vista, pode parecer que esse problema formidável da matemática pura sobre a distribuição de números primos não tenha relação com o nosso dia a dia. No entanto, a segurança da internet, que sustenta a infraestrutura da sociedade moderna, especialmente as &lt;strong>tecnologias de criptografia modernas como a criptografia RSA e a criptografia de curva elíptica (ECC)&lt;/strong>, depende profundamente das propriedades de números primos gigantescos.&lt;/p>
&lt;p>Neste artigo, faremos uma jornada matemática partindo da distribuição dos números primos até o Teorema dos Números Primos, a função zeta de Riemann e o núcleo da Hipótese de Riemann, explorando de forma extremamente detalhada e profunda como isso se conecta com a criptografia moderna e o que aconteceria com o mundo se a Hipótese de Riemann fosse provada.&lt;/p>
&lt;hr>
&lt;h1 id="2-o-teorema-dos-números-primos-e-a-distribuição-de-primos-a-descoberta-de-gauss">2. O Teorema dos Números Primos e a Distribuição de Primos: A Descoberta de Gauss
&lt;/h1>&lt;p>Para entender como os números primos estão distribuídos, os matemáticos conceberam a &lt;strong>função de contagem de números primos (Prime-counting function)&lt;/strong> $\pi(x)$, que representa &amp;ldquo;quantos números primos existem menores ou iguais a um dado número $x$&amp;rdquo;.&lt;/p>
&lt;p>Por exemplo:&lt;/p>
&lt;ul>
&lt;li>$\pi(10) = 4$ (2, 3, 5, 7)&lt;/li>
&lt;li>$\pi(100) = 25$&lt;/li>
&lt;li>$\pi(1000) = 168$&lt;/li>
&lt;/ul>
&lt;p>O gênio matemático de 15 anos, Carl Friedrich Gauss, calculou extensas tabelas de números primos e descobriu que a frequência de aparecimento dos números primos diminui de forma inversamente proporcional ao logaritmo natural $\ln x$. Em outras palavras, ele conjecturou que a probabilidade de encontrar um número primo perto de um número $x$ é de aproximadamente $\frac{1}{\ln x}$.&lt;/p>
&lt;p>Expressando isso por meio de uma integral, obtemos o &lt;strong>logaritmo integral (Logarithmic integral)&lt;/strong> $\text{Li}(x)$.&lt;/p>
$$ \text{Li}(x) = \int_{2}^{x} \frac{dt}{\ln t} $$
&lt;p>A conjectura de Gauss foi posteriormente provada de forma independente por Jacques Hadamard e Charles Jean de la Vallée Poussin em 1896, estabelecendo-se como o &lt;strong>Teorema dos Números Primos (Prime Number Theorem, PNT)&lt;/strong>.&lt;/p>
$$ \lim_{x \to \infty} \frac{\pi(x)}{\text{Li}(x)} = 1 $$
&lt;p>Ou, de forma aproximada, pode ser expresso como:&lt;/p>
$$ \pi(x) \sim \frac{x}{\ln x} $$
&lt;p>Este teorema mostrou que, de uma perspectiva macroscópica, os números primos têm uma distribuição muito suave e previsível. No entanto, microscopicamente, sempre existe um &amp;ldquo;erro&amp;rdquo;, ou seja, uma &amp;ldquo;flutuação&amp;rdquo; entre $\pi(x)$ e $\text{Li}(x)$. A verdadeira natureza dessa flutuação é exatamente o maior mistério que a Hipótese de Riemann tenta desvendar.&lt;/p>
&lt;hr>
&lt;h1 id="3-a-função-zeta-de-riemann-e-o-produto-de-euler">3. A Função Zeta de Riemann e o Produto de Euler
&lt;/h1>&lt;p>A arma mais poderosa para analisar a distribuição dos números primos é a &lt;strong>Função Zeta de Riemann (Riemann Zeta Function)&lt;/strong>. Originalmente, era uma série infinita definida por Leonhard Euler para números reais $s > 1$.&lt;/p>
$$ \zeta(s) = \sum_{n=1}^\infty \frac{1}{n^s} = 1 + \frac{1}{2^s} + \frac{1}{3^s} + \frac{1}{4^s} + \dots $$
&lt;p>Uma das maiores conquistas de Euler foi provar que esta série infinita pode ser expressa como um produto infinito sobre todos os números primos $p$. Este é o &lt;strong>Produto de Euler (Euler Product Formula)&lt;/strong>.&lt;/p>
$$ \zeta(s) = \prod_{p \text{ prime}} \frac{1}{1 - p^{-s}} = \left( \frac{1}{1 - 2^{-s}} \right) \left( \frac{1}{1 - 3^{-s}} \right) \left( \frac{1}{1 - 5^{-s}} \right) \dots $$
&lt;p>Uma compreensão intuitiva da prova é que, se expandirmos cada termo do lado direito como uma série geométrica e os multiplicarmos, o Teorema Fundamental da Aritmética (que afirma que todo número natural pode ser expresso de forma única como um produto de primos) reconstrói perfeitamente a soma dos recíprocos dos números naturais no lado esquerdo.&lt;/p>
&lt;p>&lt;strong>Essa única equação se tornou a ponte que liga a análise (séries infinitas, funções contínuas) à teoria dos números (números primos, números discretos).&lt;/strong> Estudar a função zeta é sinônimo de estudar a distribuição dos números primos.&lt;/p>
&lt;hr>
&lt;h1 id="4-continuação-analítica-e-a-extensão-para-o-plano-complexo">4. Continuação Analítica e a Extensão para o Plano Complexo
&lt;/h1>&lt;p>A genialidade de Riemann reside no fato de ele ter estendido a variável $s$ de $\zeta(s)$, que Euler considerava apenas para números reais, para &lt;strong>números complexos $s = \sigma + it$ ($\sigma$ é a parte real e $t$ é a parte imaginária)&lt;/strong>.&lt;/p>
&lt;p>A série infinita original converge apenas para $\sigma > 1$, mas Riemann usou um método chamado &amp;ldquo;Continuação Analítica (Analytic Continuation)&amp;rdquo; para estender a definição de modo que $\zeta(s)$ fizesse sentido em todo o plano complexo, com exceção do polo em $s = 1$.&lt;/p>
&lt;p>Ele também derivou uma bela equação funcional (Functional equation) que a função zeta satisfaz.&lt;/p>
$$ \zeta(s) = 2^s \pi^{s-1} \sin\left(\frac{\pi s}{2}\right) \Gamma(1-s) \zeta(1-s) $$
&lt;p>Aqui, $\Gamma(x)$ é a função gama. Com esta equação, podemos conhecer as propriedades do semiplano esquerdo a partir das propriedades do semiplano direito.&lt;/p>
&lt;h3 id="zeros-zeros-of-the-zeta-function">Zeros (Zeros of the Zeta Function)
&lt;/h3>&lt;p>Os números complexos $s$ para os quais o valor da função zeta se torna 0 são chamados de &amp;ldquo;zeros&amp;rdquo;.
A partir da equação funcional, quando $s$ é um número par negativo ($-2, -4, -6, \dots$), $\sin(\pi s / 2)$ torna-se 0, resultando em $\zeta(s) = 0$. Estes são chamados de &lt;strong>zeros triviais (Trivial zeros)&lt;/strong>.&lt;/p>
&lt;p>No entanto, o que importa para a distribuição dos números primos são os outros zeros, ou seja, os &lt;strong>zeros não triviais (Non-trivial zeros)&lt;/strong>, que existem na &amp;ldquo;faixa crítica (Critical strip)&amp;rdquo; onde $0 \le \sigma \le 1$.&lt;/p>
&lt;hr>
&lt;h1 id="5-o-núcleo-da-hipótese-de-riemann-e-a-fórmula-explícita">5. O Núcleo da Hipótese de Riemann e a Fórmula Explícita
&lt;/h1>&lt;p>Riemann calculou alguns zeros e formulou uma conjectura surpreendente. Esta é a &lt;strong>Hipótese de Riemann&lt;/strong>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Hipótese de Riemann (Riemann Hypothesis)&lt;/strong>
Todos os zeros não triviais da função zeta de Riemann $\zeta(s)$ encontram-se na linha reta onde a parte real é igual a $1/2$ ($\text{Re}(s) = 1/2$).&lt;/p>
&lt;/blockquote>
&lt;p>Esta reta onde a parte real é 1/2 é chamada de &amp;ldquo;linha crítica (Critical line)&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">graph TD
A["Função Zeta de Riemann ζ(s)"] --> B["Extensão para o plano complexo via continuação analítica"]
B --> C["Zeros triviais (s = -2, -4, -6 ...)"]
B --> D["Zeros não triviais (0 &lt;= Re(s) &lt;= 1)"]
D --> E["Hipótese de Riemann"]
E --> F["Todos os zeros não triviais estão em Re(s) = 1/2"]
F --> G["Para a prova do limite do termo de erro da distribuição de primos"]&lt;/div>
&lt;p>Por que a Hipótese de Riemann é tão importante? Porque os zeros da função zeta determinam &lt;strong>completamente&lt;/strong> a distribuição dos números primos.&lt;/p>
&lt;p>Riemann e o matemático posterior von Mangoldt derivaram a &amp;ldquo;Fórmula Explícita (Explicit formula)&amp;rdquo;, que descreve com precisão a distribuição dos números primos. Usando a função de Chebyshev $\psi(x)$, ela pode ser expressa da seguinte forma:&lt;/p>
$$ \psi(x) = x - \sum_{\rho} \frac{x^\rho}{\rho} - \ln(2\pi) - \frac{1}{2}\ln(1 - x^{-2}) $$
&lt;p>Aqui, a soma é sobre todos os zeros não triviais $\rho$ da função zeta.
O termo principal é $x$ (o que corresponde ao Teorema dos Números Primos), e ao adicionar e subtrair termos ondulatórios que dependem dos zeros $\rho$, a distribuição exata em forma de degraus dos números primos é restaurada. Pode-se dizer que os zeros não triviais representam as &amp;ldquo;frequências (ondas)&amp;rdquo; da distribuição dos números primos.&lt;/p>
&lt;p>Se a Hipótese de Riemann estiver correta e a parte real de todos os zeros não triviais $\rho$ for exatamente $1/2$, o termo de erro do Teorema dos Números Primos ficará dentro da menor margem teoricamente possível.&lt;/p>
$$ |\pi(x) - \text{Li}(x)| \le \frac{1}{8\pi} \sqrt{x} \ln x \quad \text{for} \quad x \ge 2657 $$
&lt;p>Em outras palavras, &lt;strong>se a Hipótese de Riemann for verdadeira, fica provado que os números primos estão distribuídos da forma mais &amp;ldquo;ordenada e bela&amp;rdquo; que possamos imaginar&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h1 id="6-a-relação-inseparável-entre-a-criptografia-moderna-e-os-números-primos">6. A Relação Inseparável entre a Criptografia Moderna e os Números Primos
&lt;/h1>&lt;p>Até aqui estivemos no mundo profundo da matemática pura, mas essas propriedades dos números primos sustentam fundamentalmente a sociedade digital moderna. O exemplo mais representativo são os sistemas de criptografia de chave pública, como a &lt;strong>criptografia RSA&lt;/strong>.&lt;/p>
&lt;p>A segurança de todas as comunicações, como pagamentos com cartão de crédito na internet, transmissão de senhas e assinaturas digitais em blockchain, depende dos &amp;ldquo;números primos&amp;rdquo;.&lt;/p>
&lt;h3 id="como-funciona-a-criptografia-rsa">Como funciona a Criptografia RSA
&lt;/h3>&lt;p>A segurança da criptografia RSA é baseada no fato matemático (o problema de fatoração de inteiros) de que &amp;ldquo;a fatoração de um número composto com muitos dígitos é extremamente difícil&amp;rdquo;.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Geração de Chaves&lt;/strong>:
Escolhem-se aleatoriamente dois números primos gigantescos $p$ e $q$ (por exemplo, de 2048 bits cada).
Multiplicam-se ambos para calcular $N = p \times q$. Este $N$ se torna parte da chave pública.
Usando a função totiente de Euler $\phi(N) = (p-1)(q-1)$, gera-se a chave privada $d$.&lt;/p>
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Criptografia e Descriptografia&lt;/strong>:
O texto plano (plaintext) $M$ é convertido em um texto cifrado (ciphertext) $C$ usando a chave pública $e, N$.
&lt;/p>
$$ C \equiv M^e \pmod{N} $$
&lt;p>
Apenas aquele que possui a chave privada $d$ pode descriptografar.
&lt;/p>
$$ M \equiv C^d \pmod{N} $$
&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph LR
A["Texto plano (Plaintext)"] --> B["Criptografado com a chave pública (e, N)"]
B --> C["Texto cifrado (Ciphertext)"]
C --> D["Descriptografado com a chave privada (d)"]
D --> E["Texto plano original"]
F["Atacante (Attacker)"] -- "Tenta fatorar N" --> C
F -.-> G["Sem saber p e q, d é incalculável"]&lt;/div>
&lt;p>Para quebrar a criptografia RSA, é necessário encontrar os números primos originais $p$ e $q$ a partir do gigantesco $N$ (fatoração de primos). Mesmo usando os algoritmos predominantes atuais (como o Crivo do Corpo de Números Generalizado: GNFS), diz-se que fatorar um número de centenas de dígitos levaria um tempo que excede muito a idade do universo, mesmo utilizando supercomputadores.&lt;/p>
&lt;hr>
&lt;h1 id="7-o-impacto-da-hipótese-de-riemann-na-criptografia">7. O Impacto da Hipótese de Riemann na Criptografia
&lt;/h1>&lt;p>Então, como a &amp;ldquo;Hipótese de Riemann&amp;rdquo;, que está no ápice da matemática pura, cruza-se com a &amp;ldquo;criptografia&amp;rdquo;?&lt;/p>
&lt;h3 id="71-algoritmos-de-geração-de-números-primos-teste-de-primalidade-e-a-hipótese-generalizada-de-riemann-grh">7.1. Algoritmos de Geração de Números Primos (Teste de Primalidade) e a Hipótese Generalizada de Riemann (GRH)
&lt;/h3>&lt;p>Para operar a criptografia RSA, primeiro é necessário gerar os gigantescos números primos $p$ e $q$. No entanto, determinar de forma confiável e rápida &amp;ldquo;se um determinado número é primo&amp;rdquo; não é algo simples.&lt;/p>
&lt;p>Atualmente, o que é utilizado de forma prática é um algoritmo probabilístico chamado &lt;strong>teste de primalidade de Miller-Rabin (Miller-Rabin primality test)&lt;/strong>. Esse algoritmo é rápido, mas carrega o risco de classificar incorretamente, com uma probabilidade extremamente baixa, um número composto como primo, um chamado &amp;ldquo;pseudoprimo&amp;rdquo;.&lt;/p>
&lt;p>No entanto, assumindo que a &lt;strong>&amp;ldquo;Hipótese Generalizada de Riemann (Generalized Riemann Hypothesis, GRH)&amp;rdquo;&lt;/strong>, que estende a Hipótese de Riemann às funções L de Dirichlet, é verdadeira, a história muda drasticamente.&lt;/p>
&lt;p>Se a GRH for verdadeira, o limite superior do número de testes no teste de Miller-Rabin será matematicamente garantido, elevando-o de um algoritmo probabilístico para um &lt;strong>&amp;ldquo;algoritmo de tempo polinomial determinístico&amp;rdquo;&lt;/strong> (este era um fato crucial já conhecido antes da descoberta do teste de primalidade AKS).&lt;/p>
&lt;p>Em outras palavras, a Hipótese de Riemann (e sua generalização) desempenha o papel de dar uma garantia direta para a base da criptografia: &amp;ldquo;é possível gerar números primos gigantescos de forma rápida e com absoluta confiança?&amp;rdquo;.&lt;/p>
&lt;h3 id="72-relação-com-os-algoritmos-de-fatoração">7.2. Relação com os Algoritmos de Fatoração
&lt;/h3>&lt;p>Ao avaliar a complexidade computacional dos algoritmos usados para decifrar códigos (como o Crivo do Corpo de Números Generalizado), o conhecimento sobre a distribuição dos números primos também é indispensável. A maioria dos algoritmos de fatoração depende da distribuição de &amp;ldquo;números lisos (Smooth numbers: números que possuem apenas pequenos fatores primos)&amp;rdquo;.&lt;/p>
&lt;p>Para avaliar rigorosamente a frequência com que números lisos aparecem, é necessária uma profunda compreensão da distribuição dos números primos, e aqui também são plenamente utilizadas técnicas de teoria analítica dos números que se conectam diretamente à função zeta e à Hipótese de Riemann. Se a Hipótese de Riemann for provada e o erro na distribuição de primos for completamente determinado, será possível discernir os limites de desempenho dos algoritmos de fatoração de forma mais precisa.&lt;/p>
&lt;hr>
&lt;h1 id="8-se-a-hipótese-de-riemann-for-provada-a-criptografia-será-quebrada">8. Se a Hipótese de Riemann for Provada, a Criptografia será Quebrada?
&lt;/h1>&lt;p>Assim como uma lenda urbana, às vezes se diz que &amp;ldquo;se a Hipótese de Riemann for resolvida, a criptografia RSA desmoronará em um instante&amp;rdquo;, mas &lt;strong>isso é matematicamente impreciso&lt;/strong>.&lt;/p>
&lt;p>A prova da Hipótese de Riemann, por si só, não produzirá imediatamente um algoritmo mágico que acelera drasticamente a fatoração. Isso porque a Hipótese de Riemann é, em última análise, um teorema sobre os &amp;ldquo;padrões de distribuição macroscópicos&amp;rdquo; dos números primos, e não nos diz diretamente por quais números primos um número específico $N$ é divisível (uma propriedade local).&lt;/p>
&lt;p>No entanto, o impacto não é zero.
Isso porque é extremamente provável que, no processo de provar a Hipótese de Riemann, &lt;strong>&amp;ldquo;novas ferramentas matemáticas&amp;rdquo; e &amp;ldquo;métodos analíticos desconhecidos&amp;rdquo; sejam descobertos&lt;/strong>. Olhando para a história, quando o Último Teorema de Fermat ou a Conjectura de Poincaré foram provados, as novas teorias desenvolvidas no processo impulsionaram significativamente a matemática como um todo.&lt;/p>
&lt;p>Se for estabelecido um método desconhecido de geometria algébrica ou de geometria não-comutativa capaz de manipular completamente as propriedades dos zeros da função zeta de Riemann, não se pode negar a possibilidade de que isso leve à descoberta de um algoritmo de fatoração revolucionário (por exemplo, um algoritmo clássico que reduz a complexidade para o tempo polinomial). Nesse sentido, os criptógrafos nunca podem tirar os olhos dos desenvolvimentos da Hipótese de Riemann.&lt;/p>
&lt;h3 id="computadores-quânticos-e-o-algoritmo-de-shor">Computadores Quânticos e o Algoritmo de Shor
&lt;/h3>&lt;p>Uma ameaça mais direta e realista à criptografia não é a prova da Hipótese de Riemann, mas os &lt;strong>computadores quânticos&lt;/strong>. O &amp;ldquo;Algoritmo de Shor&amp;rdquo;, anunciado por Peter Shor em 1994, provou que, com um computador quântico de capacidade suficiente, a fatoração pode ser resolvida em tempo polinomial. Isso fundamentalmente quebraria a criptografia RSA e a criptografia de curva elíptica.&lt;/p>
&lt;p>Atualmente, ao redor do mundo, há uma transição em andamento para a &amp;ldquo;Criptografia Pós-Quântica (Post-Quantum Cryptography, PQC)&amp;rdquo; (como a criptografia baseada em reticulados), que não pode ser decifrada nem por computadores quânticos. As tecnologias de criptografia baseadas em números primos podem, de certa forma, estar encerrando sua era de ouro, mas o valor matemático dos números primos em si nunca se perderá.&lt;/p>
&lt;hr>
&lt;h1 id="9-conclusão-o-cruzamento-entre-a-abstração-da-matemática-e-o-mundo-real">9. Conclusão: O Cruzamento entre a Abstração da Matemática e o Mundo Real
&lt;/h1>&lt;div class="mermaid">graph TD
A["Exploração da matemática pura"] --> B["Esclarecimento da Hipótese de Riemann"]
B --> C["Compreensão completa da distribuição de números primos"]
C --> D["Avanço rápido na teoria dos números e geometria algébrica"]
D -.-> E["Possibilidade de novos algoritmos de fatoração"]
E -.-> F["Atualização na avaliação de segurança da criptografia"]
A --> G["Matemática aplicada e ciência da computação"]
G --> H["Eficiência no teste de primalidade e geração de códigos"]
H --> F&lt;/div>
&lt;p>A exploração insaciável dos números primos, que remonta à Grécia Antiga, foi sublimada por um gênio chamado Riemann em uma bela sinfonia no plano complexo (os zeros da função zeta). E, surpreendentemente, esse cristal de matemática pura e inocente foi aplicado séculos depois como o escudo mais forte para garantir a segurança da sociedade da internet.&lt;/p>
&lt;p>A Hipótese de Riemann é uma entidade que simboliza, simultaneamente, a &amp;ldquo;beleza abstrata&amp;rdquo; e a &amp;ldquo;incrível aplicabilidade ao mundo físico e à sociedade real&amp;rdquo; que a matemática possui.&lt;/p>
&lt;p>Quando esta montanha colossal da matemática, cujo cume ninguém ainda alcançou, for um dia conquistada, compreenderemos completamente a verdade cósmica dos números primos, e também ganharemos uma nova perspectiva sobre os alicerces da sociedade da informação. Estudar criptografia é, por si só, uma jornada pela história da sabedoria humana.&lt;/p></description></item><item><title>A História da Criptografia: Da Cifra de César à Criptografia Pós-Quântica (PQC)</title><link>http://kenji.blog/pt/p/history-of-cryptography-caesar-to-pqc/</link><pubDate>Fri, 11 Sep 2026 15:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/history-of-cryptography-caesar-to-pqc/</guid><description>&lt;img src="http://kenji.blog/p/history-of-cryptography-caesar-to-pqc/img/eyecatch.jpg" alt="Featured image of post A História da Criptografia: Da Cifra de César à Criptografia Pós-Quântica (PQC)" />&lt;h1 id="1-introdução-o-que-é-criptografia">1. Introdução: O que é Criptografia?
&lt;/h1>&lt;p>A criptografia (Cryptography) é uma tecnologia para preservar o sigilo das informações e tem evoluído junto com a história da humanidade. Desde a transmissão de comandos secretos em guerras antigas até a proteção de informações de cartão de crédito na internet moderna, o propósito da criptografia tem sido consistente. Consiste em &amp;ldquo;garantir que apenas os destinatários pretendidos possam entender as informações e que terceiros não consigam decifrá-las&amp;rdquo;.&lt;/p>
&lt;p>Na segurança da informação moderna, a tecnologia criptográfica não se limita apenas ao &amp;ldquo;sigilo da informação (Confidencialidade: Confidentiality)&amp;rdquo;, mas desempenha papéis cruciais como a &amp;ldquo;Integridade (Integrity)&amp;rdquo; dos dados, a &amp;ldquo;Autenticação (Authentication)&amp;rdquo; e o &amp;ldquo;Não-repúdio (Non-repudiation)&amp;rdquo;.&lt;/p>
&lt;p>Neste artigo, desvendaremos detalhadamente a história da evolução da tecnologia criptográfica a partir de uma perspectiva técnica e matemática, começando pelas simples cifras de substituição antigas, passando pelas cifras mecânicas, as modernas criptografias de chave simétrica e chave pública, e chegando à era da &amp;ldquo;Criptografia Pós-Quântica (PQC)&amp;rdquo; que surge com o uso prático dos computadores quânticos.&lt;/p>
&lt;hr>
&lt;h1 id="2-a-era-da-criptografia-clássica-substituição-e-transposição-de-letras">2. A Era da Criptografia Clássica: Substituição e Transposição de Letras
&lt;/h1>&lt;p>As origens da criptografia remontam antes de Cristo. As primeiras cifras consistiam principalmente em duas abordagens: &amp;ldquo;Transposição (reordenação)&amp;rdquo; e &amp;ldquo;Substituição (troca)&amp;rdquo;.&lt;/p>
&lt;h2 id="cifra-de-cítala-cifra-de-transposição">Cifra de Cítala (Cifra de Transposição)
&lt;/h2>&lt;p>O &amp;ldquo;Cítala (Scytale)&amp;rdquo;, usado em Esparta na Grécia Antiga no século V a.C., é um dos mais antigos instrumentos de criptografia. Uma tira longa e estreita de pergaminho era enrolada em um bastão de madeira de uma espessura específica, e a mensagem era escrita horizontalmente. Ao desenrolar a tira, as letras ficavam ordenadas de forma sem sentido, mas um destinatário com um bastão da mesma espessura poderia enrolar a tira novamente e ler a mensagem original.&lt;/p>
&lt;h2 id="cifra-de-césar-cifra-de-substituição-simples">Cifra de César (Cifra de Substituição Simples)
&lt;/h2>&lt;p>Diz-se que o herói romano antigo Júlio César usou a &amp;ldquo;Cifra de César&amp;rdquo; no século I a.C. Esta é uma cifra de substituição simples (Monoalphabetic substitution) onde o alfabeto é deslocado por um número fixo (geralmente 3 letras).&lt;/p>
&lt;p>Matematicamente, tratando as letras como números de $0$ a $25$ e o número de deslocamentos como $K$, a conversão do texto claro $P$ para o texto cifrado $C$ é expressa pela seguinte equação de congruência:&lt;/p>
$$C \equiv P + K \pmod{26}$$
&lt;p>A decodificação realiza a operação inversa.&lt;/p>
$$P \equiv C - K \pmod{26}$$
&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;/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="c1"># Exemplo simples de implementação da Cifra de César em Python&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">caesar_cipher&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">shift&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">mode&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;encrypt&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">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&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">mode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;decrypt&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">shift&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">shift&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">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">text&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">char&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isalpha&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;A&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">char&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isupper&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;a&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="c1"># Cálculo do deslocamento&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="nb">chr&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="o">-&lt;/span> &lt;span class="n">base&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">shift&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">26&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">base&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">result&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">char&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>&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="n">plaintext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;HELLO WORLD&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">caesar_cipher&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">plaintext&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;encrypt&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;Texto cifrado: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># KHOOR ZRUOG&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="análise-de-frequência-e-cifra-de-vigenère">Análise de Frequência e Cifra de Vigenère
&lt;/h2>&lt;p>As cifras de substituição simples tornaram-se facilmente decifráveis através da &amp;ldquo;Análise de Frequência (Frequency Analysis)&amp;rdquo;, inventada pelo estudioso árabe Al-Kindi no século IX. Ela se aproveita das propriedades estatísticas da linguagem, onde letras como &amp;ldquo;E&amp;rdquo; ou &amp;ldquo;T&amp;rdquo; aparecem com frequência, no caso do inglês.&lt;/p>
&lt;p>Para combater isso, a &amp;ldquo;Cifra de Vigenère (Vigenère cipher)&amp;rdquo; foi concebida no século XVI. Esta é uma cifra de substituição polialfabética (Polyalphabetic substitution) que usa múltiplos deslocamentos (chaves) alternados periodicamente e foi chamada de &amp;ldquo;cifra indecifrável (Le Chiffre Indéchiffrable)&amp;rdquo; por cerca de 300 anos.&lt;/p>
&lt;p>Matematicamente, a $i$-ésima letra do texto claro $P_i$ e a $i$-ésima letra da chave repetida $K_i$ são usadas para criptografar da seguinte forma:&lt;/p>
$$C_i \equiv P_i + K_i \pmod{26}$$
&lt;p>Essa cifra também veio a ser decifrada no século XIX por Charles Babbage e Friedrich Kasiski, através da descoberta do &amp;ldquo;Exame de Kasiski (Kasiski examination)&amp;rdquo;, que determina o tamanho da chave a partir de padrões repetitivos no texto cifrado.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Classificação da Criptografia Clássica"
A["Criptografia Clássica"] --> B["Cifra de Transposição"]
A --> C["Cifra de Substituição"]
B --> D["Cifra de Cítala"]
C --> E["Substituição Simples"]
C --> F["Substituição Polialfabética"]
E --> G["Cifra de César"]
F --> H["Cifra de Vigenère"]
end&lt;/div>
&lt;hr>
&lt;h1 id="3-criptografia-mecânica-e-as-guerras-mundiais-enigma-e-sua-decodificação">3. Criptografia Mecânica e as Guerras Mundiais: Enigma e sua Decodificação
&lt;/h1>&lt;p>Ao entrarmos no século XX, os meios de comunicação mudaram das cartas para o telégrafo e o rádio, passando a exigir velocidade e complexidade na criptografia. Foi aqui que surgiu a &amp;ldquo;criptografia mecânica&amp;rdquo;, combinando rotores (discos rotativos).&lt;/p>
&lt;h2 id="a-ameaça-da-enigma-enigma">A Ameaça da Enigma (Enigma)
&lt;/h2>&lt;p>A &amp;ldquo;Enigma&amp;rdquo;, usada pela Alemanha Nazista durante a Segunda Guerra Mundial, é a máquina de criptografia mais famosa na história da tecnologia criptográfica. A Enigma consistia em múltiplos rotores (geralmente de 3 a 4), um painel de conexões (Steckerbrett) para trocar o cabeamento das letras, e um refletor (rotor reverso).&lt;/p>
&lt;p>Como o rotor girava a cada vez que uma letra era digitada no teclado, mesmo que a mesma letra fosse digitada consecutivamente, um caractere cifrado diferente era produzido (o auge da criptografia polialfabética). O seu espaço de chaves (combinações de configurações) chegava a cerca de $1.58 \times 10^{19}$ (aproximadamente 15,8 quintilhões), e com a tecnologia da época, a decodificação por força bruta era considerada impossível.&lt;/p>
&lt;h2 id="alan-turing-e-a-bombe-bombe">Alan Turing e a &amp;ldquo;Bombe (Bombe)&amp;rdquo;
&lt;/h2>&lt;p>A equipe de decodificação de códigos de Bletchley Park, no Reino Unido, que se baseou nos resultados iniciais do matemático polonês Marian Rejewski e outros, desafiou essa Enigma inexpugnável.&lt;/p>
&lt;p>Particularmente, Alan Turing usou a suposição de texto claro (Crib) correspondente a parte do texto cifrado e desenvolveu a máquina de decodificação eletromecânica &amp;ldquo;Bombe&amp;rdquo;. A Bombe detectava rapidamente contradições lógicas e eliminava configurações impossíveis de rotores uma após a outra, obtendo sucesso na decodificação da Enigma. Diz-se que essa grande conquista adiantou a vitória dos Aliados em vários anos.&lt;/p>
&lt;hr>
&lt;h1 id="4-o-início-da-criptografia-moderna-criptografia-de-chave-simétrica-des-e-aes">4. O Início da Criptografia Moderna: Criptografia de Chave Simétrica (DES e AES)
&lt;/h1>&lt;p>No pós-guerra, com o advento dos computadores, a criptografia passou por uma mudança drástica de paradigma, da manipulação de &amp;ldquo;letras&amp;rdquo; para a manipulação de &amp;ldquo;bits (0 e 1)&amp;rdquo;.&lt;/p>
&lt;h2 id="claude-shannon-e-a-teoria-da-informação">Claude Shannon e a Teoria da Informação
&lt;/h2>&lt;p>Em 1949, Claude Shannon publicou o artigo &amp;ldquo;Teoria da Comunicação de Sistemas Secretos&amp;rdquo;, estabelecendo os fundamentos matemáticos da criptografia moderna. Ele propôs a &amp;ldquo;Confusão (Confusion)&amp;rdquo; e a &amp;ldquo;Difusão (Diffusion)&amp;rdquo; como princípios para um design criptográfico seguro.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Confusão (Confusion)&lt;/strong>: Tornar a relação entre a chave e o texto cifrado o mais complexa possível. (Realizado por substituição / S-boxes)&lt;/li>
&lt;li>&lt;strong>Difusão (Diffusion)&lt;/strong>: Fazer com que a alteração de 1 bit do texto claro afete muitos bits do texto cifrado. (Realizado por transposição / permutação)&lt;/li>
&lt;/ul>
&lt;h2 id="des-data-encryption-standard">DES (Data Encryption Standard)
&lt;/h2>&lt;p>Em 1977, o Instituto Nacional de Padrões e Tecnologia dos EUA (NIST, então NBS) estabeleceu o &amp;ldquo;DES&amp;rdquo;, baseado no design da IBM, como o padrão de criptografia.
O DES adota uma arquitetura chamada &amp;ldquo;Rede de Feistel (Feistel Network)&amp;rdquo;, possuindo um tamanho de bloco de 64 bits e um tamanho de chave de 56 bits. Havia uma vantagem na implementação onde o algoritmo de criptografia e decodificação possuíam quase a mesma estrutura.&lt;/p>
&lt;p>No entanto, à medida que o poder de computação melhorava, tornou-se claro que um tamanho de chave de 56 bits (cerca de $7.2 \times 10^{16}$ possibilidades) era insuficiente. Em 1998, a Electronic Frontier Foundation (EFF) desenvolveu uma máquina dedicada, a &amp;ldquo;Deep Crack&amp;rdquo;, e demonstrou a quebra do DES em poucos dias.&lt;/p>
&lt;h2 id="aes-advanced-encryption-standard">AES (Advanced Encryption Standard)
&lt;/h2>&lt;p>Como um novo padrão para substituir o DES, o &amp;ldquo;AES&amp;rdquo; foi estabelecido em 2001. O algoritmo &amp;ldquo;Rijndael&amp;rdquo;, criado por criptógrafos belgas selecionado através de um concurso público, foi adotado.&lt;/p>
&lt;p>O AES não utiliza a Rede de Feistel, mas sim a &amp;ldquo;Estrutura SPN (Substitution-Permutation Network)&amp;rdquo;, e utiliza operações matemáticas sobre o Campo de Galois (campo finito) $GF(2^8)$. O tamanho da chave pode ser selecionado entre 128, 192 e 256 bits, e ainda hoje é amplamente utilizado como o padrão de criptografia de chave simétrica em todo o mundo.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Processo de 1 round do AES (Estrutura SPN)"
A["Estado de entrada (128-bit)"] --> B("SubBytes (Substituição de bytes / S-Box)")
B --> C("ShiftRows (Deslocamento de linhas)")
C --> D("MixColumns (Mistura de colunas / Multiplicação em GF(2^8))")
D --> E("AddRoundKey (XOR com a chave da rodada)")
E --> F["Para a próxima rodada"]
end&lt;/div>
&lt;hr>
&lt;h1 id="5-a-revolução-da-criptografia-de-chave-pública-de-diffie-hellman-a-rsa">5. A Revolução da Criptografia de Chave Pública: De Diffie-Hellman a RSA
&lt;/h1>&lt;p>A criptografia de chave simétrica possuía uma fraqueza decisiva. Trata-se do &amp;ldquo;Problema de Distribuição de Chaves (Key Distribution Problem)&amp;rdquo;. É o problema de como compartilhar de forma segura uma &amp;ldquo;chave comum&amp;rdquo; com uma parte distante antes de iniciar a comunicação criptografada. Este problema foi resolvido pela &amp;ldquo;Criptografia de Chave Pública&amp;rdquo;, nascida na década de 1970.&lt;/p>
&lt;h2 id="troca-de-chaves-de-diffie-hellman">Troca de Chaves de Diffie-Hellman
&lt;/h2>&lt;p>Em 1976, Whitfield Diffie e Martin Hellman publicaram o artigo revolucionário &amp;ldquo;New Directions in Cryptography&amp;rdquo;. Eles utilizaram a dificuldade matemática chamada &amp;ldquo;Problema do Logaritmo Discreto (Discrete Logarithm Problem)&amp;rdquo; e propuseram um método para compartilhar chaves de forma segura, mesmo em canais de comunicação interceptados.&lt;/p>
&lt;ol>
&lt;li>Um número primo grande $p$ e um gerador $g$ são tornados públicos.&lt;/li>
&lt;li>Alice escolhe um valor secreto $a$ e envia $A = g^a \pmod{p}$ para Bob.&lt;/li>
&lt;li>Bob escolhe um valor secreto $b$ e envia $B = g^b \pmod{p}$ para Alice.&lt;/li>
&lt;li>Alice calcula $K = B^a \pmod{p}$, e Bob calcula $K = A^b \pmod{p}$.&lt;/li>
&lt;li>Pelas leis dos expoentes, $K = (g^b)^a = (g^a)^b = g^{ab} \pmod{p}$, e assim, de forma brilhante, eles podem compartilhar a mesma chave $K$.&lt;/li>
&lt;/ol>
&lt;h2 id="criptografia-rsa">Criptografia RSA
&lt;/h2>&lt;p>No ano seguinte, em 1977, a &amp;ldquo;Criptografia RSA&amp;rdquo; foi concebida por Ron Rivest, Adi Shamir e Leonard Adleman. Ela baseia-se na propriedade de que &amp;ldquo;a fatoração de números compostos gigantes é difícil&amp;rdquo;.&lt;/p>
&lt;p>&lt;strong>Mecanismo matemático do RSA:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Escolhem-se 2 números primos gigantes $p$ e $q$, e calcula-se $n = p \times q$.&lt;/li>
&lt;li>Calcula-se a função totiente de Euler $\phi(n) = (p-1)(q-1)$.&lt;/li>
&lt;li>Escolhe-se um número inteiro $e$ (chave pública) que seja coprimo de $\phi(n)$.&lt;/li>
&lt;li>Calcula-se um número inteiro $d$ (chave privada) tal que $e \times d \equiv 1 \pmod{\phi(n)}$.&lt;/li>
&lt;/ol>
&lt;p>Criptografia: Para o texto claro $M$, $C \equiv M^e \pmod{n}$
Decodificação: Para o texto cifrado $C$, $M \equiv C^d \pmod{n}$&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="c1"># Código Python demonstrando o conceito da criptografia RSA (não para uso prático)&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">ext_euclid&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="c1"># Cálculo do inverso modular pelo algoritmo de Euclides estendido&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">b&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="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">x&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">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ext_euclid&lt;/span>&lt;span class="p">(&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 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">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="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 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">g&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">rsa_example&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Exemplo usando números primos pequenos&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&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">61&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">53&lt;/span>
&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="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">17&lt;/span> &lt;span class="c1"># Valor coprimo de phi&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">_&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ext_euclid&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">d&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">d&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="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=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, n=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&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=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, n=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&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 e decodificação de uma mensagem&lt;/span>
&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="mi">65&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decrypted&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ciphertext&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="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Texto claro: &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;gt; Texto cifrado: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ciphertext&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> -&amp;gt; Após decodificação: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted&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">rsa_example&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;h1 id="6-a-ascensão-da-criptografia-de-curva-elíptica-ecc">6. A Ascensão da Criptografia de Curva Elíptica (ECC)
&lt;/h1>&lt;p>A criptografia RSA é forte, mas com a melhoria no desempenho dos computadores, tornou-se necessário aumentar o tamanho da chave para manter a segurança (atualmente 2048 bits ou 3072 bits), o que gerou o problema do aumento do custo computacional.&lt;/p>
&lt;p>Portanto, em 1985 foi proposta a &amp;ldquo;Criptografia de Curva Elíptica (Elliptic Curve Cryptography: ECC)&amp;rdquo;. Isso utiliza a adição de pontos em uma curva elíptica sobre um campo finito (geralmente na forma de $y^2 = x^3 + ax + b$).&lt;/p>
&lt;p>Sabe-se que o Problema do Logaritmo Discreto em Curvas Elípticas (ECDLP) é ainda mais difícil de resolver do que o problema da fatoração de primos, e &lt;strong>o ECC pode alcançar a mesma segurança que o RSA de 3072 bits com um tamanho de chave de apenas 256 bits&lt;/strong>. Isso possibilitou uma comunicação criptografada de alta velocidade e segurança (como ECDSA e ECDH) até mesmo em ambientes com recursos computacionais limitados, como smartphones e dispositivos IoT.&lt;/p>
&lt;hr>
&lt;h1 id="7-a-ameaça-dos-computadores-quânticos-e-a-criptografia-pós-quântica-pqc">7. A Ameaça dos Computadores Quânticos e a Criptografia Pós-Quântica (PQC)
&lt;/h1>&lt;p>A tecnologia criptográfica parecia sólida, mas em 1994, o &amp;ldquo;Algoritmo de Shor&amp;rdquo; publicado por Peter Shor causou um grande impacto.&lt;/p>
&lt;p>Os computadores quânticos realizam cálculos utilizando as propriedades da mecânica quântica de &amp;ldquo;superposição&amp;rdquo; e &amp;ldquo;emaranhamento quântico&amp;rdquo;. Foi matematicamente provado que a execução do algoritmo de Shor em um computador quântico de desempenho suficiente pode resolver o problema de fatoração de primos e o problema do logaritmo discreto em &amp;ldquo;tempo polinomial&amp;rdquo;. Ou seja, no dia em que um computador quântico prático for concluído (Q-Day), as criptografias de chave pública usadas atualmente, como RSA e ECC, serão corrompidas instantaneamente.&lt;/p>
&lt;h2 id="o-surgimento-da-pqc-post-quantum-cryptography">O Surgimento da PQC (Post-Quantum Cryptography)
&lt;/h2>&lt;p>Em preparação para esta ameaça sem precedentes, pesquisas em &amp;ldquo;Criptografia Pós-Quântica (PQC)&amp;rdquo;, baseada em novos problemas matemáticos difíceis de resolver mesmo para computadores quânticos, estão avançando a passos largos. O NIST (Instituto Nacional de Padrões e Tecnologia dos EUA) tem conduzido um processo de padronização da PQC ao longo de muitos anos, e as seguintes abordagens matemáticas são consideradas as mais promissoras.&lt;/p>
&lt;h3 id="1-criptografia-baseada-em-reticulados-lattice-based-cryptography">1. Criptografia Baseada em Reticulados (Lattice-based Cryptography)
&lt;/h3>&lt;p>Atualmente é a abordagem mais promissora, sendo também adotada nos algoritmos de padronização do NIST (ML-KEM / Kyber, ML-DSA / Dilithium). Ela baseia-se na dificuldade de encontrar pontos específicos (como o Problema do Vetor Mais Curto: SVP) em &amp;ldquo;reticulados (Lattice)&amp;rdquo; no espaço multidimensional e no problema LWE (Learning With Errors: Aprendizado Com Erros).&lt;/p>
&lt;p>O conceito do problema LWE aproveita a propriedade de que se um &amp;ldquo;pequeno ruído (erro)&amp;rdquo; for adicionado intencionalmente a um sistema de equações lineares simultâneas, de repente torna-se difícil encontrar a solução.
Sistema de equações: $\mathbf{A}\mathbf{s} + \mathbf{e} \equiv \mathbf{b} \pmod{q}$
($\mathbf{A}$ e $\mathbf{b}$ são públicos, $\mathbf{s}$ é a chave privada, $\mathbf{e}$ é o ruído minúsculo)&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;/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="c1"># Pseudo-código conceitual do problema LWE (Para fins educacionais)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&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="mi">256&lt;/span> &lt;span class="c1"># Dimensão&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="mi">3329&lt;/span> &lt;span class="c1"># Módulo&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">512&lt;/span> &lt;span class="c1"># Número de equações&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 privada s e pequeno erro e&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&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">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&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 class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&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="o">-&lt;/span>&lt;span class="mi">1&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">size&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Matriz pública A e vetor público b&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">np&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">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">m&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 class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dot&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">s&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Mesmo utilizando um computador quântico, é considerado extremamente difícil recuperar s a partir de A e b&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="2-criptografia-baseada-em-hash-hash-based-cryptography">2. Criptografia Baseada em Hash (Hash-based Cryptography)
&lt;/h3>&lt;p>É um esquema de assinatura digital que baseia a sua segurança unicamente na resistência a colisões de funções hash. Por não possuir uma estrutura matemática, é forte contra ataques quânticos, mas tende a ter tamanhos de assinatura grandes (como SPHINCS+).&lt;/p>
&lt;h3 id="3-criptografia-baseada-em-código-code-based-cryptography">3. Criptografia Baseada em Código (Code-based Cryptography)
&lt;/h3>&lt;p>É um sistema criptográfico baseado na teoria de códigos de correção de erros. A Criptografia de McEliece, proposta em 1978, é famosa; possui uma longa história e uma segurança estabelecida, mas tem o desafio de que o tamanho da chave pública é extremamente grande (podendo chegar a vários megabytes).&lt;/p>
&lt;div class="mermaid">timeline
title "História da Evolução da Criptografia e dos Computadores"
"Antiguidade - Idade Média" : "Cifra de César" : "Cifra de Vigenère" : "Nascimento da Análise de Frequência"
"Anos 1930 - 1940" : "Operação e Decodificação da Enigma" : "Máquina de Turing - Desenvolvimento da Bombe"
"Anos 1970" : "Padronização do DES (1977)" : "Troca de Chaves de Diffie-Hellman (1976)" : "Nascimento da Criptografia RSA (1977)"
"Anos 1980 - 1990" : "Proposta da Criptografia de Curva Elíptica (ECC)" : "Publicação do Algoritmo de Shor (1994)"
"Anos 2000" : "Padronização do AES (2001)"
"Anos 2010 - Atualidade" : "Aceleração da Pesquisa em Computadores Quânticos" : "Início do Projeto de Padronização PQC pelo NIST"
"Futuro Próximo (Q-Day)" : "Realização do Computador Quântico em Larga Escala?" : "Transição Completa para PQC (ML-KEM/ML-DSA)"&lt;/div>
&lt;hr>
&lt;h1 id="8-conclusão-uma-batalha-interminável-de-escudos-e-lanças">8. Conclusão: Uma Batalha Interminável de Escudos e Lanças
&lt;/h1>&lt;p>A história da tecnologia criptográfica é a história de uma batalha interminável entre a invenção de novos esquemas de criptografia (escudos) e os novos métodos de decodificação que os quebram (lanças).&lt;/p>
&lt;p>A Cifra de César foi derrotada pela análise de frequência, e a outrora invencível Enigma foi derrotada pelo gênio de Turing e o poder das máquinas. E agora, as fortes criptografias como RSA e ECC, que sustentam as bases da sociedade moderna da internet, estão sob a ameaça da nova &amp;ldquo;lança&amp;rdquo;, que é o computador quântico.&lt;/p>
&lt;p>No entanto, a humanidade já vislumbra o futuro e está se preparando para o novo &amp;ldquo;escudo&amp;rdquo;, a Criptografia Pós-Quântica (PQC). Atualmente, as preparações para a transição (Garantia de Agilidade Criptográfica - Crypto Agility) das criptografias de chave pública existentes para a PQC em infraestruturas de TI ao redor do mundo são uma questão de urgência.&lt;/p>
&lt;p>A tecnologia criptográfica não é apenas um quebra-cabeça matemático obscuro, mas sim a barreira mais forte para proteger nossa privacidade, nossas propriedades e as próprias infraestruturas da sociedade.&lt;/p></description></item><item><title>【Explicação de Matemática】Explicando o mecanismo da criptografia RSA para que até alunos do ensino médio entendam</title><link>http://kenji.blog/pt/p/rsa-encryption-math-explained-for-beginners/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/rsa-encryption-math-explained-for-beginners/</guid><description>&lt;img src="http://kenji.blog/p/rsa-encryption-math-explained-for-beginners/img/eyecatch.jpg" alt="Featured image of post 【Explicação de Matemática】Explicando o mecanismo da criptografia RSA para que até alunos do ensino médio entendam" />&lt;p>Uma das tecnologias que sustenta a segurança da nossa sociedade baseada na internet desde a sua base é a &amp;ldquo;Criptografia RSA&amp;rdquo;. Muitas das comunicações que usamos casualmente todos os dias, como pagamentos com cartão de crédito em compras online, troca de mensagens em redes sociais com amigos, ou o envio e recebimento de informações confidenciais de empresas, são protegidas pela criptografia RSA e suas tecnologias sucessoras.&lt;/p>
&lt;p>No entanto, ao ouvir a palavra &amp;ldquo;criptografia&amp;rdquo;, você pode imaginar máquinas de cifra complexas como as que aparecem em filmes de espionagem, ou uma matemática super avançada que apenas alguns gênios conseguem entender. É verdade que a teoria criptográfica moderna é baseada em matemática avançada, mas &lt;strong>o mecanismo fundamental da criptografia RSA pode ser plenamente compreendido com o conhecimento de matemática ensinado no ensino médio (propriedades de números inteiros, números primos, congruências, etc.)&lt;/strong>.&lt;/p>
&lt;p>Neste artigo, usaremos o conhecimento da matemática do ensino médio como ponto de partida para explicar passo a passo e de forma aprofundada os princípios matemáticos pelos quais a criptografia RSA funciona e por que é tão difícil de quebrar. Explicarei cuidadosamente usando exemplos concretos para que mesmo aqueles que têm um pouco de dificuldade com matemática possam entender.&lt;/p>
&lt;hr>
&lt;h2 id="1-criptografia-de-chave-simétrica-e-criptografia-de-chave-pública">1. Criptografia de Chave Simétrica e Criptografia de Chave Pública
&lt;/h2>&lt;p>Antes de mergulhar no mecanismo matemático da criptografia RSA, vamos primeiro revisar a ideia básica de criptografia. Os métodos criptográficos podem ser amplamente divididos em dois tipos: &amp;ldquo;Criptografia de chave simétrica&amp;rdquo; e &amp;ldquo;Criptografia de chave pública&amp;rdquo;.&lt;/p>
&lt;h3 id="11-limitações-da-criptografia-de-chave-simétrica">1.1 Limitações da Criptografia de Chave Simétrica
&lt;/h3>&lt;p>Muitos dos métodos de criptografia usados há muito tempo são chamados de &amp;ldquo;Criptografia de chave simétrica&amp;rdquo;. Este é um método em que &lt;strong>a mesma chave é usada tanto para &amp;ldquo;criptografia&amp;rdquo; (converter uma mensagem em um texto cifrado secreto) quanto para &amp;ldquo;descriptografia&amp;rdquo; (retornar o texto cifrado à mensagem original)&lt;/strong>.&lt;/p>
&lt;p>Por exemplo, suponha que a Alice vá enviar uma carta secreta ao Bob. A Alice coloca a carta em uma caixa e a tranca usando um cadeado (chave simétrica). Para o Bob abrir essa caixa, ele precisará ter a mesma chave que a Alice usou.&lt;/p>
&lt;p>Este método tem um grande problema: o &amp;ldquo;Problema de distribuição de chaves&amp;rdquo;. Quando Alice e Bob, que estão distantes, se comunicam pela primeira vez, como eles poderiam compartilhar a chave sem serem interceptados? Se a chave for roubada por terceiros enquanto é enviada por correio, toda a comunicação criptografada subsequente ficará totalmente exposta.&lt;/p>
&lt;h3 id="12-uma-invenção-revolucionária-criptografia-de-chave-pública">1.2 Uma Invenção Revolucionária: &amp;ldquo;Criptografia de Chave Pública&amp;rdquo;
&lt;/h3>&lt;p>A &amp;ldquo;Criptografia de chave pública&amp;rdquo; foi idealizada para resolver esse problema de distribuição de chaves. A criptografia RSA é um tipo deste sistema.&lt;/p>
&lt;p>Na criptografia de chave pública, usamos &lt;strong>duas chaves diferentes: uma &amp;ldquo;chave para criptografar (chave pública)&amp;rdquo; e uma &amp;ldquo;chave para descriptografar (chave privada)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>O destinatário, Bob, cria um par de &amp;ldquo;chave pública&amp;rdquo; e &amp;ldquo;chave privada&amp;rdquo;.&lt;/li>
&lt;li>Bob publica a &amp;ldquo;chave pública&amp;rdquo; para todo o mundo (não importa quem a obtenha).&lt;/li>
&lt;li>A remetente, Alice, criptografa a mensagem usando a &amp;ldquo;chave pública&amp;rdquo; de Bob e a envia.&lt;/li>
&lt;li>A mensagem criptografada só pode ser descriptografada com a &amp;ldquo;chave privada&amp;rdquo; que apenas Bob possui.&lt;/li>
&lt;/ol>
&lt;p>Comparando isso com o exemplo do cadeado: Bob cria vários &amp;ldquo;cadeados abertos (chaves públicas)&amp;rdquo; e os distribui pelo mundo. Alice coloca sua mensagem destinada a Bob em uma caixa e a tranca fechando um dos cadeados que encontrou pertencente a Bob. Uma vez que o cadeado é fechado, ele só pode ser aberto com a &amp;ldquo;chave mestra (chave privada)&amp;rdquo; que Bob possui. Mesmo que alguém roube a caixa no meio do caminho, essa pessoa não conseguirá abri-la porque não tem a chave mestra.&lt;/p>
&lt;div class="mermaid">graph TD
A["Alice (Remetente)"] --> B["Texto Plano (Mensagem)"]
B --> C["Processo de Criptografia"]
D["Chave Pública do Bob (Disponível para qualquer um)"] --> C
C --> E["Enviado via Internet: Texto Cifrado"]
E --> F["Processo de Descriptografia"]
G["Chave Privada do Bob (Mantida apenas pelo Bob)"] --> F
F --> H["Texto Plano Restaurado (Mensagem)"]
H --> I["Bob (Destinatário)"]&lt;/div>
&lt;p>Para implementar este sistema revolucionário, é necessária algum tipo de &lt;strong>&amp;ldquo;função unidirecional (um quebra-cabeça matemático de mão única)&amp;rdquo;&lt;/strong>, que significa que &amp;ldquo;é fácil criptografar com a chave pública, mas é absolutamente impossível descriptografar sem a chave privada&amp;rdquo;. Como peça para esse quebra-cabeça, a atenção se voltou para os &amp;ldquo;números primos&amp;rdquo;, algo que conhecemos bem.&lt;/p>
&lt;hr>
&lt;h2 id="2-base-matemática-1-sustentando-a-criptografia-rsa-números-primos-e-fatoração-em-números-primos">2. Base Matemática 1 Sustentando a Criptografia RSA: Números Primos e Fatoração em Números Primos
&lt;/h2>&lt;p>A segurança da criptografia RSA é baseada no fato matemático de que &lt;strong>&amp;ldquo;a fatoração de números gigantes em números primos é extremamente difícil&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="21-o-que-são-números-primos">2.1 O que são Números Primos?
&lt;/h3>&lt;p>Os números primos são &amp;ldquo;números naturais maiores que 1 que só podem ser divididos por 1 e por si mesmos&amp;rdquo;.
Exemplo: $2, 3, 5, 7, 11, 13, 17, 19, 23...$&lt;/p>
&lt;p>Os números primos são como &amp;ldquo;átomos&amp;rdquo; para todos os números inteiros. Qualquer número natural pode ser decomposto na forma de uma multiplicação de números primos. Isso é chamado de &lt;strong>fatoração em números primos&lt;/strong>. Por exemplo, como em $60 = 2^2 \times 3 \times 5$, ignorando a ordem, o fato de que pode ser fatorado em números primos de apenas uma única forma é conhecido como o &amp;ldquo;Teorema Fundamental da Aritmética&amp;rdquo;.&lt;/p>
&lt;h3 id="22-a-dificuldade-da-fatoração-em-números-primos-função-unidirecional">2.2 A Dificuldade da Fatoração em Números Primos (Função Unidirecional)
&lt;/h3>&lt;p>O importante aqui é a assimetria: &lt;strong>&amp;ldquo;A multiplicação é fácil, mas a fatoração em números primos é difícil&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Por exemplo, tente calcular de cabeça a multiplicação destes dois números primos:
$11 \times 13 = ?$
Isto é fácil. A resposta é $143$.&lt;/p>
&lt;p>Então, que tal o próximo número?
Por favor, fatore $323$ em números primos.
E então? Deve demorar um pouco. (A resposta é $17 \times 19$).&lt;/p>
&lt;p>Quando os números são pequenos, até humanos conseguem calcular de alguma forma, mas quando os números ficam grandes, o cálculo se torna explosivamente difícil, mesmo usando computadores. Na criptografia RSA moderna, usamos um número $N = p \times q$ obtido pela multiplicação de números primos incrivelmente gigantes $p$ e $q$ de 2048 bits (cerca de 600 dígitos decimais).&lt;/p>
&lt;p>Quando fornecidos dois números primos gigantes $p$ e $q$, calcular $N$ leva apenas um instante (menos de um milissegundo) para um computador. No entanto, reversamente, receber apenas $N$ e encontrar os $p$ e $q$ originais leva tanto tempo que não seria resolvido mesmo rodando os supercomputadores mais rápidos da atualidade por trilhões de anos.&lt;/p>
&lt;p>Essa &lt;strong>&amp;ldquo;assimetria computacional (um caminho é fácil, o caminho inverso é difícil)&amp;rdquo;&lt;/strong> é a base que cria o relacionamento entre a chave pública e a chave privada.&lt;/p>
&lt;hr>
&lt;h2 id="3-base-matemática-2-sustentando-a-criptografia-rsa-congruência-aritmética-modular">3. Base Matemática 2 Sustentando a Criptografia RSA: Congruência (Aritmética Modular)
&lt;/h2>&lt;p>Os cálculos da criptografia RSA não são realizados com adição e multiplicação onde os números ficam infinitamente grandes, como costumamos usar, mas sim no mundo dos &amp;ldquo;restos&amp;rdquo; quando divididos por um certo número. Isso é chamado de &lt;strong>congruência (aritmética modular)&lt;/strong>.&lt;/p>
&lt;h3 id="31-a-matemática-do-relógio">3.1 A Matemática do Relógio
&lt;/h3>&lt;p>A aritmética modular é frequentemente comparada com a &amp;ldquo;matemática do relógio&amp;rdquo;. Supondo que agora são 10 horas, que horas serão daqui a 5 horas? $10 + 5 = 15$ horas, mas em um relógio normal de 12 horas, respondemos &amp;ldquo;3 horas&amp;rdquo;. Isso ocorre porque o resto de 15 dividido por 12 é 3.&lt;/p>
&lt;p>No mundo da matemática, isso é escrito da seguinte forma:
&lt;/p>
$$ 15 \equiv 3 \pmod{12} $$
&lt;p>
Lê-se &amp;ldquo;15 e 3 são congruentes módulo 12 (os restos quando divididos por 12 são iguais)&amp;rdquo;.&lt;/p>
&lt;h3 id="32-propriedades-básicas-da-congruência">3.2 Propriedades Básicas da Congruência
&lt;/h3>&lt;p>A congruência possui propriedades muito úteis e semelhantes a equações (igualdades $=$). Vamos assumir que o módulo (número pelo qual dividimos) é $N$.
Quando $a \equiv b \pmod N$ e $c \equiv d \pmod N$, o seguinte é verdadeiro:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Adição:&lt;/strong> $a + c \equiv b + d \pmod N$&lt;/li>
&lt;li>&lt;strong>Subtração:&lt;/strong> $a - c \equiv b - d \pmod N$&lt;/li>
&lt;li>&lt;strong>Multiplicação:&lt;/strong> $a \times c \equiv b \times d \pmod N$&lt;/li>
&lt;li>&lt;strong>Exponenciação:&lt;/strong> $a^k \equiv b^k \pmod N$ ($k$ é um número natural)&lt;/li>
&lt;/ol>
&lt;p>Particularmente importante é a propriedade da &amp;ldquo;exponenciação&amp;rdquo;. Isso significa que &lt;strong>&amp;ldquo;o resto de uma potência é igual à potência do resto&amp;rdquo;&lt;/strong>.
Por exemplo, imagine que você queira encontrar o resto de $7^{100}$ dividido por $5$. Seria muito difícil multiplicar o $7$ por ele mesmo 100 vezes e depois dividir por $5$, mas se usarmos a propriedade da congruência, como $7 \equiv 2 \pmod 5$, então $7^{100} \equiv 2^{100} \pmod 5$, permitindo simplificar drasticamente o cálculo. No mundo da criptografia lidamos com potências de números extremamente grandes, então essa propriedade é indispensável.&lt;/p>
&lt;hr>
&lt;h2 id="4-base-matemática-3-sustentando-a-criptografia-rsa-função-de-euler-e-teorema-de-euler">4. Base Matemática 3 Sustentando a Criptografia RSA: Função de Euler e Teorema de Euler
&lt;/h2>&lt;p>A partir daqui, entra a matemática mágica que forma o núcleo da criptografia RSA. Apresentamos o &amp;ldquo;Teorema de Euler&amp;rdquo;, que é uma generalização do &amp;ldquo;Pequeno Teorema de Fermat&amp;rdquo;.&lt;/p>
&lt;h3 id="41-a-função-totiente-de-euler-phin">4.1 A Função Totiente de Euler $\phi(N)$
&lt;/h3>&lt;p>A função totiente de Euler (função $\phi$) é uma função que, para um determinado número natural $N$, retorna &lt;strong>&amp;ldquo;a quantidade de números naturais de 1 até $N$ que são coprimos de $N$ (ou seja, seu máximo divisor comum é 1)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Vamos olhar alguns exemplos.&lt;/p>
&lt;ul>
&lt;li>$\phi(5)$: Dentre 1, 2, 3, 4, 5, os números coprimos de 5 são 1, 2, 3, 4; ou seja, 4 números. Portanto, $\phi(5) = 4$.&lt;/li>
&lt;li>$\phi(6)$: Dentre 1, 2, 3, 4, 5, 6, os números coprimos de 6 são 1, 5; ou seja, 2 números. Portanto, $\phi(6) = 2$.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[Propriedade especial no caso de números primos]&lt;/strong>
Quando $p$ é um número primo, todos os números de 1 até $p-1$ são coprimos de $p$. Logo,
&lt;/p>
$$ \phi(p) = p - 1 $$
&lt;p>&lt;strong>[Propriedade especial no caso de um produto de números primos]&lt;/strong>
Para dois números primos distintos $p$ e $q$, quando se estabelece que $N = p \times q$, $\phi(N)$ pode ser facilmente obtido pelo seguinte cálculo:
&lt;/p>
$$ \phi(N) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$
&lt;p>
Essa propriedade funciona como a &amp;ldquo;porta dos fundos secreta (alçapão)&amp;rdquo; na criptografia RSA. Alguém que conhece $p$ e $q$ (o criador das chaves) pode calcular $\phi(N)$ em um instante, mas um terceiro que conhece apenas $N$ não pode determinar $\phi(N)$ a menos que fatore $N$ em números primos.&lt;/p>
&lt;h3 id="42-teorema-de-euler">4.2 Teorema de Euler
&lt;/h3>&lt;p>Leonhard Euler usou esse $\phi(N)$ para provar o seguinte belo teorema.&lt;/p>
&lt;p>&lt;strong>Teorema de Euler:&lt;/strong>
Quando um inteiro $a$ e $N$ são coprimos, a seguinte congruência é verdadeira:
&lt;/p>
$$ a^{\phi(N)} \equiv 1 \pmod N $$
&lt;p>Isso é uma propriedade surpreendente que diz: &amp;ldquo;quando você multiplica um certo número $a$ por ele mesmo $\phi(N)$ vezes e divide por $N$, o resto será sempre $1$&amp;rdquo;. (Se $N$ for um número primo $p$, torna-se $a^{p-1} \equiv 1 \pmod p$, que é chamado de Pequeno Teorema de Fermat).&lt;/p>
&lt;p>Vamos transformar este Teorema de Euler. Multiplicamos ambos os lados por $a$ mais uma vez.
&lt;/p>
$$ a^{\phi(N) + 1} \equiv a \pmod N $$
&lt;p>Além disso, para qualquer número inteiro $k$, $a^{k \cdot \phi(N)}$ também será $1^k = 1$, de modo que a seguinte fórmula é válida:
&lt;/p>
$$ a^{k \cdot \phi(N) + 1} \equiv a \pmod N $$
&lt;p>Esta exata equação é o princípio fundamental que faz com que a mágica da criptografia RSA de &lt;strong>&amp;ldquo;retornar ao original quando descriptografada após criptografar&amp;rdquo;&lt;/strong> funcione.&lt;/p>
&lt;hr>
&lt;h2 id="5-algoritmo-da-criptografia-rsa-passos-para-geração-de-chaves-criptografia-e-descriptografia">5. Algoritmo da Criptografia RSA: Passos para Geração de Chaves, Criptografia e Descriptografia
&lt;/h2>&lt;p>Agora que temos o conhecimento básico, vamos olhar para os passos concretos da criptografia RSA. A criptografia RSA é dividida principalmente em três fases: &amp;ldquo;1. Geração de Chaves&amp;rdquo;, &amp;ldquo;2. Criptografia&amp;rdquo; e &amp;ldquo;3. Descriptografia&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Escolher os primos p, q"] --> A2["Calcular N = p × q"]
A1 --> A3["Calcular φ(N) = (p-1)(q-1)"]
A3 --> A4["Escolher e coprimo de φ(N)"]
A3 --> A5["Calcular d tal que e × d ≡ 1 (mod φ(N))"]
A2 --> A6["Chave Pública (N, e)"]
A4 --> A6
A5 --> A7["Chave Privada d"]
B1["2. Mensagem em Texto Plano M"] --> B2["Calcular C ≡ M^e (mod N)"]
A6 -.-> B2
B2 --> B3["Enviar Texto Cifrado C"]
B3 --> C1["3. Receber Texto Cifrado C"]
C1 --> C2["Calcular M ≡ C^d (mod N)"]
A7 -.-> C2
C2 --> C3["Obter a Mensagem em Texto Plano original M"]&lt;/div>
&lt;h3 id="51-geração-de-chaves-key-generation">5.1 Geração de Chaves (Key Generation)
&lt;/h3>&lt;p>Bob, o destinatário, gera sua &amp;ldquo;chave pública&amp;rdquo; e &amp;ldquo;chave privada&amp;rdquo;.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Seleção dos primos:&lt;/strong> Ele escolhe dois grandes números primos $p$ e $q$ aleatoriamente.&lt;/li>
&lt;li>&lt;strong>Cálculo do módulo $N$:&lt;/strong> Ele calcula $N = p \times q$. Este $N$ é tornado público.&lt;/li>
&lt;li>&lt;strong>Cálculo de $\phi(N)$:&lt;/strong> Ele calcula a função de Euler $\phi(N) = (p - 1)(q - 1)$. Este número é um segredo apenas do Bob.&lt;/li>
&lt;li>&lt;strong>Seleção da chave pública $e$:&lt;/strong> Ele escolhe um inteiro $e$ tal que $1 &lt; e &lt; \phi(N)$ e que $e$ seja coprimo de $\phi(N)$.&lt;/li>
&lt;li>&lt;strong>Cálculo da chave privada $d$:&lt;/strong> Ele encontra um inteiro $d$ que satisfaça a seguinte condição:
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
Isso significa &amp;ldquo;um número $d$ tal que, quando $e \times d$ é dividido por $\phi(N)$, o resto é $1$&amp;rdquo;.&lt;/li>
&lt;/ol>
&lt;p>Com isso, as chaves estão prontas.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Chave Pública:&lt;/strong> O par $(N, e)$. Publicado para todo o mundo.&lt;/li>
&lt;li>&lt;strong>Chave Privada:&lt;/strong> $d$. Jamais revelado a ninguém.&lt;/li>
&lt;/ul>
&lt;h3 id="52-criptografia-encryption">5.2 Criptografia (Encryption)
&lt;/h3>&lt;p>Suponha que Alice queira enviar uma mensagem secreta $M$ para Bob. (Assumimos que $M$ é um texto convertido em valor numérico, e que $0 \le M &lt; N$). Alice usa a chave pública do Bob, $(N, e)$, para fazer o seguinte cálculo:&lt;/p>
$$ C \equiv M^e \pmod N $$
&lt;p>Ela calcula &amp;ldquo;o resto $C$ obtido após elevar a mensagem $M$ à potência de $e$, e dividir por $N$&amp;rdquo;. Esse $C$ é o texto cifrado.&lt;/p>
&lt;h3 id="53-descriptografia-decryption">5.3 Descriptografia (Decryption)
&lt;/h3>&lt;p>Bob recebe o texto cifrado $C$. Bob usa sua chave privada $d$ para calcular o seguinte:&lt;/p>
$$ M \equiv C^d \pmod N $$
&lt;p>Ao calcular &amp;ldquo;o resto de elevar o texto cifrado $C$ à potência de $d$, e dividir por $N$&amp;rdquo;, incrivelmente a mensagem original $M$ é restaurada!&lt;/p>
&lt;hr>
&lt;h2 id="6-por-que-retorna-ao-original-na-descriptografia-prova-matemática">6. Por que retorna ao original na descriptografia? (Prova Matemática)
&lt;/h2>&lt;p>Você pode se perguntar: &amp;ldquo;Por que simplesmente elevar $C$ à potência de $d$ retorna ao $M$ original?&amp;rdquo;. Aqui, o &amp;ldquo;Teorema de Euler&amp;rdquo; mencionado anteriormente mostra o seu poder.&lt;/p>
&lt;p>Vamos substituir a equação de criptografia $C = M^e$ na equação de descriptografia $C^d \pmod N$.
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>Aqui, lembre-se do Passo 5 da Geração de Chaves. Ao criar $d$, Bob o escolheu de forma que $e \times d \equiv 1 \pmod{\phi(N)}$. Isso significa que &amp;ldquo;$ed$ é um múltiplo de $\phi(N)$ somado a $1$&amp;rdquo;. Podemos escrevê-lo da seguinte maneira, utilizando um inteiro $k$:
&lt;/p>
$$ ed = k \cdot \phi(N) + 1 $$
&lt;p>Substituímos isso no expoente e o decompomos usando as leis dos expoentes:
&lt;/p>
$$ M^{ed} = M^{k \cdot \phi(N) + 1} = M^{k \cdot \phi(N)} \times M^1 = (M^{\phi(N)})^k \times M $$
&lt;p>Aqui, assumindo que a mensagem $M$ e $N$ são coprimos, a partir do &lt;strong>Teorema de Euler&lt;/strong>, temos $M^{\phi(N)} \equiv 1 \pmod N$.
&lt;/p>
$$ (M^{\phi(N)})^k \times M \equiv 1^k \times M \equiv M \pmod N $$
&lt;p>Portanto, a seguinte equação é perfeitamente estabelecida:
&lt;/p>
$$ C^d \equiv M \pmod N $$
&lt;p>Como a Alice não conhece $d$, e o espião também não conhece $d$, apenas Bob, que possui $d$, consegue extrair o $M$ a partir de $C$.&lt;/p>
&lt;hr>
&lt;h2 id="7-exemplo-concreto-vamos-vivenciar-o-rsa-calculando-à-mão-usando-pequenos-números-primos">7. Exemplo Concreto: Vamos vivenciar o RSA calculando à mão usando pequenos números primos
&lt;/h2>&lt;p>Vamos tentar enviar uma comunicação criptografada de Alice para Bob usando números pequenos (números primos) de fato.&lt;/p>
&lt;p>&lt;strong>[Fase de Geração de Chaves do Bob]&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Escolhe-se dois números primos $p=11$, $q=13$.&lt;/li>
&lt;li>Calcula-se $N = 11 \times 13 = 143$.&lt;/li>
&lt;li>Calcula-se $\phi(N) = (11 - 1) \times (13 - 1) = 10 \times 12 = 120$.&lt;/li>
&lt;li>Escolhe-se uma chave pública $e$ coprima de $\phi(N)=120$. Aqui usaremos $e=7$.&lt;/li>
&lt;li>Calcula-se a chave privada $d$. Buscamos um $d$ que satisfaça $7 \times d \equiv 1 \pmod{120}$.
Na equação $7d = 120k + 1$, quando $k=6$, temos $721$, e $721 \div 7 = 103$.
Portanto, $d = 103$.&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Chave Pública: $(N=143, e=7)$&lt;/li>
&lt;li>Chave Privada: $d=103$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[Fase de Criptografia da Alice]&lt;/strong>
Suponha que ela queira enviar a mensagem $M = 9$.
Fórmula: $C \equiv 9^7 \pmod{143}$
$9^7 = 4.782.969$. Dividindo isso por 143, dá $33447$ com resto $48$.
O texto cifrado se tornou $C = 48$.&lt;/p>
&lt;p>&lt;strong>[Fase de Descriptografia do Bob]&lt;/strong>
Bob recebe o texto cifrado $C = 48$ e o descriptografa usando a chave privada $d = 103$.
Fórmula: $M \equiv 48^{103} \pmod{143}$
Se executarmos &lt;code>(48 ** 103) % 143&lt;/code> na calculadora, brilhantemente o resultado será &amp;ldquo;&lt;strong>9&lt;/strong>&amp;rdquo;! A mensagem original foi recebida com sucesso.&lt;/p>
&lt;hr>
&lt;h2 id="8-como-encontrar-a-chave-privada-d-algoritmo-de-euclides-estendido">8. Como encontrar a Chave Privada $d$: Algoritmo de Euclides Estendido
&lt;/h2>&lt;p>No exemplo calculado à mão, adivinhamos o valor de $k$ para encontrar $d=103$, mas quando o número atinge centenas de dígitos, esse método se torna impossível. Nos programas reais usamos um algoritmo chamado &lt;strong>&amp;ldquo;Algoritmo de Euclides Estendido&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Resolver $7d \equiv 1 \pmod{120}$ é o mesmo que encontrar inteiros $d, y$ que satisfaçam $7d + 120y = 1$. Ao realizar os passos do Algoritmo de Euclides ao reverso, podemos encontrar isso mecanicamente.&lt;/p>
&lt;ol>
&lt;li>$120 \div 7 = 17$ com resto $1$&lt;/li>
&lt;li>Rearranjando isso, temos $1 = 120 - 17 \times 7$&lt;/li>
&lt;li>Em outras palavras, $-17 \times 7 \equiv 1 \pmod{120}$&lt;/li>
&lt;/ol>
&lt;p>No mundo do módulo $120$, $-17$ tem o mesmo significado que $120 - 17 = 103$. Assim, o $d = 103$ pode ser encontrado em um instante. Este método consegue calcular de forma extremamente rápida por mais gigante que o número seja.&lt;/p>
&lt;hr>
&lt;h2 id="9-outra-face-da-criptografia-rsa-assinatura-digital">9. Outra Face da Criptografia RSA: Assinatura Digital
&lt;/h2>&lt;p>A parte fantástica da criptografia RSA é que, se invertermos as funções da chave pública e chave privada, ela também pode ser usada como uma &lt;strong>&amp;ldquo;Assinatura Digital&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Na criptografia os passos eram: &amp;ldquo;Criptografar com a chave pública $\Rightarrow$ Descriptografar com a chave privada&amp;rdquo;,
Mas na assinatura digital seguimos os passos: &amp;ldquo;Criptografar com a chave privada $\Rightarrow$ Descriptografar com a chave pública&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Alice cria a assinatura com a chave privada"] --> A2["S ≡ M^d (mod N)"]
A2 --> A3["Envia a mensagem M e a assinatura S"]
A3 --> B1["2. Bob verifica a assinatura com a chave pública"]
B1 --> B2["Calcula M' ≡ S^e (mod N)"]
B2 --> B3["Verifica se M' e M coincidem"]&lt;/div>
&lt;p>A Alice transforma a mensagem usando sua própria chave privada $d$ (essa será a assinatura $S$) e envia ao Bob. O Bob faz o cálculo de verificação usando a chave pública de Alice, $e$. Se o resultado do cálculo for igual à mensagem original, isso prova simultaneamente que &amp;ldquo;os dados só poderiam ter sido criados pela chave privada da Alice&amp;rdquo; e que &amp;ldquo;a mensagem não foi adulterada no meio do caminho&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="10-sentindo-a-criptografia-rsa-na-prática-com-código">10. Sentindo a Criptografia RSA na Prática com Código
&lt;/h2>&lt;p>O cálculo de potências que seria difícil de fazer à mão pode ser implementado muito facilmente usando Python. A seguir, um código Python para você experienciar a lógica central da criptografia RSA.&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;/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="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="s2">&amp;#34;&amp;#34;&amp;#34;Calcular o máximo divisor comum&amp;#34;&amp;#34;&amp;#34;&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="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="s2">&amp;#34;&amp;#34;&amp;#34;Encontrar a chave privada d (usando a função embutida a partir do Python 3.8)&amp;#34;&amp;#34;&amp;#34;&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">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&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="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"># 1. Geração de chaves&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">p&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">11&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">13&lt;/span>
&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 class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&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="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: (N=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">N&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, e=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">), Chave Privada: d=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">d&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"># 2. Criptografia&lt;/span>
&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="mi">9&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ciphertext&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">message&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>&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">ciphertext&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"># 3. Descriptografia&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">decrypted_message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ciphertext&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 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_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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Como a função &lt;code>pow(base, exp, mod)&lt;/code> do Python usa internamente um algoritmo rápido chamado &amp;ldquo;exponenciação binária (ou método das multiplicações repetidas)&amp;rdquo;, o cálculo termina em um instante mesmo para números com centenas de dígitos.&lt;/p>
&lt;hr>
&lt;h2 id="11-conclusão-e-futuro-das-tecnologias-de-criptografia">11. Conclusão e Futuro das Tecnologias de Criptografia
&lt;/h2>&lt;p>Nós desvendamos o mecanismo da criptografia RSA tendo como base a matemática do ensino médio.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>A dificuldade da fatoração em números primos:&lt;/strong> É fácil calcular $p \times q = N$, mas é extremamente difícil encontrar $p, q$ a partir de $N$.&lt;/li>
&lt;li>&lt;strong>Congruências e Teorema de Euler:&lt;/strong> Devido à regra $a^{\phi(N)} \equiv 1 \pmod N$, completa-se o mágico alçapão onde &amp;ldquo;a exponenciação por um certo número retorna ao estado original&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>Chave Pública e Chave Privada:&lt;/strong> Qualquer um pode criptografar, mas apenas o destinatário legítimo consegue descriptografar.&lt;/li>
&lt;/ol>
&lt;p>O $N$ da criptografia RSA usada atualmente possui mais de 600 dígitos, e mesmo que todos os supercomputadores do mundo se juntassem para faturar esse número em primos, levaria um tempo maior do que a idade do universo. No entanto, se o &amp;ldquo;computador quântico&amp;rdquo;, que vem sendo pesquisado ativamente nos últimos anos, se tornar prático no futuro, essa fatoração poderá ser resolvida em instantes pelo &amp;ldquo;Algoritmo de Shor&amp;rdquo;. Por esse motivo, criptografias &amp;ldquo;resistentes a computadores quânticos&amp;rdquo;, que não poderiam ser quebradas nem mesmo por eles, estão sendo desenvolvidas a um ritmo acelerado pelo mundo todo.&lt;/p>
&lt;p>A matemática avançada que costumamos considerar &amp;ldquo;inútil&amp;rdquo;, na verdade, protege nosso dia a dia na sua essência mais profunda. A criptografia RSA é um excelente material didático que nos ensina essa profundidade e beleza da matemática. Ficaria muito feliz se através deste artigo você pudesse sentir um pouco do fascínio da criptografia e da matemática.&lt;/p></description></item><item><title>Fundamentos Matemáticos da Criptografia de Curva Elíptica (ECC) e sua Implementação em C++</title><link>http://kenji.blog/pt/p/elliptic-curve-cryptography-math-cpp/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/elliptic-curve-cryptography-math-cpp/</guid><description>&lt;img src="http://kenji.blog/p/elliptic-curve-cryptography-math-cpp/img/eyecatch.jpg" alt="Featured image of post Fundamentos Matemáticos da Criptografia de Curva Elíptica (ECC) e sua Implementação em C++" />&lt;h1 id="fundamentos-matemáticos-da-criptografia-de-curva-elíptica-ecc-e-sua-implementação-em-c">Fundamentos Matemáticos da Criptografia de Curva Elíptica (ECC) e sua Implementação em C++
&lt;/h1>&lt;p>Na tecnologia criptográfica moderna, a &lt;strong>Criptografia de Curva Elíptica (Elliptic Curve Cryptography: ECC)&lt;/strong> desempenha um papel extremamente importante. Desde nossas comunicações diárias na internet (HTTPS/TLS), até o enclave seguro dos smartphones, autenticação de servidores via SSH, autenticação sem senha como FIDO e, além disso, criptoativos como Bitcoin e Ethereum, não é exagero dizer que a base de confiança da sociedade digital moderna é sustentada pela ECC.&lt;/p>
&lt;p>Neste artigo, explicaremos de forma exaustiva e com um volume impressionante como essa criptografia de curva elíptica funciona, partindo da teoria matemática bela e complexa por trás dela (geometria algébrica em corpos finitos), passando pelo método de implementação real usando C++, até as técnicas de codificação segura para evitar ataques de canal lateral (ataques de tempo).&lt;/p>
&lt;hr>
&lt;h2 id="1-por-que-a-criptografia-de-curva-elíptica-comparação-com-rsa">1. Por que a Criptografia de Curva Elíptica? (Comparação com RSA)
&lt;/h2>&lt;p>Por muito tempo, o sinônimo de criptografia de chave pública foi a &lt;strong>Criptografia RSA&lt;/strong>. A criptografia RSA baseia a sua segurança na &amp;ldquo;dificuldade de fatoração de números compostos gigantes&amp;rdquo;. No entanto, com o aumento da capacidade de cálculo dos computadores, surgiu a necessidade de aumentar continuamente o tamanho da chave RSA (o número de bits do módulo) para manter a segurança. Atualmente, recomenda-se um tamanho de chave de no mínimo 2048 bits, ou 3072 bits e 4096 bits para maior segurança.&lt;/p>
&lt;p>Por outro lado, a criptografia de curva elíptica (ECC) baseia a sua segurança em outra dificuldade matemática chamada &lt;strong>&amp;ldquo;Problema do Logaritmo Discreto em Curvas Elípticas (ECDLP)&amp;rdquo;&lt;/strong>. Até o momento, nenhum algoritmo eficiente (como algoritmos de tempo subexponencial) foi descoberto para resolver o ECDLP, e mesmo os métodos de ataque mais eficientes conhecidos requerem tempo exponencial.&lt;/p>
&lt;p>Devido a essa propriedade, a ECC possui a vantagem decisiva de &lt;strong>alcançar uma força de segurança equivalente à do RSA com um tamanho de chave muito menor&lt;/strong>.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">Força de Segurança (bits)&lt;/th>
&lt;th style="text-align:center">Tamanho da Chave RSA (bits)&lt;/th>
&lt;th style="text-align:center">Tamanho da Chave de Curva Elíptica (bits)&lt;/th>
&lt;th style="text-align:center">Proporção do Tamanho da Chave&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:center">80&lt;/td>
&lt;td style="text-align:center">1024&lt;/td>
&lt;td style="text-align:center">160&lt;/td>
&lt;td style="text-align:center">1:6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">112&lt;/td>
&lt;td style="text-align:center">2048&lt;/td>
&lt;td style="text-align:center">224&lt;/td>
&lt;td style="text-align:center">1:9&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">128&lt;/td>
&lt;td style="text-align:center">3072&lt;/td>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">1:12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">192&lt;/td>
&lt;td style="text-align:center">7680&lt;/td>
&lt;td style="text-align:center">384&lt;/td>
&lt;td style="text-align:center">1:20&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:center">256&lt;/td>
&lt;td style="text-align:center">15360&lt;/td>
&lt;td style="text-align:center">512&lt;/td>
&lt;td style="text-align:center">1:30&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Como a tabela acima mostra, para obter uma força de segurança de 128 bits (o padrão atual), o RSA requer uma chave de 3072 bits, mas a ECC requer apenas 256 bits. Isso permite a redução da quantidade de cálculos, a diminuição do uso de memória e a economia de largura de banda de rede, apresentando uma vantagem esmagadora, especialmente em ambientes com recursos limitados como dispositivos IoT e cartões inteligentes.&lt;/p>
&lt;hr>
&lt;h2 id="2-preparação-matemática-teoria-dos-grupos-e-corpos-finitos">2. Preparação Matemática: Teoria dos Grupos e Corpos Finitos
&lt;/h2>&lt;p>Para entender verdadeiramente a criptografia de curva elíptica, é necessário compreender os conceitos básicos de álgebra abstrata (teoria dos grupos e teoria dos corpos). Aqui, resumiremos os conhecimentos prévios para construir a ECC.&lt;/p>
&lt;h3 id="21-grupos-group-e-grupos-abelianos">2.1. Grupos (Group) e Grupos Abelianos
&lt;/h3>&lt;p>Um &lt;strong>Grupo (Group)&lt;/strong> é um conjunto de um dado conjunto $G$ com uma operação binária nesse conjunto (aqui será a adição $+$), $(G, +)$, que satisfaz os 4 axiomas a seguir.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Fechamento (Closure)&lt;/strong>: Para quaisquer $a, b \in G$, $a + b \in G$.&lt;/li>
&lt;li>&lt;strong>Associatividade (Associativity)&lt;/strong>: Para quaisquer $a, b, c \in G$, $(a + b) + c = a + (b + c)$ é válido.&lt;/li>
&lt;li>&lt;strong>Existência do Elemento Neutro (Identity element)&lt;/strong>: Existe um elemento $e \in G$ tal que para qualquer $a \in G$, $a + e = e + a = a$. No caso de grupos aditivos, este elemento neutro é normalmente denotado como $0$ ou $\mathcal{O}$.&lt;/li>
&lt;li>&lt;strong>Existência do Elemento Inverso (Inverse element)&lt;/strong>: Para qualquer $a \in G$, existe um elemento $b \in G$ tal que $a + b = b + a = e$. Esse $b$ é denotado como $-a$.&lt;/li>
&lt;/ol>
&lt;p>Além disso, um grupo que não altera o resultado mesmo mudando a ordem da operação, ou seja, que satisfaz a seguinte condição, é chamado de &lt;strong>Grupo Abeliano (Grupo Comutativo)&lt;/strong>.&lt;/p>
&lt;ol start="5">
&lt;li>&lt;strong>Comutatividade (Commutativity)&lt;/strong>: Para quaisquer $a, b \in G$, $a + b = b + a$ é válido.&lt;/li>
&lt;/ol>
&lt;p>O conjunto de pontos em uma curva elíptica forma este &lt;strong>grupo abeliano&lt;/strong> pela definição de uma regra de adição específica.&lt;/p>
&lt;h3 id="22-corpos-finitos-finite-field">2.2. Corpos Finitos (Finite Field)
&lt;/h3>&lt;p>Na teoria criptográfica, em vez de corpos contínuos com infinitos elementos como os números reais ou complexos, usamos &lt;strong>Corpos Finitos (Finite Field)&lt;/strong> ou Corpos de Galois, onde o número de elementos é finito.&lt;/p>
&lt;p>O corpo finito mais básico é o &lt;strong>corpo primo $\mathbb{F}_p$&lt;/strong> que usa o número primo $p$. Ele é a definição das quatro operações aritméticas (adição, subtração, multiplicação e divisão) em módulo $p$ (resto da divisão por $p$) no conjunto de inteiros $\{0, 1, 2, \dots, p-1\}$.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Adição&lt;/strong>: $(a + b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Subtração&lt;/strong>: $(a - b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Multiplicação&lt;/strong>: $(a \times b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Divisão&lt;/strong>: $a \times b^{-1} \pmod p$ (onde $b^{-1}$ é o inverso multiplicativo de $b$ módulo $p$)&lt;/li>
&lt;/ul>
&lt;p>O cálculo do &lt;strong>Inverso Multiplicativo Modular (Modular Multiplicative Inverse)&lt;/strong> é extremamente importante nas implementações criptográficas. Para encontrar o $b^{-1}$ que satisfaz $b \times b^{-1} \equiv 1 \pmod p$, são utilizados principalmente os 2 algoritmos a seguir.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Algoritmo de Euclides Estendido (Extended Euclidean Algorithm)&lt;/strong>: Rápido, mas dependendo da implementação, o tempo de processamento depende do valor de entrada, o que representa um risco de ataques de tempo.&lt;/li>
&lt;li>&lt;strong>Pequeno Teorema de Fermat (Fermat&amp;rsquo;s Little Theorem)&lt;/strong>: Quando $p$ é um número primo e $b \neq 0$, $b^{p-1} \equiv 1 \pmod p$ é válido. Dividindo ambos os lados por $b$, obtemos $b^{p-2} \equiv b^{-1} \pmod p$. Em outras palavras, o inverso é encontrado calculando $b$ elevado a $p-2$. A operação de exponenciação é fácil de implementar em tempo constante, por isso é a preferida em implementações criptográficas.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-equação-da-curva-elíptica-e-geometria">3. Equação da Curva Elíptica e Geometria
&lt;/h2>&lt;h3 id="31-forma-normal-de-weierstrass">3.1. Forma Normal de Weierstrass
&lt;/h3>&lt;p>Uma &lt;strong>Curva Elíptica (Elliptic Curve)&lt;/strong> é geralmente uma curva plana definida pela equação chamada de &lt;strong>Forma normal de Weierstrass (Weierstrass normal form)&lt;/strong> a seguir.&lt;/p>
$$ y^2 = x^3 + ax + b $$
&lt;p>Aqui, $a$ e $b$ são constantes, e como condição para que a curva não possua singularidades (autointerseção ou cúspides) (para que seja uma curva suave), exige-se que o &lt;strong>Discriminante (Discriminant) $\Delta$&lt;/strong> a seguir não seja zero.&lt;/p>
$$ \Delta = -16(4a^3 + 27b^2) \neq 0 $$
&lt;p>Como as curvas com singularidades comprometem a segurança criptográfica, coeficientes $a, b$ que satisfaçam essa condição são sempre escolhidos.&lt;/p>
&lt;h3 id="32-ponto-no-infinito-point-at-infinity">3.2. Ponto no Infinito (Point at Infinity)
&lt;/h3>&lt;p>Para transformar a curva elíptica em um grupo matematicamente perfeito, além dos pontos no plano, introduzimos um ponto virtual chamado &lt;strong>&amp;ldquo;Ponto no Infinito (Point at Infinity)&amp;rdquo;&lt;/strong>. Ele é denotado como $\mathcal{O}$ (O).&lt;/p>
&lt;p>O ponto no infinito $\mathcal{O}$ é definido como o ponto onde todas as linhas verticais se cruzam no infinito. Na teoria dos grupos, este ponto no infinito $\mathcal{O}$ funciona como o &lt;strong>elemento neutro na adição&lt;/strong> (zero).&lt;/p>
&lt;p>Ou seja, para qualquer ponto $P$ na curva, vale o seguinte:
&lt;/p>
$$ P + \mathcal{O} = \mathcal{O} + P = P $$
&lt;p>Além disso, o inverso $-P$ do ponto $P = (x, y)$ é definido como o ponto simétrico em relação ao eixo x $(x, -y)$. Portanto:
&lt;/p>
$$ P + (-P) = \mathcal{O} $$
&lt;p>
é obtido.&lt;/p>
&lt;hr>
&lt;h2 id="4-operações-de-grupo-em-curvas-elípticas-adição-de-pontos-e-dobro">4. Operações de Grupo em Curvas Elípticas (Adição de Pontos e Dobro)
&lt;/h2>&lt;p>O núcleo da criptografia de curva elíptica é a operação de &lt;strong>&amp;ldquo;Adição (Addition)&amp;rdquo;&lt;/strong> entre pontos na curva. Diferente da adição normal de inteiros, ela é baseada em operações geométricas.&lt;/p>
&lt;h3 id="41-adição-geométrica-tangent-and-chord-method">4.1. Adição Geométrica (Tangent and Chord Method)
&lt;/h3>&lt;p>O procedimento para somar 2 pontos diferentes $P$ e $Q$ na curva para encontrar um novo ponto $R$ ($R = P + Q$) é o seguinte.&lt;/p>
&lt;ol>
&lt;li>Trace uma reta (corda) passando pelo ponto $P$ e pelo ponto $Q$.&lt;/li>
&lt;li>Esta reta sempre cruzará a curva elíptica em um terceiro ponto (vamos chamá-lo de $-R$). (*Pelo teorema da geometria algébrica)&lt;/li>
&lt;li>O ponto simétrico de $-R$ em relação ao eixo x (o ponto com o sinal da coordenada y invertido) será o ponto $R$ desejado.&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
Step1["Traçar uma reta ligando P(x1, y1) e Q(x2, y2)"] --> Step2["Encontrar o terceiro ponto de interseção -R com a curva"]
Step2 --> Step3["Refletir -R no eixo x para obter R(x3, y3)"]
Step3 -.-> Result["Este é R = P + Q"]&lt;/div>
&lt;h3 id="42-dobro-de-um-ponto-point-doubling">4.2. Dobro de um Ponto (Point Doubling)
&lt;/h3>&lt;p>Quando somamos o ponto $P$ ao próprio ponto $P$ ($P + P = 2P$), não podemos traçar uma reta que passe por 2 pontos. Neste caso, traçamos a &lt;strong>tangente (Tangent) à curva no ponto $P$&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>Trace a tangente à curva no ponto $P$.&lt;/li>
&lt;li>Esta tangente cruzará a curva em outro ponto $-R$.&lt;/li>
&lt;li>O ponto simétrico desse cruzamento em relação ao eixo x será o ponto $R = 2P$ desejado.&lt;/li>
&lt;/ol>
&lt;h3 id="43-fórmulas-de-cálculo-algébrico">4.3. Fórmulas de Cálculo Algébrico
&lt;/h3>&lt;p>As operações geométricas são convertidas em fórmulas algébricas para que possam ser calculadas por computadores.
As operações são todas feitas no &lt;strong>corpo finito $\mathbb{F}_p$ (módulo $p$)&lt;/strong>.&lt;/p>
&lt;p>Sejam os pontos $P = (x_1, y_1)$ e $Q = (x_2, y_2)$.
Além disso, seja o ponto do resultado do cálculo $R = P + Q = (x_3, y_3)$.&lt;/p>
&lt;p>Seja $\lambda$ (lambda) a inclinação da reta.&lt;/p>
&lt;p>&lt;strong>[Caso 1: Quando $P \neq Q$ (Adição de Pontos)]&lt;/strong>
A inclinação $\lambda$ é a taxa de variação entre os 2 pontos.
&lt;/p>
$$ \lambda \equiv \frac{y_2 - y_1}{x_2 - x_1} \pmod p $$
$$ \lambda \equiv (y_2 - y_1) \cdot (x_2 - x_1)^{-1} \pmod p $$
&lt;p>Usando esse $\lambda$, $x_3, y_3$ são calculados da seguinte forma.
&lt;/p>
$$ x_3 \equiv \lambda^2 - x_1 - x_2 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;p>&lt;strong>[Caso 2: Quando $P = Q$ (Dobro de Ponto)]&lt;/strong>
A inclinação $\lambda$ será a inclinação da tangente, encontrada pela derivada. (Diferenciação implícita de $y^2 = x^3 + ax + b$)
&lt;/p>
$$ 2y \cdot y' = 3x^2 + a \implies y' = \frac{3x^2 + a}{2y} $$
&lt;p>
Portanto,
&lt;/p>
$$ \lambda \equiv (3x_1^2 + a) \cdot (2y_1)^{-1} \pmod p $$
&lt;p>As equações de $x_3, y_3$ têm o mesmo formato da adição, mas como $x_2 = x_1$, ficam assim:
&lt;/p>
$$ x_3 \equiv \lambda^2 - 2x_1 \pmod p $$
$$ y_3 \equiv \lambda(x_1 - x_3) - y_1 \pmod p $$
&lt;blockquote>
&lt;p>[!IMPORTANT]
Estas fórmulas contêm &lt;strong>divisões (cálculo do inverso modular)&lt;/strong> como $(x_2 - x_1)^{-1}$ e $(2y_1)^{-1}$. O cálculo do inverso modular tem um custo computacional muito alto, então em implementações reais, geralmente se usa um sistema de coordenadas projetivas, como o &lt;strong>&amp;ldquo;Sistema de Coordenadas Jacobiano (Jacobian Coordinates)&amp;rdquo;&lt;/strong>, que adia a divisão.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="5-multiplicação-escalar-e-o-problema-do-logaritmo-discreto-em-curvas-elípticas-ecdlp">5. Multiplicação Escalar e o Problema do Logaritmo Discreto em Curvas Elípticas (ECDLP)
&lt;/h2>&lt;p>Na criptografia de curva elíptica, a operação de maior complexidade computacional e que forma o núcleo da segurança é a &lt;strong>Multiplicação Escalar (Scalar Multiplication)&lt;/strong>.&lt;/p>
&lt;h3 id="51-o-que-é-a-multiplicação-escalar">5.1. O que é a Multiplicação Escalar
&lt;/h3>&lt;p>A operação de somar um ponto $P$ a ele mesmo $k$ vezes é chamada de multiplicação escalar e denotada como $kP$.
&lt;/p>
$$ kP = \underbrace{P + P + \dots + P}_{k\text{ vezes}} $$
&lt;p>Aqui, $k$ é um inteiro muito grande (por exemplo, um número inteiro de 256 bits).&lt;/p>
&lt;h3 id="52-problema-do-logaritmo-discreto-em-curvas-elípticas-ecdlp">5.2. Problema do Logaritmo Discreto em Curvas Elípticas (ECDLP)
&lt;/h3>&lt;p>A segurança da criptografia de curva elíptica depende da dificuldade do seguinte problema.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Problema do Logaritmo Discreto em Curvas Elípticas (Elliptic Curve Discrete Logarithm Problem: ECDLP)&lt;/strong>
Dado um ponto conhecido $P$ (ponto base) e um ponto de resultado do cálculo $Q$, encontre o escalar $k$ que satisfaz $Q = kP$.&lt;/p>
&lt;/blockquote>
&lt;p>É fácil (em tempo polinomial) calcular $Q$ a partir de $k$ e $P$ (direção direta) usando os algoritmos que serão mencionados depois, mas calcular inversamente $k$ a partir de $P$ e $Q$ (direção inversa) é virtualmente impossível sem usar uma busca exaustiva (força bruta), tornando-a uma função de via única.
Nos protocolos criptográficos, &lt;strong>$k$ corresponde à &amp;ldquo;chave privada&amp;rdquo; e $Q$ corresponde à &amp;ldquo;chave pública&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="53-algoritmo-double-and-add">5.3. Algoritmo Double-and-Add
&lt;/h3>&lt;p>Quando $k$ é um número gigante (ex: $2^{256}$), a adição direta de $P$ por $k$ vezes não terminaria nem com o fim da vida do universo. Assim, para realizar a multiplicação escalar rapidamente, usa-se o &lt;strong>método Double-and-Add (Método Binário)&lt;/strong>.&lt;/p>
&lt;p>Esta é a versão em curva elíptica da &amp;ldquo;exponenciação modular rápida&amp;rdquo; para calcular rapidamente potências de números inteiros. Ele expressa o escalar $k$ em binário e o processa a partir do bit mais significativo.&lt;/p>
&lt;ol>
&lt;li>Inicialize o ponto $R$, que guardará o resultado, como $\mathcal{O}$.&lt;/li>
&lt;li>Repita do bit mais significativo até o bit menos significativo de $k$:
&lt;ul>
&lt;li>Dobre $R$ (Point Doubling: $R = 2R$)&lt;/li>
&lt;li>Se o bit atual for &lt;code>1&lt;/code>, adicione $P$ a $R$ (Point Addition: $R = R + P$)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>Com este algoritmo, a complexidade computacional é drasticamente reduzida de $O(k)$ para $O(\log_2 k)$, tornando o cálculo possível em tempo realista (na ordem de milissegundos).&lt;/p>
&lt;hr>
&lt;h2 id="6-troca-de-chaves-diffie-hellman-em-curva-elíptica-ecdh">6. Troca de Chaves Diffie-Hellman em Curva Elíptica (ECDH)
&lt;/h2>&lt;p>Aqui explicaremos o funcionamento do protocolo mais representativo de aplicação da ECC, o &lt;strong>protocolo de troca de chaves ECDH (Elliptic Curve Diffie-Hellman)&lt;/strong>. O ECDH é um mecanismo que permite que Alice e Bob gerem e compartilhem de forma segura uma chave secreta comum (chave de sessão) sobre um canal de comunicação sujeito a interceptação (é o núcleo do handshake TLS).&lt;/p>
&lt;p>&lt;strong>[Parâmetros Prévios (Parâmetros de Domínio)]&lt;/strong>
As duas partes compartilham com antecedência a curva elíptica $E$ a ser usada, um número primo $p$, e um ponto base $G$. (Exemplos incluem NIST P-256 e secp256k1)&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice as "Alice"
participant Bob as "Bob"
Note over Alice,Bob: "Parâmetros Públicos: Curva E, Ponto base G, Primo p"
Alice->>Alice: "Gerar chave privada d_A (inteiro aleatório)"
Alice->>Alice: "Calcular chave pública Q_A = d_A * G"
Bob->>Bob: "Gerar chave privada d_B (inteiro aleatório)"
Bob->>Bob: "Calcular chave pública Q_B = d_B * G"
Alice->>Bob: "Enviar chave pública Q_A (texto claro)"
Bob->>Alice: "Enviar chave pública Q_B (texto claro)"
Alice->>Alice: "Calcular segredo compartilhado S = d_A * Q_B"
Bob->>Bob: "Calcular segredo compartilhado S = d_B * Q_A"
Note over Alice,Bob: "S = d_A * (d_B * G) = d_B * (d_A * G) = (d_A * d_B) * G"
Note over Alice,Bob: "O resultado do cálculo S de ambos é perfeitamente idêntico!"&lt;/div>
&lt;p>Um interceptador (Eve) pode capturar $G$, $Q_A$ e $Q_B$ que fluem na via de comunicação, mas devido à dificuldade do ECDLP, não pode deduzir a chave privada $d_A$ de Alice a partir de $Q_A = d_A \cdot G$. Além disso, multiplicar $Q_A$ e $Q_B$ não resulta na chave compartilhada $S$, de forma que o interceptador não pode calcular $S$.&lt;/p>
&lt;hr>
&lt;h2 id="7-armadilhas-de-implementação-ataques-de-canal-lateral-e-contramedidas">7. Armadilhas de Implementação: Ataques de Canal Lateral e Contramedidas
&lt;/h2>&lt;p>Mesmo que seja um algoritmo de criptografia teoricamente perfeito, vulnerabilidades podem surgir no processo de implementá-lo como um programa. Isso é conhecido como &lt;strong>&amp;ldquo;Ataque de Canal Lateral (Side-Channel Attack)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="71-ataques-de-tempo-timing-attack">7.1. Ataques de Tempo (Timing Attack)
&lt;/h3>&lt;p>Vamos rever o algoritmo Double-and-Add mencionado anteriormente.&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;/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="c1">// Pseudocódigo vulnerável de Double-and-Add
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">Infinity&lt;/span>&lt;span class="p">;&lt;/span>
&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">255&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&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="n">i&lt;/span>&lt;span class="o">--&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">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointDoubling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Sempre executado
&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">bit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&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="n">R&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PointAddition&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Executado apenas quando o bit é 1!
&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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Esta implementação tem uma falha fatal. Como a Adição de Pontos (Point Addition) é executada quando o bit é &lt;code>1&lt;/code>, o &lt;strong>tempo de cálculo é ligeiramente maior&lt;/strong> do que quando o bit é &lt;code>0&lt;/code>. Além disso, o comportamento da previsão de ramificação do processador e da memória cache também muda.
Observando estatisticamente essas diferenças microscópicas no tempo de computação (ou consumo de energia) milhares de vezes, um atacante pode &lt;strong>restaurar a sequência de bits da chave secreta $k$ completamente, bit a bit&lt;/strong>. Esse é o ataque de tempo.&lt;/p>
&lt;h3 id="72-implementação-em-tempo-constante-constant-time-montgomery-ladder">7.2. Implementação em Tempo Constante (Constant-Time): Montgomery Ladder
&lt;/h3>&lt;p>Para prevenir ataques de tempo, é necessário adotar um algoritmo em que &lt;strong>a sequência de instruções executadas e o tempo de computação sejam sempre constantes (Constant-Time), independentemente do valor do bit da chave secreta&lt;/strong>.&lt;/p>
&lt;p>Um exemplo representativo disso é a &lt;strong>Escada de Montgomery (Montgomery Ladder)&lt;/strong>.&lt;/p>
&lt;div class="mermaid">graph TD
Start["Inicialização: R0 = O, R1 = P"] --> LoopStart["Para cada bit i (a partir do mais significativo)"]
LoopStart --> Cond{"Qual é o valor de k_i?"}
Cond -->|0| Branch0["R1 = R0 + R1&lt;br>R0 = 2 * R0"]
Cond -->|1| Branch1["R0 = R0 + R1&lt;br>R1 = 2 * R1"]
Branch0 --> LoopEnd["Ir para o próximo bit"]
Branch1 --> LoopEnd
LoopEnd --> LoopStart
LoopStart -.->|"Todos os bits concluídos"| End["Término: R0 é o resultado (kP)"]&lt;/div>
&lt;p>A beleza da Montgomery Ladder é que, seja o bit &lt;code>0&lt;/code> ou &lt;code>1&lt;/code>, &lt;strong>&amp;ldquo;sempre 1 Point Addition e 1 Point Doubling&amp;rdquo;&lt;/strong> são executados. Isto elimina completamente a dependência de dados no tempo de computação.&lt;/p>
&lt;p>No entanto, se a própria ramificação (&lt;code>if (k_i == 0)&lt;/code>) existir, haverá um risco de variação no tempo de execução devido à otimização do compilador e à previsão de ramificação da CPU. Portanto, nas implementações em Tempo Constante reais, as ramificações condicionais (comandos &lt;code>if&lt;/code>) são eliminadas e usa-se a &lt;strong>troca condicional (Conditional Swap) usando operações de bit&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h2 id="8-implementação-da-criptografia-de-curva-elíptica-em-c">8. Implementação da Criptografia de Curva Elíptica em C++
&lt;/h2>&lt;p>A partir daqui, transformaremos a teoria em código C++. Bibliotecas de criptografia práticas (como OpenSSL e libsodium) usam otimizações avançadas em Assembly e o sistema de coordenadas jacobiano, mas aqui mostraremos a estrutura de uma &lt;strong>implementação de tempo constante simples usando coordenadas afins&lt;/strong>, para aprofundar a compreensão matemática.&lt;/p>
&lt;p>Supõe-se que será usado &lt;code>boost::multiprecision::cpp_int&lt;/code> para operações com números inteiros enormes.&lt;/p>
&lt;h3 id="81-aritmética-modular-e-inverso">8.1. Aritmética Modular e Inverso
&lt;/h3>&lt;p>Primeiro, vamos definir as funções auxiliares de cálculo sobre o corpo finito. Vamos implementar o cálculo do inverso com base no pequeno teorema de Fermat.&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;/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;vector&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;stdexcept&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;boost/multiprecision/cpp_int.hpp&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">boost&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">multiprecision&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: primo p e parâmetros da secp256k1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">p&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F&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">const&lt;/span> &lt;span class="n">cpp_int&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">const&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">7&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">// Aritmética modular retornando resto positivo
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&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="n">cpp_int&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">x&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">return&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="nl">m&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">r&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">// Cálculo de exponenciação modular (x^y mod m)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="nf">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">exp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&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="n">cpp_int&lt;/span> &lt;span class="n">res&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">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span>&lt;span class="p">,&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">exp&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="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">exp&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="n">res&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">res&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&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="n">base&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">base&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">base&lt;/span>&lt;span class="p">,&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="n">exp&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">res&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">// Inverso modular usando o Pequeno Teorema 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="n">cpp_int&lt;/span> &lt;span class="nf">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&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="c1">// Pressupondo que m seja primo: n^(m-2) ≡ n^(-1) mod m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">powerMod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&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="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="82-representação-dos-pontos-e-operações-de-grupo-adição-e-dobro">8.2. Representação dos Pontos e Operações de Grupo (Adição e Dobro)
&lt;/h3>&lt;p>Vamos implementar a estrutura &lt;code>Point&lt;/code> para gerenciar o ponto no infinito por meio de uma flag e a fórmula de adiçã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;/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="k">struct&lt;/span> &lt;span class="nc">Point&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&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 class="kt">bool&lt;/span> &lt;span class="n">isInfinity&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">// Geração do ponto no infinito
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">true&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Geração de um ponto normal
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpp_int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">x&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="p">(&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">isInfinity&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">false&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="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">// Adição de pontos em uma curva elíptica (R = P + Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">Q&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="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&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="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">isInfinity&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">P&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">if&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">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">mod&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">y&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">Q&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">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&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="k">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// P + (-P) = ponto no infinito
&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="n">cpp_int&lt;/span> &lt;span class="n">lambda&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="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">P&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">Q&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">y&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">// Point Doubling (Quando P = Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (3x^2 + a) / 2y
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&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">P&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">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">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">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">P&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">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">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">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&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="c1">// Point Addition (Quando P != Q)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// lambda = (y2 - y1) / (x2 - x1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&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">P&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">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">cpp_int&lt;/span> &lt;span class="n">den&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">modInverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Q&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">P&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">p&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">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">lambda&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">den&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&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="n">cpp_int&lt;/span> &lt;span class="n">x3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">lambda&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&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">Q&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">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">cpp_int&lt;/span> &lt;span class="n">y3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lambda&lt;/span> &lt;span class="o">*&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">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">x3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">P&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">p&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">return&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y3&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="83-implementação-da-troca-condicional-em-tempo-constante-constant-time-conditional-swap">8.3. Implementação da Troca Condicional em Tempo Constante (Constant-Time Conditional Swap)
&lt;/h3>&lt;p>Ao trocar o conteúdo de variáveis com base no valor do bit da chave privada, efetuamos a troca apenas com operações de bit (máscaras) sem usar o comando &lt;code>if&lt;/code>. Deste modo, o caminho de execução se torna estritamente constante.&lt;/p>
&lt;blockquote>
&lt;p>[!TIP]
Em implementações reais, classes de números inteiros de múltipla precisão dinamicamente alocadas, como &lt;code>cpp_int&lt;/code>, não são adequadas para processamento em Tempo Constante (Constant-Time). Isso ocorre porque informações de temporização vazam por causa de alocações de memória e mudanças de tamanho de vetor. Em bibliotecas de produção, representamos números inteiros de tamanho fixo (por exemplo, arrays de 4 elementos uint64_t) e implementamos processamento de máscara a nível de bit. A seguir, está um exemplo conceitual.&lt;/p>
&lt;/blockquote>
&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;/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="c1">// Constant-Time Swap Conceitual (assumindo números inteiros de tamanho fixo)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Se bit for 1, troca P1 e P2; se for 0, não troca
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">void&lt;/span> &lt;span class="nf">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&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">// bit é 0 ou 1. A máscara é todos os bits 1 (0xFF..) se bit=1 e todos 0 se for 0.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// (Aqui, para explicação, assumimos cada palavra da classe BigInt de tamanho fixo como w)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="cm">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t mask = 0 - (uint64_t)bit;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> for (int i = 0; i &amp;lt; NUM_WORDS; i++) {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> uint64_t dummy = mask &amp;amp; (P1.x.words[i] ^ P2.x.words[i]);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P1.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> P2.x.words[i] ^= dummy;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> // As coordenadas y e as flags isInfinity também são processadas da mesma forma
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm"> */&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">// ※ É difícil realizar uma troca de tempo constante perfeita usando boost::multiprecision,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// então, aqui nos limitaremos a simular a ramificação para entender a lógica.
&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">bit&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">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">swap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">P1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">P2&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;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="84-multiplicação-escalar-pela-escada-de-montgomery-montgomery-ladder">8.4. Multiplicação Escalar pela Escada de Montgomery (Montgomery Ladder)
&lt;/h3>&lt;p>Combinando os comandos &lt;code>pointAdd&lt;/code> e &lt;code>cswap&lt;/code> acima mencionados, implementaremos uma multiplicação escalar segura.&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;/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="c1">// Multiplicação escalar k * P (método Montgomery Ladder)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">Point&lt;/span> &lt;span class="nf">scalarMultiply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">P&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">k&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">Point&lt;/span> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// Ponto no infinito
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Point&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">P&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">// Obtém o comprimento em bits de k (256 bits se secp256k1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">numBits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&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="n">numBits&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">i&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="n">i&lt;/span>&lt;span class="o">--&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">// Obtém o valor do bit i (0 ou 1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">uint8_t&lt;/span> &lt;span class="n">bit&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint8_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bit_test&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">k&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="mi">1&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>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Se bit == 1, faz swap entre R0 e R1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&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">// Executa sempre a mesma operação (Point Addition e Point Doubling)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">R1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">R0&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pointAdd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R0&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">// Se bit == 1, faz o swap novamente para retornar ao estado original
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cswap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">R0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">R1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">bit&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="k">return&lt;/span> &lt;span class="n">R0&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;p>Por essa lógica de implementação, se cada bit do escalar $k$ é &lt;code>0&lt;/code> ou &lt;code>1&lt;/code>, as operações executadas em cada iteração de loop (&lt;code>cswap&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>cswap&lt;/code>) seguem exatamente o mesmo fluxo, e é possível prevenir vigorosamente o vazamento de informações secretas através das diferenças de temporização ou padrões de acesso ao cache.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusão">9. Conclusão
&lt;/h2>&lt;p>À primeira vista, a criptografia de curva elíptica (ECC) pode parecer estranha: &amp;ldquo;Por que uma operação geométrica de traçar retas e dobrar interseções resulta em criptografia?&amp;rdquo;. No entanto, é o produto da fusão milagrosa da matemática e da criptografia que permite que uma brilhante função de via única (o problema do logaritmo discreto) seja estruturada por meio do mapeamento do mundo discreto dos corpos finitos.&lt;/p>
&lt;p>Este artigo abordou os seguintes pontos cruciais.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Superioridade em relação ao RSA&lt;/strong>: Fornece segurança poderosa com comprimentos de chave muito curtos, sendo a mais adequada para as eras móveis e IoT contemporâneas.&lt;/li>
&lt;li>&lt;strong>Bases da Teoria dos Grupos e Corpos Finitos&lt;/strong>: As estruturas matemáticas subjacentes da ECC.&lt;/li>
&lt;li>&lt;strong>Fórmulas de Adição e Dobro&lt;/strong>: O método para implementar operações algébricas de grupo usando equações de Weierstrass.&lt;/li>
&lt;li>&lt;strong>Ameaça de Ataques de Canal Lateral&lt;/strong>: As ramificações condicionais dependentes de bit da chave privada causam vulnerabilidades fatais.&lt;/li>
&lt;li>&lt;strong>Implementação de Tempo Constante (Constant-Time)&lt;/strong>: Técnicas de codificação em C++ para evitar ataques através de comportamentos unificados de nível de hardware usando Escada de Montgomery (Montgomery Ladder) e Troca Condicional (Conditional Swap).&lt;/li>
&lt;/ol>
&lt;p>Não é recomendado (&amp;ldquo;Don&amp;rsquo;t roll your own crypto&amp;rdquo;) criar suas próprias bibliotecas criptográficas que operem efetivamente no ambiente de produção, uma vez que o risco de segurança é extremamente alto. No entanto, compreender a fundo o seu algoritmo interno e o contexto matemático que operem lá dentro deveria ser uma arma indubitavelmente forte para qualquer engenheiro que queira criar e operar um sistema ainda mais seguro e com maior desempenho.&lt;/p>
&lt;p>No próximo artigo, aprofundaremos um pouco mais sobre o mecanismo do &lt;strong>ECDSA (Elliptic Curve Digital Signature Algorithm)&lt;/strong>, um algoritmo de assinatura digital que usa essas curvas elípticas, bem como a &lt;strong>Assinatura de Schnorr&lt;/strong> usada no Bitcoin.&lt;/p></description></item></channel></rss>