<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mathematics on kenji.blog</title><link>http://kenji.blog/pt/tags/mathematics/</link><description>Recent content in Mathematics on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 10:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/mathematics/index.xml" rel="self" type="application/rss+xml"/><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>