<?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/en/categories/cryptography/</link><description>Recent content in Cryptography on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 22:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/en/categories/cryptography/index.xml" rel="self" type="application/rss+xml"/><item><title>Fundamentals and Implementation of Cryptography Using Fermat's Little Theorem</title><link>http://kenji.blog/en/p/fermats-little-theorem-cryptography-implementation/</link><pubDate>Fri, 11 Sep 2026 22:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/fermats-little-theorem-cryptography-implementation/</guid><description>&lt;img src="http://kenji.blog/p/fermats-little-theorem-cryptography-implementation/img/eyecatch.jpg" alt="Featured image of post Fundamentals and Implementation of Cryptography Using Fermat's Little Theorem" />&lt;h2 id="1-introduction-the-mystery-of-mathematics-supporting-modern-cryptography">1. Introduction: The Mystery of Mathematics Supporting Modern Cryptography
&lt;/h2>&lt;p>In modern digital society, especially in communication over the Internet, &amp;ldquo;encryption&amp;rdquo; has become an indispensable foundational technology. The reason we can securely browse websites via HTTPS, perform financial transactions through online banking, and exchange private messages on messaging apps is because cryptographic protocols backed by highly advanced mathematical theories are working behind the scenes. Among them, &amp;ldquo;Public-Key Cryptography&amp;rdquo; plays a particularly important role, and its prime representative is &lt;strong>RSA cryptography&lt;/strong>.&lt;/p>
&lt;p>The security and correctness of many cryptographic algorithms, including RSA cryptography, depend heavily on a very beautiful and powerful theorem discovered by the 17th-century French mathematician Pierre de Fermat. That is &lt;strong>Fermat&amp;rsquo;s Little Theorem&lt;/strong>. Furthermore, Leonhard Euler&amp;rsquo;s theorem, which generalizes this, also plays a decisive role in cryptographic theory.&lt;/p>
&lt;p>In this article, we will thoroughly explain from the basics how the pure mathematical discovery of Fermat&amp;rsquo;s Little Theorem is applied to modern practical cryptographic technologies, especially &amp;ldquo;primality testing&amp;rdquo; and &amp;ldquo;RSA cryptography&amp;rdquo;. This will be a highly detailed technical guide covering mathematical proofs, encryption and decryption mechanisms, and specific algorithm implementations using C++ and Python.&lt;/p>
&lt;hr>
&lt;h2 id="2-fundamentals-of-congruences-and-modular-arithmetic">2. Fundamentals of Congruences and Modular Arithmetic
&lt;/h2>&lt;p>To understand Fermat&amp;rsquo;s Little Theorem, you first need to become familiar with the mathematical concept of &amp;ldquo;modular arithmetic (congruence)&amp;rdquo;. Modular arithmetic is a calculation system that focuses on the &amp;ldquo;remainder&amp;rdquo; when dividing by a certain fixed number (called the modulus). Because it&amp;rsquo;s a calculation like a clock face (which cycles every 12 hours), it is also called &amp;ldquo;clock mathematics&amp;rdquo;.&lt;/p>
&lt;p>When the remainders of dividing integers $a$ and $b$ by a positive integer $n$ are equal, it is described mathematically as follows:&lt;/p>
$$
a \equiv b \pmod n
$$
&lt;p>This is read as &amp;ldquo;$a$ and $b$ are congruent modulo $n$&amp;rdquo;. For example, the remainder of 17 divided by 5 is 2, and the remainder of 12 divided by 5 is also 2. Therefore, it can be written as:&lt;/p>
$$
17 \equiv 12 \pmod 5 \equiv 2 \pmod 5
$$
&lt;p>In modular arithmetic, normal basic arithmetic operations (addition, subtraction, multiplication) apply as they are.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Addition&lt;/strong>: If $a \equiv b \pmod n$ and $c \equiv d \pmod n$, then $a + c \equiv b + d \pmod n$&lt;/li>
&lt;li>&lt;strong>Subtraction&lt;/strong>: If $a \equiv b \pmod n$ and $c \equiv d \pmod n$, then $a - c \equiv b - d \pmod n$&lt;/li>
&lt;li>&lt;strong>Multiplication&lt;/strong>: If $a \equiv b \pmod n$ and $c \equiv d \pmod n$, then $a \times c \equiv b \times d \pmod n$&lt;/li>
&lt;li>&lt;strong>Exponentiation&lt;/strong>: If $a \equiv b \pmod n$, then for any natural number $k$, $a^k \equiv b^k \pmod n$&lt;/li>
&lt;/ol>
&lt;p>However, care must be taken with &lt;strong>division&lt;/strong>. In general, just because $a \times c \equiv b \times c \pmod n$, you cannot divide both sides by $c$ to get $a \equiv b \pmod n$. This only holds true when $c$ and $n$ are coprime (their greatest common divisor is 1). This concept of &amp;ldquo;modular inverse&amp;rdquo; becomes extremely important in the key generation of RSA cryptography discussed later.&lt;/p>
&lt;hr>
&lt;h2 id="3-mathematical-background-and-proof-of-fermats-little-theorem">3. Mathematical Background and Proof of Fermat&amp;rsquo;s Little Theorem
&lt;/h2>&lt;p>Having grasped the basics of modular arithmetic, let&amp;rsquo;s look at the main subject, Fermat&amp;rsquo;s Little Theorem.&lt;/p>
&lt;h3 id="31-definition-of-the-theorem">3.1 Definition of the Theorem
&lt;/h3>&lt;p>Fermat&amp;rsquo;s Little Theorem is formulated as follows:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Fermat&amp;rsquo;s Little Theorem&lt;/strong>
Let $p$ be a prime number, and let $a$ be any integer that is not a multiple of $p$ (i.e., $a$ and $p$ are coprime). Then, the following congruence holds:
&lt;/p>
$$ a^{p-1} \equiv 1 \pmod p $$
&lt;/blockquote>
&lt;p>It is also common to express it in a form that holds for all integers $a$ by removing the condition that &amp;ldquo;$a$ is not a multiple of $p$&amp;rdquo;. In that case, multiplying both sides by $a$ gives:&lt;/p>
$$
a^p \equiv a \pmod p
$$
&lt;h3 id="32-verification-with-concrete-examples">3.2 Verification with Concrete Examples
&lt;/h3>&lt;p>Let&amp;rsquo;s check if the theorem really holds using specific numbers.
Let the prime number $p = 5$. $p-1 = 4$. We choose an integer $a$ that is not a multiple of $p$.&lt;/p>
&lt;ul>
&lt;li>For $a = 2$: $2^{5-1} = 2^4 = 16$. $16 \div 5 = 3$ remainder $1$. Thus $16 \equiv 1 \pmod 5$. (Holds)&lt;/li>
&lt;li>For $a = 3$: $3^{5-1} = 3^4 = 81$. $81 \div 5 = 16$ remainder $1$. Thus $81 \equiv 1 \pmod 5$. (Holds)&lt;/li>
&lt;li>For $a = 4$: $4^{5-1} = 4^4 = 256$. $256 \div 5 = 51$ remainder $1$. Thus $256 \equiv 1 \pmod 5$. (Holds)&lt;/li>
&lt;/ul>
&lt;p>In this way, no matter what $a$ you choose (as long as it&amp;rsquo;s not a multiple of 5), raising it to the 4th power and dividing by 5 will always yield a remainder of 1. It seems like magic, but this comes from the beautiful properties that prime numbers possess.&lt;/p>
&lt;h3 id="33-mathematical-proof-of-the-theorem">3.3 Mathematical Proof of the Theorem
&lt;/h3>&lt;p>Why does this happen? Here we introduce an elegant proof using the set of residue classes.&lt;/p>
&lt;p>Consider the set $S = \{1, 2, 3, \dots, p-1\}$. These are representatives of integers whose remainders when divided by $p$ are from $1$ to $p-1$.
Here, consider a new set $T$ obtained by multiplying each element by an integer $a$ that is coprime to $p$:
&lt;/p>
$$ T = \{1a, 2a, 3a, \dots, (p-1)a\} $$
&lt;p>Consider the remainder of each element of this set $T$ when divided by $p$. Surprisingly, these remainders, although their order might change, perfectly match the set of elements in the original set $S$.
Because:&lt;/p>
&lt;ol>
&lt;li>No element of $T$ can be a multiple of $p$ (since neither $a$ nor the original elements are multiples of $p$).&lt;/li>
&lt;li>There are no two distinct elements in $T$ that are congruent modulo $p$. If $ia \equiv ja \pmod p$ ($i \neq j$), since $a$ and $p$ are coprime, we can divide by $a$ to get $i \equiv j \pmod p$, which is a contradiction.&lt;/li>
&lt;/ol>
&lt;p>Therefore, the product of all elements of $S$ and the product of all elements of $T$ are congruent modulo $p$.&lt;/p>
$$
(1a) \times (2a) \times \dots \times ((p-1)a) \equiv 1 \times 2 \times \dots \times (p-1) \pmod p
$$
&lt;p>Simplifying the left side, since there are $p-1$ copies of $a$:&lt;/p>
$$
a^{p-1} \cdot (p-1)! \equiv (p-1)! \pmod p
$$
&lt;p>Since $(p-1)!$ is coprime to $p$, we can divide both sides by $(p-1)!$, which finally leads to the theorem:&lt;/p>
$$
a^{p-1} \equiv 1 \pmod p
$$
&lt;p>This is the proof of Fermat&amp;rsquo;s Little Theorem.&lt;/p>
&lt;hr>
&lt;h2 id="4-eulers-totient-function-and-eulers-theorem">4. Euler&amp;rsquo;s Totient Function and Euler&amp;rsquo;s Theorem
&lt;/h2>&lt;p>Fermat&amp;rsquo;s Little Theorem is a theorem concerning &amp;ldquo;prime numbers $p$&amp;rdquo;, but it was Leonhard Euler who generalized this to &amp;ldquo;any positive integer $n$&amp;rdquo;. This extension is essential for understanding RSA cryptography.&lt;/p>
&lt;h3 id="41-eulers-totient-function-phin">4.1 Euler&amp;rsquo;s Totient Function $\phi(n)$
&lt;/h3>&lt;p>Euler&amp;rsquo;s totient function (or Euler&amp;rsquo;s $\phi$ function) $\phi(n)$ is a function that represents &amp;ldquo;the number of integers from $1$ to $n$ that are coprime to $n$&amp;rdquo;.&lt;/p>
&lt;ul>
&lt;li>For a prime number $p$, all integers from $1$ to $p-1$ are coprime to $p$, so $\phi(p) = p - 1$.&lt;/li>
&lt;li>For two distinct prime numbers $p, q$, their product $n = p \times q$ has a $\phi(n)$ given by a very simple formula:
$$ \phi(p \times q) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$&lt;/li>
&lt;/ul>
&lt;p>This property is the fundamental logic in RSA key generation.&lt;/p>
&lt;h3 id="42-eulers-theorem">4.2 Euler&amp;rsquo;s Theorem
&lt;/h3>&lt;p>Euler generalized Fermat&amp;rsquo;s Little Theorem as follows:&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Euler&amp;rsquo;s Theorem&lt;/strong>
For a positive integer $n$ and an integer $a$ coprime to it, the following holds:
&lt;/p>
$$ a^{\phi(n)} \equiv 1 \pmod n $$
&lt;/blockquote>
&lt;p>If $n$ is a prime number $p$, then $\phi(p) = p - 1$, so this becomes Fermat&amp;rsquo;s Little Theorem itself ($a^{p-1} \equiv 1 \pmod p$). In other words, Fermat&amp;rsquo;s Little Theorem is merely a special case of Euler&amp;rsquo;s Theorem.&lt;/p>
&lt;hr>
&lt;h2 id="5-finding-giant-prime-numbers-fermat-primality-test">5. Finding Giant Prime Numbers: Fermat Primality Test
&lt;/h2>&lt;p>In cryptographic technologies (such as RSA cryptography and Diffie-Hellman key exchange), it is necessary to find &amp;ldquo;giant prime numbers&amp;rdquo; spanning hundreds of digits at high speed. However, to test whether a giant number $N$ is prime, checking if it is divisible by every number from $2$ to $\sqrt{N}$ (trial division) would take as long as the lifespan of the universe.&lt;/p>
&lt;p>This is where the &lt;strong>Fermat Primality Test&lt;/strong> comes in, a &amp;ldquo;probabilistic primality test&amp;rdquo; that takes advantage of Fermat&amp;rsquo;s Little Theorem.&lt;/p>
&lt;h3 id="51-what-is-a-probabilistic-primality-test">5.1 What is a Probabilistic Primality Test?
&lt;/h3>&lt;p>According to Fermat&amp;rsquo;s Little Theorem, if $p$ is prime, then for any $a$ ($1 &lt; a &lt; p$), $a^{p-1} \equiv 1 \pmod p$ must hold.
Taking the contrapositive, we can say that &amp;ldquo;if $a^{p-1} \not\equiv 1 \pmod p$ for some $a$, then $p$ is &lt;strong>absolutely not a prime number (it is a composite number)&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>Therefore, if we want to determine whether $N$ is prime, we randomly choose several $a$&amp;rsquo;s, calculate $a^{N-1} \pmod N$, and check if it equals $1$. If an answer other than $1$ appears even once, $N$ is definitively a composite number. If it equals $1$ no matter how many times we try, we can determine with high probability that $N$ is &amp;ldquo;probably prime&amp;rdquo;.&lt;/p>
&lt;h3 id="52-algorithm-explanation-and-flowchart">5.2 Algorithm Explanation and Flowchart
&lt;/h3>&lt;p>The algorithm for the Fermat primality test is as follows:&lt;/p>
&lt;div class="mermaid">flowchart TD
Start["Start"] --> Input["Input number to test p and number of tests k"]
Input --> LoopStart["Loop for i = 0 to k-1"]
LoopStart --> Condition{"i &lt; k ?"}
Condition -- "Yes" --> RandomA["Select random integer a in range 1 &lt; a &lt; p-1"]
RandomA --> Calc["Calculate modular exponentiation a^(p-1) mod p"]
Calc --> CheckPrime{"Is result 1 ?"}
CheckPrime -- "No" --> ReturnComposite["p is a composite number (definite)"]
CheckPrime -- "Yes" --> Increment["Increment i"]
Increment --> Condition
Condition -- "No" --> ReturnPrime["p is probably prime (probabilistic)"]
ReturnComposite --> End["End"]
ReturnPrime --> End&lt;/div>
&lt;h3 id="53-the-pitfall-of-carmichael-numbers-pseudoprimes">5.3 The Pitfall of Carmichael Numbers (Pseudoprimes)
&lt;/h3>&lt;p>While the Fermat test is very fast, it has a significant flaw. There are devilish numbers that are composite numbers but still satisfy $a^{N-1} \equiv 1 \pmod N$ for all $a$. These are called &lt;strong>Carmichael numbers&lt;/strong>. The smallest Carmichael number is $561$ ($3 \times 11 \times 17$).&lt;/p>
&lt;p>Because Carmichael numbers exist, a pure Fermat test alone cannot provide absolute primality testing. Therefore, in actual cryptographic systems (such as OpenSSL), the &lt;strong>Miller-Rabin primality test&lt;/strong>, an improved version of the Fermat test, is used as the standard. The Miller-Rabin test can detect Carmichael numbers, effectively reducing the probability of misjudgment to zero.&lt;/p>
&lt;h3 id="54-fast-modular-exponentiation-exponentiation-by-squaring">5.4 Fast Modular Exponentiation (Exponentiation by Squaring)
&lt;/h3>&lt;p>In the primality testing algorithm, we need to calculate $a^{N-1} \pmod N$, but when $N$ is huge, $a^{N-1}$ becomes an astronomically large number that cannot fit into a computer&amp;rsquo;s memory.
This is solved by &lt;strong>Exponentiation by Squaring&lt;/strong> or modular exponentiation. By taking the modulo ($mod N$) at each step of the calculation, the value is always kept smaller than $N$, allowing it to be calculated very quickly (with a computational complexity of $O(\log N)$).&lt;/p>
&lt;hr>
&lt;h2 id="6-implementation-of-primality-testing-and-modular-exponentiation">6. Implementation of Primality Testing and Modular Exponentiation
&lt;/h2>&lt;p>Now, let&amp;rsquo;s implement the Fermat primality test and exponentiation by squaring in C++ and Python.&lt;/p>
&lt;h3 id="61-implementation-in-c">6.1 Implementation in C++
&lt;/h3>&lt;p>In C++, standard integer types are prone to overflow, so handling giant numbers requires a multiple-precision integer library (like GMP), but here we show an implementation within the range of 64-bit integers (&lt;code>unsigned long long&lt;/code>) to understand the algorithm.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;random&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Fast modular exponentiation (a^b mod m) - Exponentiation by squaring
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="nf">power_mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// If the lowest bit of b is 1, multiply result by a
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">__int128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">result&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 128-bit extension to prevent overflow
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Square a
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">__int128&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Right shift b (halve it)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Fermat primality test
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">bool&lt;/span> &lt;span class="nf">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">iterations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">random_device&lt;/span> &lt;span class="n">rd&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">mt19937_64&lt;/span> &lt;span class="n">gen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rd&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">uniform_int_distribution&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">dis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dis&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">gen&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// If a^(p-1) mod p is not 1, it&amp;#39;s composite
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">power_mod&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Probably prime
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000000007&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// A known prime
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is probably prime.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; is composite.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-implementation-in-python">6.2 Implementation in Python
&lt;/h3>&lt;p>Python&amp;rsquo;s standard integer type supports arbitrary precision integers, so there&amp;rsquo;s no need to worry about overflow. Furthermore, Python&amp;rsquo;s built-in function &lt;code>pow(a, b, m)&lt;/code> internally uses exponentiation by squaring, so it&amp;rsquo;s very fast.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> Probabilistic primality test using Fermat&amp;#39;s primality test
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">iterations&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Choose a random number a between 2 and p-2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calculate a^(p-1) mod p. Built-in pow is fast.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">False&lt;/span> &lt;span class="c1"># Definitely composite&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="kc">True&lt;/span> &lt;span class="c1"># Probably prime&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"># Test&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">number_to_test&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">104729&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">fermat_is_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> is probably prime.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">number_to_test&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> is composite.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="7-application-to-rsa-cryptography-where-fermat-and-euler-bear-fruit">7. Application to RSA Cryptography: Where Fermat and Euler Bear Fruit
&lt;/h2>&lt;p>The greatest application of Fermat&amp;rsquo;s Little Theorem (and Euler&amp;rsquo;s Theorem) is &lt;strong>RSA cryptography&lt;/strong>, developed in 1977 by Rivest, Shamir, and Adleman.
RSA cryptography is an epoch-making system called &amp;ldquo;public-key cryptography&amp;rdquo;, realizing a mechanism where the key for encryption (public key) is published to the whole world, while the key for decryption (private key) is known only to the receiver themselves.&lt;/p>
&lt;p>This asymmetry is based on the computational security that &amp;ldquo;factorizing a giant composite number into its prime factors is extremely difficult.&amp;rdquo;&lt;/p>
&lt;h3 id="71-mechanism-of-rsa-cryptography-key-generation-encryption-decryption">7.1 Mechanism of RSA Cryptography (Key Generation, Encryption, Decryption)
&lt;/h3>&lt;p>Let&amp;rsquo;s check the overall communication flow of RSA cryptography with a Mermaid sequence diagram.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice["Alice (Receiver)"]
participant Bob["Bob (Sender)"]
Alice->>Alice: "Generate large primes p, q"
Alice->>Alice: "Calculate N = p * q, φ(N) = (p-1)(q-1)"
Alice->>Alice: "Calculate public key e and private key d (e*d ≡ 1 mod φ(N))"
Alice->>Bob: "Send public key (N, e)"
Note over Bob: "Prepare plaintext M (M &lt; N)"
Bob->>Bob: "Calculate ciphertext C = M^e mod N"
Bob->>Alice: "Send ciphertext C"
Alice->>Alice: "Calculate plaintext M = C^d mod N to decrypt"&lt;/div>
&lt;p>The mathematical detail steps are explained below.&lt;/p>
&lt;h4 id="step-1-key-generation-task-of-receiver-alice">Step 1: Key Generation (Task of Receiver Alice)
&lt;/h4>&lt;ol>
&lt;li>Randomly generate two giant prime numbers $p$ and $q$ (the primality test mentioned above is used here).&lt;/li>
&lt;li>Calculate their product $N = p \times q$. This $N$ is made public.&lt;/li>
&lt;li>Using Euler&amp;rsquo;s totient function, calculate $\phi(N) = (p-1)(q-1)$.&lt;/li>
&lt;li>Choose an integer $e$ (public exponent) that is coprime to $\phi(N)$ (often $e = 65537$ is used).&lt;/li>
&lt;li>Calculate the modular inverse $d$ (private exponent) of $e$. In other words, find $d$ that satisfies:
$$ e \cdot d \equiv 1 \pmod{\phi(N)} $$
The &lt;strong>extended Euclidean algorithm&lt;/strong> is used for this calculation.&lt;/li>
&lt;/ol>
&lt;p>Now, the &lt;strong>public key is $(N, e)$&lt;/strong>, and the &lt;strong>private key is $(N, d)$&lt;/strong>. ($p, q, \phi(N)$ are immediately discarded or strictly hidden).&lt;/p>
&lt;h4 id="step-2-encryption-task-of-sender-bob">Step 2: Encryption (Task of Sender Bob)
&lt;/h4>&lt;p>Suppose Bob wants to send a message $M$ to Alice ($M$ is a numerically converted character, and $0 \le M &lt; N$).
Bob uses Alice&amp;rsquo;s public key $(N, e)$ to perform the following calculation to create ciphertext $C$.&lt;/p>
$$
C \equiv M^e \pmod N
$$
&lt;p>He sends this $C$ to Alice over the network.&lt;/p>
&lt;h4 id="step-3-decryption-task-of-receiver-alice">Step 3: Decryption (Task of Receiver Alice)
&lt;/h4>&lt;p>Alice, receiving the ciphertext $C$, performs the following calculation using the private key $d$ that only she knows.&lt;/p>
$$
M' \equiv C^d \pmod N
$$
&lt;p>Surprisingly, this calculation result $M'$ perfectly matches the original message $M$.&lt;/p>
&lt;h3 id="72-why-can-it-be-decrypted-mathematical-proof">7.2 Why can it be decrypted? (Mathematical Proof)
&lt;/h3>&lt;p>Here, Fermat&amp;rsquo;s Little Theorem (Euler&amp;rsquo;s Theorem) shows its true worth. Why does $C^d \pmod N$ return to $M$?&lt;/p>
&lt;p>Let&amp;rsquo;s expand the decryption equation.
Since $C \equiv M^e \pmod N$,
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>In the key generation step, we chose $d$ such that $e \cdot d \equiv 1 \pmod{\phi(N)}$. This means there exists an integer $k$ such that it can be written as:
&lt;/p>
$$ e \cdot d = 1 + k \cdot \phi(N) $$
&lt;p>Substitute this into the above equation:
&lt;/p>
$$ M^{ed} = M^{1 + k \cdot \phi(N)} = M \cdot M^{k \cdot \phi(N)} = M \cdot (M^{\phi(N)})^k \pmod N $$
&lt;p>Here, &lt;strong>Euler&amp;rsquo;s Theorem&lt;/strong> ($M^{\phi(N)} \equiv 1 \pmod N$) comes into play. (*Strictly speaking, $M$ and $N$ need to be coprime, but in RSA, the probability that $M$ and $N$ are not coprime is astronomically low, and using the Chinese Remainder Theorem, it can be proven to hold even if they are not coprime).&lt;/p>
&lt;p>Applying Euler&amp;rsquo;s Theorem, since $M^{\phi(N)} \equiv 1$:
&lt;/p>
$$ M \cdot (1)^k \equiv M \pmod N $$
&lt;p>$M$ is beautifully restored! The properties of numbers discovered hundreds of years ago by Fermat and Euler perfectly guarantee the confidentiality of modern digital communication.&lt;/p>
&lt;hr>
&lt;h2 id="8-toy-implementation-of-rsa-cryptography-python">8. Toy Implementation of RSA Cryptography (Python)
&lt;/h2>&lt;p>It&amp;rsquo;s hard to get a real feel from theory alone, so let&amp;rsquo;s actually implement the key generation, encryption, and decryption process of RSA cryptography using Python. This is a &amp;ldquo;toy implementation&amp;rdquo; for educational purposes, but the math used is exactly the same as the real thing.&lt;/p>
&lt;p>The &amp;ldquo;extended Euclidean algorithm&amp;rdquo; for finding the modular inverse $d$ is also included in the implementation.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;span class="lnt">84
&lt;/span>&lt;span class="lnt">85
&lt;/span>&lt;span class="lnt">86
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Find the greatest common divisor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">b&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Extended Euclidean algorithm (Find x, y for ax + by = gcd(a,b))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Used to find d for e*d ≡ 1 (mod φ(N))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">//&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">extended_gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">Exception&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Inverse does not exist&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">phi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Prime number generation function (simplified version: generates small primes)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="kc">True&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getrandbits&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Simplified check instead of the Fermat test mentioned above&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">p&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># RSA key generation&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">16&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Ensure p and q are not the same&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">q&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">q&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_prime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">q&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">phi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">q&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># e is often a prime like 65537, but here we choose it randomly&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="n">g&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randrange&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calculation of private key d&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mod_inverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">phi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Public key (e, n), Private key (d, n)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">plaintext&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calculate plaintext^e mod n&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cipher&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">ord&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">plaintext&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">cipher&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sk&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ciphertext&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Calculate cipher^d mod n and convert back to characters&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">plain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="nb">chr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">pow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">char&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">ciphertext&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">plain&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Example execution&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;--- RSA Cryptography Toy Implementation ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">private_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">generate_keypair&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bits&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">12&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># Use 12-bit primes&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;Public key (e, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">public_key&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Private key (d, n): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">private_key&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Hello Math!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">Original message: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">message&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Encryption&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">encrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">encrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">public_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Ciphertext: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">encrypted_msg&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Decryption&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">decrypted_msg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">decrypt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">private_key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">encrypted_msg&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Decrypted message: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">decrypted_msg&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>When you run this code, you can see how an array of characters is converted into an unfamiliar array of numbers (ciphertext), which is then beautifully restored to the original string by the private key.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusion-the-intersection-of-mathematical-beauty-and-practicality">9. Conclusion: The Intersection of Mathematical Beauty and Practicality
&lt;/h2>&lt;p>In the 17th century when Pierre de Fermat discovered this &amp;ldquo;Little Theorem&amp;rdquo;, no one thought it would be of any use. Fermat himself studied number theory out of pure mathematical curiosity.&lt;/p>
&lt;p>However, about 300 years later in the 1970s, at the dawn of computer networks, Fermat&amp;rsquo;s theorem made a dramatic comeback as an indispensable cryptographic technology for establishing secure communication protocols. Primality testing technology based on Fermat&amp;rsquo;s Little Theorem and RSA cryptography based on Euler&amp;rsquo;s theorem literally support modern Internet infrastructure.&lt;/p>
&lt;p>The LINE messages we casually send every day, the shopping on Amazon, all dance on this simple and beautiful formula $a^{p-1} \equiv 1 \pmod p$. No matter how abstract mathematics may be, Fermat&amp;rsquo;s Little Theorem teaches us that the time will definitely come when it will be useful to humanity.&lt;/p>
&lt;p>When studying programming or cryptographic theory, understanding the mathematical structures at their foundation will become a great weapon for deeply understanding the behavior of libraries provided as black boxes and designing more secure systems.&lt;/p></description></item><item><title>Mathematical Intuition of Lattice-based Cryptography</title><link>http://kenji.blog/en/p/lattice-based-cryptography-math-intuition/</link><pubDate>Fri, 11 Sep 2026 21:00:00 +0900</pubDate><guid>http://kenji.blog/en/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 Mathematical Intuition of Lattice-based Cryptography" />&lt;h1 id="1-introduction-the-dawn-of-post-quantum-cryptography-pqc-and-the-rise-of-lattice-based-cryptography">1. Introduction: The Dawn of Post-Quantum Cryptography (PQC) and the Rise of Lattice-based Cryptography
&lt;/h1>&lt;p>The digital infrastructure of modern society is supported by public-key cryptography technologies such as RSA cryptography and Elliptic Curve Cryptography (ECC). These cryptographic schemes base their security on the mathematical difficulty of problems like the &amp;ldquo;prime factorization problem&amp;rdquo; and the &amp;ldquo;discrete logarithm problem,&amp;rdquo; which are believed to be inefficient (requiring exponential time) to solve with conventional classical computers.&lt;/p>
&lt;p>However, &amp;ldquo;Shor&amp;rsquo;s algorithm,&amp;rdquo; published by Peter Shor in 1994, sent shockwaves through the cryptographic world. This algorithm mathematically proved that once a large-scale quantum computer is realized, it would be able to solve the prime factorization problem and the discrete logarithm problem in polynomial time. This means that the widely used public-key cryptography of today will become completely decipherable in the future.&lt;/p>
&lt;p>To counter such a &amp;ldquo;Quantum Threat,&amp;rdquo; research into new cryptographic schemes that are difficult to break even with quantum computers became an urgent task. This field is called &amp;ldquo;Post-Quantum Cryptography (PQC)&amp;rdquo; or &amp;ldquo;quantum-resistant cryptography.&amp;rdquo;&lt;/p>
&lt;p>There are several strong candidates for PQC. Examples include hash-based cryptography, code-based cryptography, multivariate polynomial cryptography, and isogeny-based cryptography. Among them, &amp;ldquo;Lattice-based cryptography&amp;rdquo; is currently attracting the most attention and is at the center of the PQC standardization process by NIST (National Institute of Standards and Technology). Compared to other methods, lattice-based cryptography has extremely fast encryption and decryption processing speeds, and it has the outstanding feature of an extremely strong security proof in cryptographic theory: a reduction from &amp;ldquo;worst-case complexity&amp;rdquo; to &amp;ldquo;average-case complexity.&amp;rdquo;&lt;/p>
&lt;p>In this article, starting from the mathematical definition of a &amp;ldquo;Lattice,&amp;rdquo; which is the foundation of lattice-based cryptography, we will thoroughly and deeply explain difficult problems on lattices such as SVP (Shortest Vector Problem) and CVP (Closest Vector Problem), and the &amp;ldquo;LWE (Learning With Errors) problem,&amp;rdquo; which can be said to be the heart of modern lattice-based cryptography, using mathematical formulas, geometric intuition, and specific numerical examples.&lt;/p>
&lt;h1 id="2-mathematical-definition-and-geometric-intuition-of-a-lattice">2. Mathematical Definition and Geometric Intuition of a Lattice
&lt;/h1>&lt;h2 id="21-vector-spaces-and-lattices">2.1 Vector Spaces and Lattices
&lt;/h2>&lt;p>In mathematics, a &amp;ldquo;Lattice&amp;rdquo; is a set of discrete points arranged regularly in an $n$-dimensional real vector space $\mathbb{R}^n$. It is similar to a Vector Space learned in linear algebra, but there is a crucial difference. While a vector space is a continuous space represented by a linear combination of basis vectors with &amp;ldquo;real coefficients,&amp;rdquo; a lattice is a discrete space represented by a linear combination of basis vectors with &amp;ldquo;integer coefficients.&amp;rdquo;&lt;/p>
&lt;p>Let&amp;rsquo;s give a strict mathematical definition. Consider $n$ ($n \le m$) linearly independent vectors $\mathbf{b}_1, \mathbf{b}_2, \dots, \mathbf{b}_n$ in an $m$-dimensional real vector space $\mathbb{R}^m$. Let a matrix having these vectors as column vectors be $B = [\mathbf{b}_1, \mathbf{b}_2, \dots, \mathbf{b}_n] \in \mathbb{R}^{m \times n}$. This $B$ is called the &amp;ldquo;Basis&amp;rdquo; of the lattice.&lt;/p>
&lt;p>The lattice $\mathcal{L}(B)$ generated by this basis $B$ is defined as follows:&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>What is important here is that the coefficients $x_i$ are limited to integers $\mathbb{Z}$, not real numbers $\mathbb{R}$. As a result, rather than a continuous space with infinitely many points, a &amp;ldquo;set of discrete points&amp;rdquo; like equally spaced intersections is formed.&lt;/p>
&lt;h2 id="22-geometric-image">2.2 Geometric Image
&lt;/h2>&lt;p>Let&amp;rsquo;s consider an example of a 2-dimensional plane $\mathbb{R}^2$. When $\mathbf{b}_1 = \begin{pmatrix} 1 \\ 0 \end{pmatrix}$ and $\mathbf{b}_2 = \begin{pmatrix} 0 \\ 1 \end{pmatrix}$ are chosen as basis vectors, the lattice generated by them is the set of all integer coordinates $(x, y) \in \mathbb{Z}^2$ on the coordinate plane. This is the simplest &amp;ldquo;square lattice.&amp;rdquo;&lt;/p>
&lt;p>However, lattices are not always orthogonal. For example, considering the basis $\mathbf{b}_1 = \begin{pmatrix} 2 \\ 1 \end{pmatrix}$ and $\mathbf{b}_2 = \begin{pmatrix} 1 \\ 3 \end{pmatrix}$, the generated points become like the intersections of an obliquely skewed mesh.&lt;/p>
&lt;h2 id="23-non-uniqueness-of-the-basis-and-unimodular-transformations">2.3 Non-uniqueness of the Basis and Unimodular Transformations
&lt;/h2>&lt;p>There is an important property related to the foundation of the security of lattice-based cryptography. That is, &amp;ldquo;there are infinitely many bases that generate the same lattice.&amp;rdquo;&lt;/p>
&lt;p>For example, the $\mathbb{Z}^2$ lattice generated by the previous basis $\mathbf{b}_1 = (1, 0)^T, \mathbf{b}_2 = (0, 1)^T$ can be generated as exactly the same lattice $\mathbb{Z}^2$ using the basis $\mathbf{b}'_1 = (1, 1)^T, \mathbf{b}'_2 = (2, 3)^T$.&lt;/p>
&lt;p>The necessary and sufficient condition for a basis $B$ and another basis $B'$ to generate the same lattice is that there exists a matrix with integer components $U \in \mathbb{Z}^{n \times n}$ whose determinant is $\det(U) = \pm 1$, and it can be expressed as:
&lt;/p>
$$ B' = B U $$
&lt;p>
Such a matrix $U$ is called a &amp;ldquo;Unimodular matrix.&amp;rdquo;&lt;/p>
&lt;p>The basic idea in its application to cryptography is to use a &amp;ldquo;good basis&amp;rdquo; (a basis that is close to orthogonal and consists of short vectors) as a secret key, and a &amp;ldquo;bad basis&amp;rdquo; (a basis that is extremely skewed relative to each other and consists of very long vectors) as a public key. It becomes very difficult to calculate a good basis from a bad basis as the dimension increases. This is the basic intuition behind lattice-based cryptography.&lt;/p>
&lt;h1 id="3-computationally-hard-problems-in-lattices">3. Computationally Hard Problems in Lattices
&lt;/h1>&lt;p>The security of lattice-based cryptography depends on the difficulty of solving specific mathematical problems on lattices. Here, we introduce the two most fundamental and famous problems.&lt;/p>
&lt;h2 id="31-shortest-vector-problem-svp">3.1 Shortest Vector Problem (SVP)
&lt;/h2>&lt;p>SVP is the most classical and famous problem in lattice theory.&lt;/p>
&lt;p>&lt;strong>Definition (SVP):&lt;/strong>
Given an arbitrary lattice basis $B$, find the vector $\mathbf{v}$ with the minimum Euclidean norm (length) among the non-zero vectors belonging to that lattice $\mathcal{L}(B)$.&lt;/p>
&lt;p>Expressed mathematically, it is the problem of finding $\mathbf{v}$ such that $\min_{\mathbf{v} \in \mathcal{L}(B) \setminus \{\mathbf{0}\}} \| \mathbf{v} \|$. This minimum length is written as $\lambda_1(\mathcal{L})$ and is called the &amp;ldquo;first successive minimum&amp;rdquo; of the lattice.&lt;/p>
&lt;p>In lower dimensions such as 2D or 3D, you can draw a figure and visually find the shortest vector. Alternatively, it can be efficiently solved using algorithms like Gauss&amp;rsquo;s lattice reduction algorithm. However, when the dimension $n$ becomes a high dimension such as hundreds to thousands, it is known that strictly solving SVP is NP-hard.&lt;/p>
&lt;p>In actual cryptography, instead of the strict shortest vector, an approximate SVP ($\gamma$-SVP) is used, which finds an &amp;ldquo;approximately short vector.&amp;rdquo; When the approximation factor $\gamma$ is of polynomial size, this problem is still considered very difficult.&lt;/p>
&lt;h2 id="32-closest-vector-problem-cvp">3.2 Closest Vector Problem (CVP)
&lt;/h2>&lt;p>CVP is also an extremely important problem in lattice-based cryptography.&lt;/p>
&lt;p>&lt;strong>Definition (CVP):&lt;/strong>
Given an arbitrary lattice basis $B$ and an arbitrary target vector $\mathbf{t} \in \mathbb{R}^m$ in space (which is not necessarily a lattice point), find the lattice point $\mathbf{v} \in \mathcal{L}(B)$ that is closest to $\mathbf{t}$ among the lattice points.&lt;/p>
&lt;p>Expressed mathematically, it is the problem of searching for a lattice point $\mathbf{v}$ such that $\min_{\mathbf{v} \in \mathcal{L}(B)} \| \mathbf{v} - \mathbf{t} \|$.&lt;/p>
&lt;p>Like SVP, CVP is also NP-hard in high dimensions. From the perspective of application to cryptography, the LWE problem described later is closely related to a special variant of this CVP (Bounded Distance Decoding: BDD).&lt;/p>
&lt;h2 id="33-why-are-they-unsolvable-in-high-dimensions-limits-of-lll-and-bkz">3.3 Why Are They Unsolvable in High Dimensions? (Limits of LLL and BKZ)
&lt;/h2>&lt;p>A famous algorithm for solving high-dimensional lattice problems is the LLL algorithm (Lenstra-Lenstra-Lovász algorithm). The LLL algorithm operates in polynomial time and can reduce a lattice basis to a &amp;ldquo;good basis&amp;rdquo; to some extent. However, since the shortest vector found by the LLL algorithm has an exponential approximation factor ($2^{\mathcal{O}(n)}$) relative to the length of the true shortest vector, it is not enough to break the security of the cryptography.&lt;/p>
&lt;p>By using a more powerful basis reduction algorithm such as the BKZ (Block Korkine-Zolotarev) algorithm, which is an improvement over LLL, a shorter vector can be found, but its computational complexity increases exponentially with respect to the block size. In lattice-based cryptography, secure parameters (such as the size of the dimension $n$) are determined by estimating the execution time of this BKZ algorithm. In current PQC standard parameters, values of dimension $n$ from 500 to over 1000 are chosen, and it is said that it would take more than the age of the universe to decrypt even if supercomputers or future quantum computers were used.&lt;/p>
&lt;h1 id="4-mathematical-formulation-of-the-lwe-learning-with-errors-problem">4. Mathematical Formulation of the LWE (Learning With Errors) Problem
&lt;/h1>&lt;p>Most of modern lattice-based cryptography is based on the &amp;ldquo;LWE (Learning With Errors) problem&amp;rdquo; proposed by Oded Regev in 2005. The beauty of the LWE problem lies in the simplicity of its formulation and the fact that it has a powerful mathematical proof of &amp;ldquo;reduction from worst-case to average-case complexity.&amp;rdquo;&lt;/p>
&lt;h2 id="41-systems-of-linear-equations-without-noise">4.1 Systems of Linear Equations Without Noise
&lt;/h2>&lt;p>To understand the LWE problem, let&amp;rsquo;s first consider a simple system of linear equations without noise.
Suppose there is an unknown secret vector $\mathbf{s} \in \mathbb{Z}_q^n$ (each component is an integer from $0$ to $q-1$). Here, $q$ is assumed to be a prime number.&lt;/p>
&lt;p>Choose random coefficient vectors $\mathbf{a}_1, \mathbf{a}_2, \dots \in \mathbb{Z}_q^n$, and calculate their inner product with the secret vector $\mathbf{s}$ modulo $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>Given a sufficient number (at least $n$) of pairs $(\mathbf{a}_i, b_i)$, we can easily recover the secret vector $\mathbf{s}$ by using &amp;ldquo;Gaussian elimination&amp;rdquo; in linear algebra. This is a problem that can be easily solved in polynomial time.&lt;/p>
&lt;h2 id="42-definition-of-the-lwe-problem-adding-noise">4.2 Definition of the LWE Problem: Adding Noise
&lt;/h2>&lt;p>So, what happens if we add a slight &amp;ldquo;noise (error)&amp;rdquo; to this problem?
This is the essence of the LWE problem.&lt;/p>
&lt;p>For an unknown secret vector $\mathbf{s} \in \mathbb{Z}_q^n$, we add a small error $e_i \in \mathbb{Z}_q$ to the result of each equation.
$b_i = \langle \mathbf{a}_i, \mathbf{s} \rangle + e_i \pmod q$&lt;/p>
&lt;p>Here, $e_i$ is a small integer value with a mean of 0 and a relatively small standard deviation (for example, chosen from a discrete Gaussian distribution, like a normal distribution).
The given information is a list of pairs of a random vector $\mathbf{a}_i$ and $b_i$ calculated by adding an error to it.
$( \mathbf{a}_1, b_1 ), ( \mathbf{a}_2, b_2 ), \dots, ( \mathbf{a}_m, b_m )$&lt;/p>
&lt;p>This becomes very neat when expressed as a matrix.
Using a random matrix $A \in \mathbb{Z}_q^{m \times n}$, a secret vector $\mathbf{s} \in \mathbb{Z}_q^n$, and an error vector $\mathbf{e} \in \mathbb{Z}_q^m$, it can be written as:
&lt;/p>
$$ \mathbf{b} = A \mathbf{s} + \mathbf{e} \pmod q $$
&lt;p>
Only $A$ and $\mathbf{b}$ are given. The problem of finding $\mathbf{s}$ from this is the &amp;ldquo;Search LWE problem.&amp;rdquo;&lt;/p>
&lt;p>Because the error $e_i$ is included, if one tries to use Gaussian elimination, the errors amplify exponentially during the process of adding and subtracting equations, making it impossible to reach the correct answer. At first glance, it looks like a simple system of linear equations, but just by adding this small noise, the difficulty of the problem jumps to an NP-hard level.&lt;/p>
&lt;h2 id="43-decision-lwe-problem">4.3 Decision LWE Problem
&lt;/h2>&lt;p>What is frequently used in cryptographic theory proofs is the &amp;ldquo;Decision LWE problem,&amp;rdquo; a variation of the Search LWE problem.&lt;/p>
&lt;p>The Decision LWE problem is the problem of determining which of the following two distributions a given list of samples came from:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>LWE Distribution&lt;/strong>: Intentionally calculated $(A, \mathbf{b} = A\mathbf{s} + \mathbf{e} \pmod q)$&lt;/li>
&lt;li>&lt;strong>Uniform Random Distribution&lt;/strong>: $(A, \mathbf{u})$ consisting of a completely randomly chosen matrix $A$ and vector $\mathbf{u}$&lt;/li>
&lt;/ol>
&lt;p>Surprisingly, if the parameters of the LWE problem are chosen appropriately, the pairs obtained from the LWE distribution become &amp;ldquo;Computationally Indistinguishable&amp;rdquo; from pairs of completely random data. This property provides the foundation for LWE-based cryptography to generate &amp;ldquo;ciphertexts indistinguishable from random numbers.&amp;rdquo;&lt;/p>
&lt;h2 id="44-reduction-from-worst-case-to-average-case-complexity-regevs-theorem">4.4 Reduction from Worst-Case to Average-Case Complexity (Regev&amp;rsquo;s Theorem)
&lt;/h2>&lt;p>Oded Regev&amp;rsquo;s greatest achievement is mathematically linking the difficulty of this LWE problem to the difficulty of the aforementioned lattice problems (SVP and CVP).&lt;/p>
&lt;p>Using a quantum reduction, he proved that &amp;ldquo;if there is a polynomial-time algorithm that can solve the LWE problem on average (for randomly chosen $A$ and $\mathbf{e}$), then there is a polynomial-time quantum algorithm that can solve the Gap-SVP for the worst case (the most difficult case) of any lattice.&amp;rdquo; (Later, a classical reduction was also demonstrated by Peikert et al.)&lt;/p>
&lt;p>This is a dream-like property in cryptographic theory. This is because it dispels the concern that &amp;ldquo;the cipher might be broken because we happened to choose a weak key (a part of the average case),&amp;rdquo; and gives a strong guarantee that &amp;ldquo;if average-case LWE can be solved, all hard problems on lattices can be solved (therefore LWE is absolutely hard).&amp;rdquo;&lt;/p>
&lt;div class="mermaid">graph TD
A["Worst-case Lattice Problems (Gap-SVP, SIVP)"] -->|Quantum/Classical Reduction| B["Average-case LWE Problem"]
B -->|Cryptographic Construction| C["LWE-based Cryptosystems (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-construction-of-a-public-key-cryptosystem-regevs-cryptosystem-using-lwe">5. Construction of a Public-Key Cryptosystem (Regev&amp;rsquo;s Cryptosystem) using LWE
&lt;/h1>&lt;p>Now that we understand the difficulty of the LWE problem, let&amp;rsquo;s look at the basic public-key cryptosystem proposed by Oded Regev to see how it is used for encryption and decryption. Here, we will explain the most basic mechanism for encrypting a 1-bit message $M \in \{0, 1\}$.&lt;/p>
&lt;h2 id="51-key-generation">5.1 Key Generation
&lt;/h2>&lt;ol>
&lt;li>Determine the system parameters: the modulus prime number $q$, the dimension $n$, and the number of equations $m$ ($m > n \log q$).&lt;/li>
&lt;li>As a secret key, choose a vector $\mathbf{s} \in \mathbb{Z}_q^n$ at random.&lt;/li>
&lt;li>Generate a random matrix $A \in \mathbb{Z}_q^{m \times n}$.&lt;/li>
&lt;li>Choose a small error vector $\mathbf{e} \in \mathbb{Z}_q^m$ from an error distribution such as a discrete Gaussian distribution.&lt;/li>
&lt;li>Calculate the vector $\mathbf{b} = A \mathbf{s} + \mathbf{e} \pmod q$.&lt;/li>
&lt;li>The Public Key will be $(A, \mathbf{b})$.&lt;/li>
&lt;li>The Secret Key will be $\mathbf{s}$.&lt;/li>
&lt;/ol>
&lt;p>The public key is exactly an &amp;ldquo;instance of the LWE problem.&amp;rdquo; Finding the secret key $\mathbf{s}$ from the public key $(A, \mathbf{b})$ is equivalent to solving the Search LWE problem, thereby ensuring security.&lt;/p>
&lt;h2 id="52-encryption">5.2 Encryption
&lt;/h2>&lt;p>Alice encrypts a 1-bit message $M \in \{0, 1\}$ using Bob&amp;rsquo;s public key $(A, \mathbf{b})$.&lt;/p>
&lt;ol>
&lt;li>Choose a random binary vector (components are 0 or 1) $\mathbf{r} \in \{0, 1\}^m$.&lt;/li>
&lt;li>As the first half of the ciphertext, compute the vector $\mathbf{u} = A^T \mathbf{r} \pmod q$. ($A^T$ is the transpose of $A$. That is, we are adding up the rows of $A$ where the component of $\mathbf{r}$ is 1).&lt;/li>
&lt;li>As the second half of the ciphertext, compute the scalar $v = \mathbf{b}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor \pmod q$.
(If the message $M$ is 0, add nothing; if $1$, add exactly half the value of $q$, $\lfloor \frac{q}{2} \rfloor$).&lt;/li>
&lt;li>The Ciphertext will be $(\mathbf{u}, v)$.&lt;/li>
&lt;/ol>
&lt;p>The intuitive meaning of encryption is to take the &amp;ldquo;sum of a random subset&amp;rdquo; for the public key matrix $A$ and vector $\mathbf{b}$. Due to the difficulty of the Decision LWE problem, this ciphertext $(\mathbf{u}, v)$ appears indistinguishable from a completely random vector and uniform random number (Semantic Security).&lt;/p>
&lt;div class="mermaid">flowchart LR
M["Message M in {0,1}"] --> Enc
PK["Public Key (A, b)"] --> Enc
r["Random binary vector r"] --> Enc
subgraph Enc ["Encryption Process"]
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["Ciphertext (u, v)"]&lt;/div>
&lt;h2 id="53-decryption">5.3 Decryption
&lt;/h2>&lt;p>Bob decrypts the ciphertext $(\mathbf{u}, v)$ using the secret key $\mathbf{s}$.&lt;/p>
&lt;ol>
&lt;li>Compute the following value: $D = v - \mathbf{s}^T \mathbf{u} \pmod q$&lt;/li>
&lt;li>If the computed result is closer to $0$, output $M=0$; if it is closer to $\lfloor \frac{q}{2} \rfloor$, output $M=1$.&lt;/li>
&lt;/ol>
&lt;p>Let&amp;rsquo;s expand this mathematically to see why this can decrypt the message.
Recall that $\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>Here, $\mathbf{s}^T A^T \mathbf{r}$ perfectly cancelled out from the equation!
What remains is $\mathbf{e}^T \mathbf{r} + M \cdot \lfloor \frac{q}{2} \rfloor$.&lt;/p>
&lt;p>$\mathbf{e}$ is a noise vector with very small components, and $\mathbf{r}$ is a binary vector whose components are 0 or 1. Therefore, their inner product $\mathbf{e}^T \mathbf{r}$ also remains a relatively small value (if parameters are chosen properly).&lt;/p>
&lt;ul>
&lt;li>If $M=0$, the result is $\mathbf{e}^T \mathbf{r}$, which is a small value close to $0$.&lt;/li>
&lt;li>If $M=1$, the result is $\mathbf{e}^T \mathbf{r} + \lfloor \frac{q}{2} \rfloor$, which will be located around half the value of $q$, $\lfloor \frac{q}{2} \rfloor$.&lt;/li>
&lt;/ul>
&lt;p>If the parameters are designed so that the absolute value of the error $\mathbf{e}^T \mathbf{r}$ stays under $\frac{q}{4}$, Bob can accurately determine (decrypt) the message $M$ just by seeing whether the computed result is closer to $0$ or $\lfloor \frac{q}{2} \rfloor$. This is the beautiful mechanism by which LWE-based cryptography functions.&lt;/p>
&lt;div class="mermaid">flowchart LR
CT["Ciphertext (u, v)"] --> Dec
SK["Secret Key s"] --> Dec
subgraph Dec ["Decryption Process"]
direction TB
calc["Compute D = v - s^T * u mod q"]
check["Check if D is closer to 0 or q/2"]
end
calc --> check
Dec --> M_out["Recovered Message M"]&lt;/div>
&lt;h1 id="6-toy-example-of-lwe-cryptography-using-specific-numerical-values">6. Toy Example of LWE Cryptography Using Specific Numerical Values
&lt;/h1>&lt;p>Since simply listing formulas might make it hard to get a real sense of it, let&amp;rsquo;s actually set very small numerical parameters and follow the calculations from encryption to decryption.
(* In actual cryptographic systems, values of $n$ of 500 or more and $q$ of several thousands or more are used to ensure security)&lt;/p>
&lt;p>&lt;strong>[Parameter Settings]&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Modulus $q = 17$ (A prime number. Therefore, values take the range from $0$ to $16$)&lt;/li>
&lt;li>Dimension $n = 2$&lt;/li>
&lt;li>Number of equations $m = 4$&lt;/li>
&lt;li>Suppose we want to encrypt the message $M = 1$.&lt;/li>
&lt;li>Message shift amount: $\lfloor \frac{q}{2} \rfloor = \lfloor \frac{17}{2} \rfloor = 8$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[1. Key Generation Phase]&lt;/strong>
Bob randomly chooses the secret key $\mathbf{s}$, matrix $A$, and error vector $\mathbf{e}$.
&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>Next, calculate the public key $\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>
Calculate this modulo 17. (e.g., $66 = 17 \times 3 + 15$)
&lt;/p>
$$ A \mathbf{s} \pmod{17} = \begin{pmatrix} 15 \\ 1 \\ 11 \\ 16 \end{pmatrix} $$
&lt;p>
Add the error vector $\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>The public key is $A$ and $\mathbf{b} = (16, 0, 11, 1)^T$.&lt;/p>
&lt;p>&lt;strong>[2. Encryption Phase]&lt;/strong>
Alice encrypts the message $M = 1$.
Choose a random vector $\mathbf{r}$. Here, let $\mathbf{r} = (1, 0, 1, 0)^T$.&lt;/p>
&lt;p>Calculate $\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>Calculate $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>
Add the value $\lfloor 17/2 \rfloor = 8$ corresponding to the message $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 sends the ciphertext $(\mathbf{u}, v) = \left( \begin{pmatrix} 16 \\ 3 \end{pmatrix}, 1 \right)$ to Bob.&lt;/p>
&lt;p>&lt;strong>[3. Decryption Phase]&lt;/strong>
Bob, upon receiving the ciphertext, decrypts it using the secret key $\mathbf{s} = (3, 4)^T$.
Calculate the decryption formula: $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>Here, in the modulo 17 world, $-8$ is equal to $9$ ($-8 + 17 = 9$).
Determine whether the obtained value $D = 9$ is closer to $0$ or $8$ ($\lfloor 17/2 \rfloor$).
Since $9$ is clearly closer to $8$ than to $0$, Bob correctly restored $M = 1$!&lt;/p>
&lt;p>Why did it become $9$? Let&amp;rsquo;s recall the previous proof.
The error part is $\mathbf{e}^T \mathbf{r} = (1, -1, 0, 2) (1, 0, 1, 0)^T = 1 \times 1 + 0 \times 1 = 1$.
Therefore, the calculation result is $\mathbf{e}^T \mathbf{r} + M \cdot 8 = 1 + 8 = 9$, confirming that the theoretically expected value was calculated.&lt;/p>
&lt;h1 id="7-evolution-towards-practical-application-ring-lwe-and-module-lwe">7. Evolution Towards Practical Application: Ring-LWE and Module-LWE
&lt;/h1>&lt;p>The Standard LWE problem explained so far has an extremely strong security proof, but it has a fatal flaw in practical use. That is, &amp;ldquo;the size of the keys becomes huge&amp;rdquo; and &amp;ldquo;the computational cost is high.&amp;rdquo;&lt;/p>
&lt;p>In Standard LWE, the public key includes a huge matrix $A \in \mathbb{Z}_q^{m \times n}$. When the parameter $n$ goes up to hundreds or thousands, the size of this matrix reaches several megabytes, making it too heavy to transmit and receive every time over Internet communication protocols (such as TLS). Also, multiplying a matrix and a vector requires a computational complexity of $\mathcal{O}(n^2)$.&lt;/p>
&lt;p>To solve this problem, &amp;ldquo;Ring-LWE (RLWE)&amp;rdquo; and &amp;ldquo;Module-LWE (MLWE)&amp;rdquo; were introduced, incorporating an algebraic structure called polynomial rings into the lattice.&lt;/p>
&lt;h2 id="71-intuition-of-ring-lwe">7.1 Intuition of Ring-LWE
&lt;/h2>&lt;p>In Ring-LWE, vectors and matrices are replaced with elements (polynomials) over a polynomial ring $\mathcal{R}_q = \mathbb{Z}_q[X]/(X^n + 1)$. (Here, $n$ is chosen as a power of 2).&lt;/p>
&lt;p>Whereas the public key of Standard LWE was a matrix $A$, Ring-LWE uses a single polynomial $a(x)$. The secret key $s(x)$ and the error $e(x)$ also become polynomials.
The equation looks like this:
&lt;/p>
$$ b(x) = a(x) \cdot s(x) + e(x) \pmod q $$
&lt;p>Since this is polynomial multiplication, by using the &amp;ldquo;Number Theoretic Transform (NTT),&amp;rdquo; which is similar to the Fast Fourier Transform (FFT), the computational complexity can be dramatically reduced to $\mathcal{O}(n \log n)$. Furthermore, because the size of the public key shrinks from a matrix to a single polynomial, the data size is reduced to $\mathcal{O}(n)$. This brings an overwhelming advantage in communication bandwidth.&lt;/p>
&lt;p>Mathematically speaking, Ring-LWE reduces to a problem on a lattice with a special symmetry called an &amp;ldquo;Ideal Lattice&amp;rdquo; rather than a general lattice.&lt;/p>
&lt;h2 id="72-module-lwe-and-nist-standardization-kyber--ml-kem">7.2 Module-LWE and NIST Standardization (Kyber / ML-KEM)
&lt;/h2>&lt;p>While Ring-LWE is efficient, there was some concern that the special algebraic structure of ideal lattices might become a clue for future attacks. Therefore, &amp;ldquo;Module-LWE (MLWE)&amp;rdquo; was created to take the &amp;ldquo;best of both worlds&amp;rdquo;: the conservative security of Standard LWE and the efficiency of Ring-LWE.&lt;/p>
&lt;p>Module-LWE considers small matrices and vectors whose elements are polynomials. In other words, it handles modules over a ring.
Currently, &amp;ldquo;CRYSTALS-Kyber&amp;rdquo; (standardized name: ML-KEM), which NIST selected as the standard for PQC key encapsulation mechanisms (KEM), is built precisely on the difficulty of this Module-LWE problem.&lt;/p>
&lt;h1 id="8-why-is-it-secure-against-quantum-computers">8. Why is it Secure Against Quantum Computers?
&lt;/h1>&lt;p>Finally, let&amp;rsquo;s touch upon the core issue: &amp;ldquo;Why is lattice-based cryptography considered unbreakable even when using quantum computers?&amp;rdquo;&lt;/p>
&lt;p>Shor&amp;rsquo;s algorithm, which allows quantum computers to break RSA cryptography and Elliptic Curve Cryptography, is essentially an algorithm that solves the &amp;ldquo;Hidden Subgroup Problem (HSP).&amp;rdquo; The mathematical structure (finite abelian groups) behind RSA and ECC has periodicity, and by using a specific operation of quantum algorithms called the Quantum Fourier Transform (QFT), this period (hidden subgroup) can be extracted all at once.&lt;/p>
&lt;p>However, lattice problems are fundamentally different. Although lattices also have periodicity, what is required in SVP and CVP is a geometric, non-linear property such as &amp;ldquo;shortest distance&amp;rdquo; or &amp;ldquo;removal of noise.&amp;rdquo; Even if a &amp;ldquo;Quantum Fourier Transform over an abelian group&amp;rdquo; like Shor&amp;rsquo;s algorithm is applied directly, useful information that would be the answer to the lattice problem cannot be efficiently extracted. To date, no quantum algorithm that can solve SVP or LWE in polynomial time has been discovered, and it is widely believed that even with the parallel computing power of quantum computers, the only effective means is near-brute-force search (about the level of square root speedup by Grover&amp;rsquo;s algorithm).&lt;/p>
&lt;h1 id="9-conclusion">9. Conclusion
&lt;/h1>&lt;p>In this article, we explained the mathematical intuition of lattice-based cryptography in detail, starting from the geometric definition of a lattice, to the formulation of the LWE problem, and the construction of a public-key cryptosystem.&lt;/p>
&lt;ol>
&lt;li>A &lt;strong>Lattice&lt;/strong> is a discrete space represented by integer-coefficient linear combinations of basis vectors, and finding a &amp;ldquo;good basis&amp;rdquo; close to orthogonal (SVP) becomes difficult in high dimensions.&lt;/li>
&lt;li>The &lt;strong>LWE (Learning With Errors) problem&lt;/strong> is the problem of solving a system of linear equations with noise, and since it is tied to the difficulty of worst-case problems on lattices, it provides a powerful security foundation.&lt;/li>
&lt;li>By using the LWE problem, encryption and decryption (&lt;strong>Regev&amp;rsquo;s Cryptosystem&lt;/strong>) are realized through an ingenious mechanism of intentionally adding and removing noise.&lt;/li>
&lt;li>In real-world protocols, &lt;strong>Ring-LWE&lt;/strong> and &lt;strong>Module-LWE&lt;/strong> using polynomial rings are adopted to improve communication efficiency and computation speed, serving as the foundation for the NIST-standard &lt;strong>ML-KEM&lt;/strong>.&lt;/li>
&lt;/ol>
&lt;p>As the unprecedented computational paradigm shift of quantum computers approaches, it is quite romantic that &amp;ldquo;lattice-based cryptography,&amp;rdquo; born from the depths of classical linear algebra and number theory, will bear the foundation of future internet security. The math that forms the foundation of lattice-based cryptography is by no means too esoteric, and anyone with a basic knowledge of linear algebra and probability can fully understand its beautiful structure. We hope this article has helped you understand lattice-based cryptography, the core of PQC.&lt;/p></description></item><item><title>How Zero-Knowledge Proofs (ZKP) Work and Their Latest Applications in Web3 and Security</title><link>http://kenji.blog/en/p/zero-knowledge-proofs-zkp-web3-security/</link><pubDate>Fri, 11 Sep 2026 19:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/zero-knowledge-proofs-zkp-web3-security/</guid><description>&lt;img src="http://kenji.blog/p/zero-knowledge-proofs-zkp-web3-security/img/eyecatch.jpg" alt="Featured image of post How Zero-Knowledge Proofs (ZKP) Work and Their Latest Applications in Web3 and Security" />&lt;h2 id="introduction">Introduction
&lt;/h2>&lt;p>In modern digital society, data privacy and scalability have become two of the most critical challenges. As the risks of personal information leaks and unauthorized use increase, there is a strong demand for technology that allows you to &amp;ldquo;prove that you have certain information without revealing the information itself to the other party.&amp;rdquo; This is realized by &lt;strong>Zero-Knowledge Proofs (ZKP)&lt;/strong>.&lt;/p>
&lt;p>Zero-Knowledge Proofs is a concept in cryptography first proposed in the 1980s by Shafi Goldwasser, Silvio Micali, and Charles Rackoff, but for a long time, it remained primarily a theoretical research topic. However, with the rise of blockchain technology and Web3, the situation completely changed. ZKP has suddenly been thrust into the spotlight as the &amp;ldquo;magic wand&amp;rdquo; that simultaneously solves the scalability problems (limits of processing capacity) and privacy problems (the fact that all transactions are public) faced by public blockchains like Ethereum.&lt;/p>
&lt;p>In this article, we will provide a highly detailed and technically deep explanation, ranging from the basic concepts of Zero-Knowledge Proofs to the profound mathematical and cryptographic mechanisms of the currently mainstream &lt;strong>zk-SNARKs&lt;/strong> and &lt;strong>zk-STARKs&lt;/strong>, and finally to the latest application examples in Web3 and security, such as ZK-Rollups and Decentralized Identity (DID).&lt;/p>
&lt;hr>
&lt;h2 id="what-is-a-zero-knowledge-proof-zkp">What is a Zero-Knowledge Proof (ZKP)?
&lt;/h2>&lt;p>A Zero-Knowledge Proof (ZKP) refers to a protocol in which a prover can prove to a verifier that a certain proposition is true, &amp;ldquo;without transmitting any information other than the fact that the proposition is true.&amp;rdquo;&lt;/p>
&lt;h3 id="the-3-requirements-for-zkp">The 3 Requirements for ZKP
&lt;/h3>&lt;p>To be established as a ZKP, the following three properties must be strictly satisfied:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Completeness&lt;/strong>
If the proposition is true, and both the prover and the verifier follow the protocol correctly, the verifier must accept the proof with an overwhelming probability.&lt;/li>
&lt;li>&lt;strong>Soundness&lt;/strong>
If the proposition is false, no matter how computationally powerful and malicious the prover is, it is impossible (except for a negligibly small probability) to deceive the verifier into accepting the proof.&lt;/li>
&lt;li>&lt;strong>Zero-Knowledge&lt;/strong>
If the proposition is true, the verifier cannot obtain any information from the proof process other than the fact that &amp;ldquo;the proposition is true.&amp;rdquo; From the verifier&amp;rsquo;s perspective, this is proven by the mathematical definition that it is possible to simulate the proof process (a simulator exists).&lt;/li>
&lt;/ol>
&lt;h3 id="interactive-and-non-interactive-proofs">Interactive and Non-Interactive Proofs
&lt;/h3>&lt;p>There are two types of ZKPs: &lt;strong>Interactive Proofs&lt;/strong>, where the prover and verifier communicate multiple times, and &lt;strong>Non-Interactive Proofs&lt;/strong>, where the prover sends the proof data only once.&lt;/p>
&lt;h4 id="interactive-zkp">Interactive ZKP
&lt;/h4>&lt;p>Early ZKPs were designed as interactive protocols. The famous &amp;ldquo;Ali Baba&amp;rsquo;s Cave&amp;rdquo; allegory falls under this category. The general flow of the protocol is as follows:&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Prover as "Prover"
participant Verifier as "Verifier"
Note over Prover, Verifier: "Basic Flow of the Interactive Proof Protocol"
Prover->>Verifier: "1. Send Commitment"
Verifier->>Prover: "2. Send Random Challenge"
Prover->>Verifier: "3. Calculate and Send Response"
Note over Verifier: "Verify the Response"
Verifier-->>Prover: "4. Accept / Reject"
Note over Prover, Verifier: "* Repeat this dozens of times to increase certainty"&lt;/div>
&lt;p>This method is powerful, but the verifier must be online, making it inconvenient to apply to asynchronous distributed systems like blockchains. In a blockchain, anyone must be able to verify past proofs at any time.&lt;/p>
&lt;h4 id="fiat-shamir-heuristic-and-non-interactivity">Fiat-Shamir Heuristic and Non-Interactivity
&lt;/h4>&lt;p>A breakthrough technique for converting interactive proofs into Non-Interactive Zero-Knowledge Proofs (NIZK) is the &lt;strong>Fiat-Shamir Heuristic&lt;/strong>.&lt;/p>
&lt;p>Instead of the &amp;ldquo;random challenge&amp;rdquo; sent by the verifier, the prover self-generates a &amp;ldquo;pseudo-random challenge&amp;rdquo; using their own commitment and the hash value of public information. Assuming that a cryptographic hash function (such as SHA-256 or Keccak) functions as a random oracle, the prover cannot predict or manipulate the challenge in advance, allowing the proof to be completed with a single message transmission while maintaining the same level of security as an interactive proof.&lt;/p>
&lt;hr>
&lt;h2 id="technical-details-of-zk-snarks">Technical Details of zk-SNARKs
&lt;/h2>&lt;p>Currently, the most widely used ZKP is &lt;strong>zk-SNARKs&lt;/strong> (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge). As the name suggests, it is an Argument of Knowledge that has zero-knowledge properties (zk), features very small proof sizes and fast verification (Succinct), and is Non-Interactive.&lt;/p>
&lt;p>The foundation of zk-SNARKs is advanced algebraic geometry and cryptography. It converts the execution and computation of programs into the verification of specific polynomial equations.&lt;/p>
&lt;h3 id="1-conversion-to-arithmetic-circuits-and-r1cs-rank-1-constraint-system">1. Conversion to Arithmetic Circuits and R1CS (Rank-1 Constraint System)
&lt;/h3>&lt;p>First, any computation you want to prove (such as an algorithm or smart contract logic) is converted into an &lt;strong>Arithmetic Circuit&lt;/strong> consisting of addition and multiplication gates.&lt;/p>
&lt;p>Next, this arithmetic circuit is converted into a set of matrix equations called &lt;strong>R1CS (Rank-1 Constraint System)&lt;/strong>. R1CS is the problem of finding matrices $A, B, C$ that satisfy the following constraint for a variable vector $x$:&lt;/p>
$$ (A \cdot x) \circ (B \cdot x) = C \cdot x $$
&lt;p>Here, $\circ$ represents the Hadamard product (element-wise product). This constraint ensures that all logic gates (especially multiplication gates) in the circuit are calculated correctly.&lt;/p>
&lt;h3 id="2-conversion-to-qap-quadratic-arithmetic-program">2. Conversion to QAP (Quadratic Arithmetic Program)
&lt;/h3>&lt;p>Since there are countless R1CS matrix constraints, verifying them individually is highly inefficient. Therefore, Lagrange interpolation is used to compress these constraints into a single polynomial equation. This is the &lt;strong>QAP (Quadratic Arithmetic Program)&lt;/strong>.&lt;/p>
&lt;p>Through the conversion to QAP, the problem to be proven is reduced to the question: &amp;ldquo;Is a specific polynomial $P(x)$ divisible by another known polynomial $Z(x)$?&amp;rdquo;&lt;/p>
$$ P(x) = L(x) \cdot R(x) - O(x) $$
&lt;p>Here, $L(x), R(x), O(x)$ are combinations of polynomials corresponding to each row of matrices $A, B, C$, respectively. If the prover knows the correct solution (Witness), the value becomes 0 at each root (evaluation point) of $P(x)$, so $P(x)$ will have the target polynomial $Z(x)$ as a factor. In other words, there exists a polynomial $H(x)$ such that the following equation holds:&lt;/p>
$$ P(x) = H(x) \cdot Z(x) $$
&lt;p>The verifier only needs to check whether this equation $P(s) = H(s) \cdot Z(s)$ holds at a certain random secret point $s$ to instantly verify that the entire computation was performed correctly. This is the secret of its &amp;ldquo;Succinctness.&amp;rdquo;&lt;/p>
&lt;h3 id="3-elliptic-curve-cryptography-and-bilinear-pairings">3. Elliptic Curve Cryptography and Bilinear Pairings
&lt;/h3>&lt;p>However, if the verifier knows the secret point $s$, it would be possible for the prover to fabricate a fake polynomial to satisfy the equation (a collapse of soundness). Therefore, it is necessary to perform computations while keeping $s$ encrypted (using homomorphic encryption) so that no one knows it.&lt;/p>
&lt;p>This is achieved using &lt;strong>Bilinear Pairings&lt;/strong> on elliptic curves.
A pairing $e$ is a special function that can calculate a value equivalent to the encryption of the product of two encrypted values.&lt;/p>
$$ e(g_1^a, g_2^b) = e(g_1, g_2)^{ab} $$
&lt;p>Even without knowing $s$ itself, the prover calculates the encrypted values of the polynomials $P(s)$ and $H(s)$ using encrypted values of powers of $s$ (this is called the CRS: Common Reference String). The verifier uses the pairing function to verify whether the relationship $P(s) = H(s) \cdot Z(s)$ holds while the values remain encrypted.&lt;/p>
&lt;h3 id="4-trusted-setup">4. Trusted Setup
&lt;/h3>&lt;p>The biggest weakness of zk-SNARKs (especially early ones like Groth16) is that they require a process to generate the secret point $s$, known as a &lt;strong>Trusted Setup&lt;/strong>. If the creator of $s$ retains the value without destroying it, they can generate arbitrary fake proofs (the Toxic Waste problem).&lt;/p>
&lt;p>To prevent this, a ritual called a &amp;ldquo;Ceremony&amp;rdquo; is conducted using Multi-Party Computation (MPC). Numerous participants cooperate to provide randomness, and as long as at least one participant honestly destroys their random value, the security of the entire system is maintained. However, research to eliminate this dependency has been ongoing for many years.&lt;/p>
&lt;hr>
&lt;h2 id="technical-details-of-zk-starks">Technical Details of zk-STARKs
&lt;/h2>&lt;p>&lt;strong>zk-STARKs&lt;/strong> (Zero-Knowledge Scalable Transparent Argument of Knowledge) emerged as an answer to the reliance on trusted setups and the risk of elliptic curve cryptography being decrypted by quantum computers.&lt;/p>
&lt;p>Developed by Eli Ben-Sasson and others, STARKs feature no need for a trusted setup, living up to the name &amp;ldquo;Transparent,&amp;rdquo; and maintain efficient proof sizes and verification times even as the amount of computation increases, living up to the name &amp;ldquo;Scalable.&amp;rdquo;&lt;/p>
&lt;h3 id="1-polynomial-commitments-and-the-fri-protocol">1. Polynomial Commitments and the FRI Protocol
&lt;/h3>&lt;p>zk-STARKs base their security entirely on &lt;strong>hash functions&lt;/strong>, rather than elliptic curve cryptography. Therefore, they have the properties of Post-Quantum Cryptography.&lt;/p>
&lt;p>Computation verification is performed by utilizing the properties of one-dimensional or multi-dimensional polynomials after being converted into a format called AIR (Algebraic Intermediate Representation). The core of STARKs lies in the &lt;strong>FRI (Fast Reed-Solomon Interactive Oracle Proof of Proximity)&lt;/strong> protocol.&lt;/p>
&lt;p>The FRI protocol is a technique for verifying &amp;ldquo;whether a certain function is sufficiently close to a polynomial of a specific degree (Proximity).&amp;rdquo; The prover commits the polynomial&amp;rsquo;s values as leaves of a Merkle Tree (Polynomial Commitment).&lt;/p>
&lt;div class="mermaid">graph TD
Root["Merkle Root (Commitment)"] --> Node0["Node 0"]
Root --> Node1["Node 1"]
Node0 --> Leaf0["P(x_0)"]
Node0 --> Leaf1["P(x_1)"]
Node1 --> Leaf2["P(x_2)"]
Node1 --> Leaf3["P(x_3)"]&lt;/div>
&lt;p>The verifier requests the disclosure of several random points and uses Merkle proofs to confirm that they are included in the commitment. By repeating this recursively, it guarantees with overwhelming probability that the original polynomial actually has a low degree.&lt;/p>
&lt;h3 id="comparison-of-zk-snarks-and-zk-starks">Comparison of zk-SNARKs and zk-STARKs
&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Feature&lt;/th>
&lt;th style="text-align:left">zk-SNARKs&lt;/th>
&lt;th style="text-align:left">zk-STARKs&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Cryptographic Assumptions&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Elliptic curves, Pairings&lt;/td>
&lt;td style="text-align:left">Collision-resistant hash functions&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Trusted Setup&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Required (Universal for Plonk, etc.)&lt;/td>
&lt;td style="text-align:left">Not required (Transparent)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Quantum Resistance&lt;/strong>&lt;/td>
&lt;td style="text-align:left">No&lt;/td>
&lt;td style="text-align:left">Yes&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Proof Size&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Very small (~200 Bytes)&lt;/td>
&lt;td style="text-align:left">Somewhat large (Tens of KB)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Proof Generation Computational Cost&lt;/strong>&lt;/td>
&lt;td style="text-align:left">High&lt;/td>
&lt;td style="text-align:left">Relatively lower than SNARKs&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Verification Cost (Gas Fee)&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Very low (Constant)&lt;/td>
&lt;td style="text-align:left">Low (Increases logarithmically)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>In recent years, SNARKs that &amp;ldquo;do not require a trusted setup, or only require it once&amp;rdquo; like Plonk and Halo2 have appeared, and the boundary between SNARKs and STARKs is gradually blurring, but the fundamental difference in mathematical approaches remains important.&lt;/p>
&lt;hr>
&lt;h2 id="latest-applications-of-zero-knowledge-proofs-in-web3-and-security">Latest Applications of Zero-Knowledge Proofs in Web3 and Security
&lt;/h2>&lt;p>Having transitioned from theory to practice, ZKPs are now sparking a revolution at the forefront of Web3 and cybersecurity.&lt;/p>
&lt;h3 id="1-ultimate-scaling-of-ethereum-with-zk-rollups">1. Ultimate Scaling of Ethereum with ZK-Rollups
&lt;/h3>&lt;p>L1 (Layer 1) blockchains like Ethereum have significant constraints on scalability (the trilemma) due to their emphasis on decentralization and security. The definitive L2 (Layer 2) solution to solve this is &lt;strong>ZK-Rollups&lt;/strong>.&lt;/p>
&lt;p>In a ZK-Rollup, thousands of transactions are executed and processed off-chain (L2), generating a &amp;ldquo;single ZKP (Validity Proof)&amp;rdquo; indicating that they were all executed correctly. The smart contract on the L1 chain only needs to verify this proof.&lt;/p>
&lt;div class="mermaid">flowchart LR
Users["Users (Tx Submission)"] --> Sequencer["Sequencer (Tx Collection &amp; Execution)"]
Sequencer --> Prover["Prover (ZKP Generation)"]
Sequencer --> L1Contract["L1 Smart Contract (Tx Data Publication)"]
Prover --> L1Contract["ZKP (Proof) Submission"]
L1Contract --> Verify["Verification &amp; State Update"]&lt;/div>
&lt;p>The biggest advantage of ZK-Rollups is that, unlike Optimistic Rollups (such as Arbitrum and Optimism), they do not require a challenge period (typically 7 days) for Fraud Proofs. Because correctness is cryptographically guaranteed, fund withdrawals to L1 (Finality) are completed the moment the proof is verified. Currently, projects like zkSync, Starknet, Scroll, and Polygon zkEVM are engaged in fierce development competition, and the realization of &lt;strong>zkEVMs&lt;/strong>, which are compatible with the EVM (Ethereum Virtual Machine), is driving rapid ecosystem growth.&lt;/p>
&lt;h3 id="2-privacy-preserving-identity-zkp-for-identity">2. Privacy-Preserving Identity (ZKP for Identity)
&lt;/h3>&lt;p>The nature of personal authentication in the digital world will also be fundamentally changed by ZKPs.
For example, in response to the question, &amp;ldquo;Are you 18 or older?&amp;rdquo;, conventional systems required presenting a driver&amp;rsquo;s license or passport, handing over unnecessary personal information like name and address to the other party.&lt;/p>
&lt;p>By using ZKPs, based on a digital certificate (Verifiable Credential) issued by a public institution, it becomes possible to &lt;strong>mathematically prove only the fact&lt;/strong> that &amp;ldquo;calculated from my date of birth, I am 18 or older on the current date.&amp;rdquo; The verifier only needs to verify the certificate&amp;rsquo;s signature and the ZKP, without knowing the user&amp;rsquo;s date of birth or identity.&lt;/p>
&lt;p>Projects for Proof of Personhood like Worldcoin also incorporate a mechanism to prove only that one is a &amp;ldquo;unique human&amp;rdquo; using ZKPs, rather than storing and sharing iris data directly.&lt;/p>
&lt;h3 id="3-confidential-smart-contracts-and-enterprise-use">3. Confidential Smart Contracts and Enterprise Use
&lt;/h3>&lt;p>The property of public blockchains that &amp;ldquo;all data is public&amp;rdquo; has been a major barrier for companies handling confidential transactions and supply chain information on the blockchain.&lt;/p>
&lt;p>By using ZKP technology (such as privacy-focused networks like Aleo and Aztec), the input values, output values of transactions, and even the smart contract logic executed can be kept encrypted, while only the validity of state updates is etched onto the public chain. This makes it possible to prevent front-running (MEV) in DeFi (Decentralized Finance) and to build confidential consortium networks among enterprises, all while enjoying the high security of public chains.&lt;/p>
&lt;hr>
&lt;h2 id="future-challenges-and-prospects-for-zkp">Future Challenges and Prospects for ZKP
&lt;/h2>&lt;p>While ZKPs are undoubtedly a next-generation foundational technology, several challenges remain.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Proof Generation Computational Costs and Hardware Acceleration&lt;/strong>
Generating a ZKP requires massive polynomial operations, FFT (Fast Fourier Transform), and MSM (Multi-Scalar Multiplication). Currently, research into dedicated hardware (FPGAs and ASICs) to accelerate this proof generation, known as &lt;strong>ZKP Mining&lt;/strong> (Prover Networks), is rapidly advancing.&lt;/li>
&lt;li>&lt;strong>Standardization and Improvement of Developer Experience (DX)&lt;/strong>
Dedicated languages for writing ZKP circuits, such as Circom, Cairo, Noir, and Leo, are proliferating. A standard unifying these and the maturation of compilers that automatically generate ZKP circuits from existing languages like Rust and C++ will be key to general software engineers adopting ZKPs.&lt;/li>
&lt;/ol>
&lt;h2 id="conclusion">Conclusion
&lt;/h2>&lt;p>Zero-Knowledge Proofs (ZKP) have evolved from merely a &amp;ldquo;technology to enhance cryptocurrency anonymity&amp;rdquo; to a &amp;ldquo;general-purpose technology redefining trust across the internet.&amp;rdquo; Small proofs calculated deep within mathematics and cryptography will infinitely scale blockchain capabilities and act as a strong shield protecting our privacy.&lt;/p>
&lt;p>Towards true mass adoption of Web3 and the construction of a secure and private next-generation internet, Zero-Knowledge Proofs will continue to function as the most crucial piece. We must keep a close eye on the future evolution of ZKP technology.&lt;/p>
&lt;hr>
&lt;p>&lt;em>References and Related Links&lt;/em>&lt;/p>
&lt;ul>
&lt;li>Groth, J. (2016). &amp;ldquo;On the Size of Pairing-based Non-interactive Arguments&amp;rdquo;&lt;/li>
&lt;li>Ben-Sasson, E., et al. (2018). &amp;ldquo;Scalable, transparent, and post-quantum secure computational integrity&amp;rdquo;&lt;/li>
&lt;li>Vitalik Buterin&amp;rsquo;s blog on zk-SNARKs and zk-STARKs&lt;/li>
&lt;/ul></description></item><item><title>The Riemann Hypothesis and the Distribution of Prime Numbers: A Deep Connection with Modern Cryptography</title><link>http://kenji.blog/en/p/riemann-hypothesis-prime-distribution-cryptography/</link><pubDate>Fri, 11 Sep 2026 16:00:00 +0900</pubDate><guid>http://kenji.blog/en/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 The Riemann Hypothesis and the Distribution of Prime Numbers: A Deep Connection with Modern Cryptography" />&lt;h1 id="1-introduction-the-mystery-of-the-universe-in-prime-numbers-and-the-riemann-hypothesis">1. Introduction: The Mystery of the Universe in Prime Numbers and the Riemann Hypothesis
&lt;/h1>&lt;p>&amp;ldquo;Prime Numbers&amp;rdquo; are natural numbers divisible only by 1 and themselves, often called the &amp;ldquo;atoms&amp;rdquo; in the world of mathematics. The sequence of 2, 3, 5, 7, 11, 13&amp;hellip; appears at first glance to be unordered and random. Ever since the ancient Greek mathematician Euclid proved that &amp;ldquo;there are infinitely many prime numbers,&amp;rdquo; countless mathematicians have challenged themselves to unravel the regularity hidden in the arrangement of these primes.&lt;/p>
&lt;p>The closest anyone has come to the mystery of prime numbers is the &lt;strong>&amp;ldquo;Riemann Hypothesis&amp;rdquo;&lt;/strong> proposed by the German mathematician Bernhard Riemann in 1859. The Riemann Hypothesis is one of the most important and unsolved difficult problems in modern mathematics, and carries a $1 million prize as one of the Millennium Prize Problems designated by the Clay Mathematics Institute.&lt;/p>
&lt;p>At first glance, a difficult problem in pure mathematics regarding the distribution of prime numbers may seem unrelated to our daily lives. However, internet security, which supports the infrastructure of modern society, especially &lt;strong>modern cryptographic technologies such as RSA cryptography and Elliptic Curve Cryptography (ECC)&lt;/strong>, relies deeply on the properties of gigantic prime numbers.&lt;/p>
&lt;p>In this article, we will embark on a mathematical journey from the distribution of prime numbers to the Prime Number Theorem, the Riemann Zeta function, and the core of the Riemann Hypothesis. We will provide an extremely detailed and deep explanation of how it is connected to modern cryptography and what would happen to the world if the Riemann Hypothesis were proven.&lt;/p>
&lt;hr>
&lt;h1 id="2-the-prime-number-theorem-and-the-distribution-of-primes-gausss-discovery">2. The Prime Number Theorem and the Distribution of Primes: Gauss&amp;rsquo;s Discovery
&lt;/h1>&lt;p>To understand how prime numbers are distributed, mathematicians considered the &lt;strong>Prime-counting function&lt;/strong> $\pi(x)$, which represents &amp;ldquo;how many prime numbers exist up to a certain number $x$.&amp;rdquo;&lt;/p>
&lt;p>For example:&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>The 15-year-old genius mathematician Carl Friedrich Gauss calculated vast tables of prime numbers and discovered that the frequency of appearance of prime numbers decreases in inverse proportion to the natural logarithm $\ln x$. That is, he conjectured that the probability of finding a prime number near a certain number $x$ is approximately $\frac{1}{\ln x}$.&lt;/p>
&lt;p>Expressing this using integration gives the &lt;strong>Logarithmic integral&lt;/strong> $\text{Li}(x)$:&lt;/p>
$$ \text{Li}(x) = \int_{2}^{x} \frac{dt}{\ln t} $$
&lt;p>Gauss&amp;rsquo;s conjecture was later independently proven in 1896 by Jacques Hadamard and Charles Jean de la Vallée Poussin, and was established as the &lt;strong>Prime Number Theorem (PNT)&lt;/strong>.&lt;/p>
$$ \lim_{x \to \infty} \frac{\pi(x)}{\text{Li}(x)} = 1 $$
&lt;p>Or, it can be approximately expressed as follows:&lt;/p>
$$ \pi(x) \sim \frac{x}{\ln x} $$
&lt;p>Through this theorem, it became clear that prime numbers have a very smooth and predictable distribution when viewed macroscopically. However, microscopically, there is always an &amp;ldquo;error&amp;rdquo; or &amp;ldquo;fluctuation&amp;rdquo; between $\pi(x)$ and $\text{Li}(x)$. The true nature of this fluctuation is exactly the greatest mystery that the Riemann Hypothesis attempts to unravel.&lt;/p>
&lt;hr>
&lt;h1 id="3-the-riemann-zeta-function-and-the-euler-product">3. The Riemann Zeta Function and the Euler Product
&lt;/h1>&lt;p>The most powerful weapon for analyzing the distribution of prime numbers is the &lt;strong>Riemann Zeta Function&lt;/strong>. Originally, it was an infinite series defined by Leonhard Euler for real numbers $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>One of Euler&amp;rsquo;s greatest achievements was proving that this infinite series can be expressed as an infinite product over all prime numbers $p$. This is the &lt;strong>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>An intuitive understanding of the proof is that if each term on the right side is expanded as a geometric series and multiplied together, by the Fundamental Theorem of Arithmetic (every natural number can be uniquely represented as a product of primes), the sum of the reciprocals of natural numbers on the left side is perfectly reconstructed.&lt;/p>
&lt;p>&lt;strong>This single mathematical formula became the bridge connecting analysis (infinite series, continuous functions) and number theory (prime numbers, discrete numbers).&lt;/strong> Investigating the Zeta function is synonymous with investigating the distribution of prime numbers.&lt;/p>
&lt;hr>
&lt;h1 id="4-analytic-continuation-and-extension-to-the-complex-plane">4. Analytic Continuation and Extension to the Complex Plane
&lt;/h1>&lt;p>Riemann&amp;rsquo;s genius lay in extending the variable $s$ of $\zeta(s)$, which Euler had considered only for real numbers, to &lt;strong>complex numbers $s = \sigma + it$ (where $\sigma$ is the real part and $t$ is the imaginary part)&lt;/strong>.&lt;/p>
&lt;p>The original infinite series only converges for $\sigma > 1$, but using a technique called &amp;ldquo;Analytic Continuation,&amp;rdquo; Riemann extended the definition so that $\zeta(s)$ is meaningful over the entire complex plane, excluding the pole at $s = 1$.&lt;/p>
&lt;p>He further derived a beautiful functional equation satisfied by the Zeta function:&lt;/p>
$$ \zeta(s) = 2^s \pi^{s-1} \sin\left(\frac{\pi s}{2}\right) \Gamma(1-s) \zeta(1-s) $$
&lt;p>Here, $\Gamma(x)$ is the Gamma function. Through this equation, the properties of the left half-plane can be known from the properties of the right half-plane.&lt;/p>
&lt;h3 id="zeros-of-the-zeta-function">Zeros of the Zeta Function
&lt;/h3>&lt;p>Complex numbers $s$ for which the value of the Zeta function becomes 0 are called &amp;ldquo;zeros&amp;rdquo;.
From the functional equation, when $s$ is a negative even integer ($-2, -4, -6, \dots$), $\sin(\pi s / 2)$ becomes 0, resulting in $\zeta(s) = 0$. These are called &lt;strong>Trivial zeros&lt;/strong>.&lt;/p>
&lt;p>However, what is important in the distribution of prime numbers are the other zeros, namely the &lt;strong>Non-trivial zeros&lt;/strong> that exist in the &amp;ldquo;Critical strip&amp;rdquo; where $0 \le \sigma \le 1$.&lt;/p>
&lt;hr>
&lt;h1 id="5-the-core-of-the-riemann-hypothesis-and-the-explicit-formula">5. The Core of the Riemann Hypothesis and the Explicit Formula
&lt;/h1>&lt;p>Riemann calculated a small number of zeros and formulated a remarkable conjecture. This is the &lt;strong>Riemann Hypothesis&lt;/strong>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Riemann Hypothesis&lt;/strong>
All non-trivial zeros of the Riemann Zeta function $\zeta(s)$ lie on the line where the real part is $1/2$ ($\text{Re}(s) = 1/2$).&lt;/p>
&lt;/blockquote>
&lt;p>This line with a real part of $1/2$ is called the &amp;ldquo;Critical line&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">graph TD
A["Riemann Zeta function ζ(s)"] --> B["Extension to the complex plane by analytic continuation"]
B --> C["Trivial zeros (s = -2, -4, -6 ...)"]
B --> D["Non-trivial zeros (0 &lt;= Re(s) &lt;= 1)"]
D --> E["Riemann Hypothesis"]
E --> F["All non-trivial zeros lie on Re(s) = 1/2"]
F --> G["To the proof of the limit of the error term in the prime distribution"]&lt;/div>
&lt;p>Why is the Riemann Hypothesis so important? It is because the zeros of the Zeta function &lt;strong>completely&lt;/strong> determine the distribution of prime numbers.&lt;/p>
&lt;p>Riemann and later the mathematician von Mangoldt derived an &amp;ldquo;Explicit formula&amp;rdquo; that accurately describes the distribution of primes. Using the Chebyshev function $\psi(x)$, it is expressed as follows:&lt;/p>
$$ \psi(x) = x - \sum_{\rho} \frac{x^\rho}{\rho} - \ln(2\pi) - \frac{1}{2}\ln(1 - x^{-2}) $$
&lt;p>Here, $\rho$ runs over all the non-trivial zeros of the Zeta function.
The main term is $x$ (which corresponds to the Prime Number Theorem), and by adding and subtracting wave-like terms depending on the zeros $\rho$, the precise step-like distribution of primes is restored. The non-trivial zeros can be said to represent the &amp;ldquo;frequencies (waves)&amp;rdquo; of the distribution of primes.&lt;/p>
&lt;p>If the Riemann Hypothesis is true, and the real part of all non-trivial zeros $\rho$ is exactly $1/2$, the error term of the Prime Number Theorem would fall within the theoretically smallest possible range.&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>In other words, &lt;strong>if the Riemann Hypothesis is true, it proves that prime numbers are distributed as &amp;ldquo;regularly and beautifully&amp;rdquo; as we can possibly imagine.&lt;/strong>&lt;/p>
&lt;hr>
&lt;h1 id="6-the-inseparable-relationship-between-modern-cryptography-and-prime-numbers">6. The Inseparable Relationship Between Modern Cryptography and Prime Numbers
&lt;/h1>&lt;p>So far, we have been in the realm of profound pure mathematics, but this property of prime numbers fundamentally supports modern digital society. A representative example of this is public-key cryptography, such as &lt;strong>RSA cryptography&lt;/strong>.&lt;/p>
&lt;p>The security of all communications, such as credit card payments on the internet, password transmissions, and electronic signatures in blockchains, relies on &amp;ldquo;prime numbers.&amp;rdquo;&lt;/p>
&lt;h3 id="how-rsa-cryptography-works">How RSA Cryptography Works
&lt;/h3>&lt;p>The security of RSA cryptography is based on the mathematical fact that &amp;ldquo;factorizing a composite number with a large number of digits is extremely difficult&amp;rdquo; (the integer factorization problem).&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Key Generation&lt;/strong>:
Randomly select two gigantic prime numbers $p$ and $q$ (for example, 2048 bits each).
Multiply them to calculate $N = p \times q$. This $N$ becomes a part of the public key.
Using Euler&amp;rsquo;s totient function $\phi(N) = (p-1)(q-1)$, generate a private key $d$:&lt;/p>
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Encryption and Decryption&lt;/strong>:
The plaintext $M$ is converted into ciphertext $C$ using the public keys $e, N$:
&lt;/p>
$$ C \equiv M^e \pmod{N} $$
&lt;p>
Only the person possessing the private key $d$ can decrypt it:
&lt;/p>
$$ M \equiv C^d \pmod{N} $$
&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph LR
A["Plaintext"] --> B["Encrypt with public key (e, N)"]
B --> C["Ciphertext"]
C --> D["Decrypt with private key (d)"]
D --> E["Original Plaintext"]
F["Attacker"] -- "Attempts to factorize N" --> C
F -.-> G["d cannot be calculated without knowing p and q"]&lt;/div>
&lt;p>To break RSA cryptography, one must find (factorize) the original primes $p$ and $q$ from a massive $N$. Even using currently mainstream algorithms (such as the General Number Field Sieve, GNFS), factorizing a number with hundreds of digits would take significantly more time than the age of the universe, even with a supercomputer.&lt;/p>
&lt;hr>
&lt;h1 id="7-the-impact-of-the-riemann-hypothesis-on-cryptography">7. The Impact of the Riemann Hypothesis on Cryptography
&lt;/h1>&lt;p>So, how do the &amp;ldquo;Riemann Hypothesis,&amp;rdquo; which sits at the pinnacle of pure mathematics, and &amp;ldquo;cryptography&amp;rdquo; intersect?&lt;/p>
&lt;h3 id="71-prime-generation-algorithms-primality-testing-and-the-generalized-riemann-hypothesis-grh">7.1. Prime Generation Algorithms (Primality Testing) and the Generalized Riemann Hypothesis (GRH)
&lt;/h3>&lt;p>To operate RSA cryptography, gigantic prime numbers $p$ and $q$ must first be generated. However, it is not easy to reliably and quickly determine whether &amp;ldquo;a certain number is prime.&amp;rdquo;&lt;/p>
&lt;p>Currently, what is used practically is a probabilistic algorithm called the &lt;strong>Miller-Rabin primality test&lt;/strong>. Although this algorithm is fast, there is a risk of &amp;ldquo;pseudoprimes,&amp;rdquo; where a composite number is incorrectly identified as a prime number with an extremely low probability.&lt;/p>
&lt;p>However, if we assume the &lt;strong>&amp;ldquo;Generalized Riemann Hypothesis (GRH)&amp;rdquo;&lt;/strong>, which extends the Riemann Hypothesis to Dirichlet L-functions, to be true, the story changes dramatically.
If the GRH is true, an upper bound on the number of tests in the Miller-Rabin test is mathematically guaranteed, and it is &lt;strong>elevated from a probabilistic algorithm to a &amp;ldquo;deterministic polynomial-time algorithm&amp;rdquo;&lt;/strong> (this was a significant fact known even before the discovery of the AKS primality test).&lt;/p>
&lt;p>In short, the Riemann Hypothesis (and its generalization) plays a role in directly validating the foundation of cryptography: &amp;ldquo;Can we generate massive prime numbers quickly and with absolute confidence?&amp;rdquo;&lt;/p>
&lt;h3 id="72-relationship-with-factorization-algorithms">7.2. Relationship with Factorization Algorithms
&lt;/h3>&lt;p>When evaluating the computational complexity of algorithms for breaking codes (such as the General Number Field Sieve), knowledge of the distribution of prime numbers is also essential. Many integer factorization algorithms rely on the distribution of &amp;ldquo;Smooth numbers&amp;rdquo; (numbers that only have small prime factors).&lt;/p>
&lt;p>To strictly evaluate how frequently smooth numbers appear, a deep understanding of the distribution of primes is necessary, and analytic number theory techniques directly connected to the Zeta function and the Riemann Hypothesis are fully utilized here as well. If the Riemann Hypothesis is proven and the error in prime distribution is completely determined, it will become possible to more accurately assess the performance limits of integer factorization algorithms.&lt;/p>
&lt;hr>
&lt;h1 id="8-will-cryptography-be-broken-if-the-riemann-hypothesis-is-proven">8. Will Cryptography be Broken if the Riemann Hypothesis is Proven?
&lt;/h1>&lt;p>There is an urban legend that says, &amp;ldquo;If the Riemann Hypothesis is solved, RSA cryptography will instantly collapse,&amp;rdquo; but &lt;strong>this is mathematically inaccurate&lt;/strong>.&lt;/p>
&lt;p>The proof of the Riemann Hypothesis itself would not immediately yield a magical algorithm that drastically speeds up integer factorization. This is because the Riemann Hypothesis is ultimately a theorem about the &amp;ldquo;macroscopic regularity of the distribution&amp;rdquo; of primes, and it does not directly tell us which primes divide an individual number $N$ (a local property).&lt;/p>
&lt;p>However, the impact is not zero.
This is because, in the process of proving the Riemann Hypothesis, it is extremely likely that &lt;strong>&amp;ldquo;new mathematical tools&amp;rdquo; and &amp;ldquo;unknown analytical methods&amp;rdquo;&lt;/strong> will be discovered. Looking at history, when Fermat&amp;rsquo;s Last Theorem or the Poincaré Conjecture were proven, the new theories developed during the process greatly advanced the entirety of mathematics.&lt;/p>
&lt;p>If unknown algebraic geometry methods or non-commutative geometry methods are established that can completely manipulate the properties of the zeros of the Riemann Zeta function, it cannot be denied that this might ultimately lead to the discovery of a groundbreaking integer factorization algorithm (for example, a classical algorithm that reduces the computational complexity to polynomial time). In that sense, cryptographers can never take their eyes off the developments surrounding the Riemann Hypothesis.&lt;/p>
&lt;h3 id="quantum-computers-and-shors-algorithm">Quantum Computers and Shor&amp;rsquo;s Algorithm
&lt;/h3>&lt;p>A more direct and realistic threat to cryptography is not the proof of the Riemann Hypothesis, but &lt;strong>quantum computers&lt;/strong>. &amp;ldquo;Shor&amp;rsquo;s Algorithm,&amp;rdquo; published by Peter Shor in 1994, proved that integer factorization can be solved in polynomial time if a quantum computer with sufficient performance exists. Consequently, RSA cryptography and Elliptic Curve Cryptography will be fundamentally broken.&lt;/p>
&lt;p>Currently, a transition to &amp;ldquo;Post-Quantum Cryptography (PQC)&amp;rdquo; (such as lattice-based cryptography), which cannot be decrypted even by quantum computers, is progressing worldwide. Cryptography relying on prime numbers may be coming to the end of its golden age in a sense, but the mathematical value of prime numbers themselves will never be lost.&lt;/p>
&lt;hr>
&lt;h1 id="9-conclusion-the-intersection-of-mathematical-abstraction-and-real-society">9. Conclusion: The Intersection of Mathematical Abstraction and Real Society
&lt;/h1>&lt;div class="mermaid">graph TD
A["Exploration of pure mathematics"] --> B["Elucidation of the Riemann Hypothesis"]
B --> C["Complete understanding of prime distribution"]
C --> D["Leap in the development of number theory and algebraic geometry"]
D -.-> E["Possibility of new integer factorization algorithms"]
E -.-> F["Update of security evaluations for cryptography"]
A --> G["Applied mathematics and computer science"]
G --> H["Efficiency in primality testing and cryptographic generation"]
H --> F&lt;/div>
&lt;p>The insatiable exploration of prime numbers that has continued since ancient Greece was elevated by the genius of Riemann into a beautiful symphony (the zeros of the Zeta function) on the complex plane. Amazingly, after several centuries, the crystallization of that purely innocent mathematics is being applied as the strongest shield ensuring the safety of the internet society.&lt;/p>
&lt;p>The Riemann Hypothesis symbolizes both the &amp;ldquo;abstract beauty&amp;rdquo; of mathematics and its &amp;ldquo;astonishing applicability to the physical world and real society.&amp;rdquo;&lt;/p>
&lt;p>When this massive mountain of mathematics, whose peak no one has yet reached, is conquered someday, we will completely understand the universal truth of prime numbers and gain a new perspective on the foundation of our information society. Studying cryptography is, in itself, a journey tracing the history of human wisdom.&lt;/p></description></item><item><title>History of Cryptography: From Caesar Cipher to Post-Quantum Cryptography (PQC)</title><link>http://kenji.blog/en/p/history-of-cryptography-caesar-to-pqc/</link><pubDate>Fri, 11 Sep 2026 15:00:00 +0900</pubDate><guid>http://kenji.blog/en/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 History of Cryptography: From Caesar Cipher to Post-Quantum Cryptography (PQC)" />&lt;h1 id="1-introduction-what-is-cryptography">1. Introduction: What is Cryptography?
&lt;/h1>&lt;p>Cryptography is the technology used to maintain the confidentiality of information, and it has evolved alongside human history. From the transmission of secret commands in ancient wars to the protection of credit card information on the modern internet, the purpose of cryptography has remained consistent: &amp;ldquo;to ensure that only the intended recipient can understand the information, and that it cannot be deciphered by third parties.&amp;rdquo;&lt;/p>
&lt;p>In modern information security, cryptography goes beyond simple &amp;ldquo;information concealment (Confidentiality)&amp;rdquo; and plays crucial roles in ensuring data &amp;ldquo;Integrity,&amp;rdquo; &amp;ldquo;Authentication,&amp;rdquo; and &amp;ldquo;Non-repudiation.&amp;rdquo;&lt;/p>
&lt;p>In this article, we will thoroughly unravel the history of cryptographic evolution from a technical and mathematical perspective, starting from simple ancient substitution ciphers, through mechanical ciphers, modern symmetric and public-key cryptography, to the era of &amp;ldquo;Post-Quantum Cryptography (PQC)&amp;rdquo; brought about by the practical application of quantum computers.&lt;/p>
&lt;hr>
&lt;h1 id="2-the-era-of-classical-cryptography-letter-substitution-and-transposition">2. The Era of Classical Cryptography: Letter Substitution and Transposition
&lt;/h1>&lt;p>The origins of cryptography date back to Before Christ (B.C.). Early cryptography mainly consisted of two approaches: &amp;ldquo;Transposition&amp;rdquo; and &amp;ldquo;Substitution.&amp;rdquo;&lt;/p>
&lt;h2 id="scytale-cipher-transposition-cipher">Scytale Cipher (Transposition Cipher)
&lt;/h2>&lt;p>The &amp;ldquo;Scytale,&amp;rdquo; used in ancient Greece (Sparta) in the 5th century B.C., is one of the oldest cryptographic devices. A strip of parchment was wrapped around a wooden cylinder of a specific thickness, and a message was written across it horizontally. When the parchment was unwrapped, the letters were arranged in a meaningless order, but the recipient, who had a cylinder of the exact same thickness, could wrap the parchment around it again to read the original message.&lt;/p>
&lt;h2 id="caesar-cipher-monoalphabetic-substitution-cipher">Caesar Cipher (Monoalphabetic Substitution Cipher)
&lt;/h2>&lt;p>The &amp;ldquo;Caesar cipher,&amp;rdquo; believed to have been used by the ancient Roman hero Julius Caesar in the 1st century B.C., is a monoalphabetic substitution cipher that shifts the alphabet by a certain number of positions (usually 3 letters).&lt;/p>
&lt;p>Mathematically, if we treat letters as numbers from $0$ to $25$, and let the shift amount be $K$, the transformation from plaintext $P$ to ciphertext $C$ is expressed by the following congruence:&lt;/p>
$$C \equiv P + K \pmod{26}$$
&lt;p>Decryption is performed by the reverse operation.&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"># Simple Python implementation example of the Caesar cipher&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"># Shift calculation&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"># Execution example&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;Ciphertext: &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="frequency-analysis-and-the-vigenère-cipher">Frequency Analysis and the Vigenère Cipher
&lt;/h2>&lt;p>Monoalphabetic substitution ciphers became easily broken due to &amp;ldquo;Frequency Analysis,&amp;rdquo; devised by the 9th-century Arab scholar Al-Kindi. It utilizes the statistical properties of a language, such as the fact that in English, letters like &amp;ldquo;E&amp;rdquo; and &amp;ldquo;T&amp;rdquo; appear frequently.&lt;/p>
&lt;p>To counter this, the &amp;ldquo;Vigenère cipher&amp;rdquo; was invented in the 16th century. This is a polyalphabetic substitution cipher that periodically switches between multiple shifts (keys), and for about 300 years it was called the &amp;ldquo;indecipherable cipher (Le Chiffre Indéchiffrable).&amp;rdquo;&lt;/p>
&lt;p>Mathematically, using the $i$-th letter of the plaintext $P_i$ and the $i$-th letter of the repeating key $K_i$, the encryption is performed as follows:&lt;/p>
$$C_i \equiv P_i + K_i \pmod{26}$$
&lt;p>However, entering the 19th century, this cipher was also broken when Charles Babbage and Friedrich Kasiski discovered the &amp;ldquo;Kasiski examination,&amp;rdquo; a method to deduce the key length from repeated patterns in the ciphertext.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Classification of Classical Ciphers"
A["Classical Ciphers"] --> B["Transposition Ciphers"]
A --> C["Substitution Ciphers"]
B --> D["Scytale Cipher"]
C --> E["Monoalphabetic Substitution"]
C --> F["Polyalphabetic Substitution"]
E --> G["Caesar Cipher"]
F --> H["Vigenère Cipher"]
end&lt;/div>
&lt;hr>
&lt;h1 id="3-mechanical-ciphers-and-the-world-wars-enigma-and-its-decryption">3. Mechanical Ciphers and the World Wars: Enigma and its Decryption
&lt;/h1>&lt;p>Entering the 20th century, communication methods shifted from letters to telegraphs and radios, and speed and complexity in encryption became necessary. This is where &amp;ldquo;mechanical ciphers,&amp;rdquo; combining rotors (rotating disks), made their appearance.&lt;/p>
&lt;h2 id="the-threat-of-enigma">The Threat of Enigma
&lt;/h2>&lt;p>During World War II, the &amp;ldquo;Enigma,&amp;rdquo; used by Nazi Germany, became the most famous cipher machine in cryptographic history. Enigma consisted of multiple rotors (usually 3 to 4), a plugboard (Steckerbrett) to swap letter wirings, and a reflector (reversing rotor).&lt;/p>
&lt;p>Because the rotors advanced with every letter typed on the keyboard, typing the same letter consecutively would output different ciphertext letters (the pinnacle of polyalphabetic ciphers). Its key space (combinations of settings) reached approximately $1.58 \times 10^{19}$ (about 15.8 quintillion), and with the technology of that time, brute-force decryption was considered impossible.&lt;/p>
&lt;h2 id="alan-turing-and-the-bombe">Alan Turing and the &amp;ldquo;Bombe&amp;rdquo;
&lt;/h2>&lt;p>Challenging this impregnable Enigma was the decryption team at Bletchley Park in the UK, building upon the early achievements of Polish mathematician Marian Rejewski and others.&lt;/p>
&lt;p>In particular, Alan Turing developed an electromechanical decryption machine called the &amp;ldquo;Bombe,&amp;rdquo; which utilized guesses of the plaintext corresponding to parts of the ciphertext (Cribs). The Bombe quickly detected logical contradictions and successively eliminated impossible rotor settings, successfully breaking Enigma. It is said that this great achievement advanced the Allied victory by several years.&lt;/p>
&lt;hr>
&lt;h1 id="4-the-dawn-of-modern-cryptography-symmetric-key-cryptography-des-and-aes">4. The Dawn of Modern Cryptography: Symmetric-key Cryptography (DES and AES)
&lt;/h1>&lt;p>After the war, with the advent of computers, cryptography underwent a dramatic paradigm shift from manipulating &amp;ldquo;letters&amp;rdquo; to manipulating &amp;ldquo;bits (0 and 1).&amp;rdquo;&lt;/p>
&lt;h2 id="claude-shannon-and-information-theory">Claude Shannon and Information Theory
&lt;/h2>&lt;p>In 1949, Claude Shannon published the paper &amp;ldquo;Communication Theory of Secrecy Systems,&amp;rdquo; laying the mathematical foundation for modern cryptography. He proposed &amp;ldquo;Confusion&amp;rdquo; and &amp;ldquo;Diffusion&amp;rdquo; as principles of secure cryptographic design.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Confusion&lt;/strong>: Making the relationship between the key and the ciphertext as complex as possible. (Realized by substitution and S-boxes)&lt;/li>
&lt;li>&lt;strong>Diffusion&lt;/strong>: Ensuring that changing one bit of the plaintext affects many bits in the ciphertext. (Realized by transposition and permutation)&lt;/li>
&lt;/ul>
&lt;h2 id="des-data-encryption-standard">DES (Data Encryption Standard)
&lt;/h2>&lt;p>In 1977, the National Institute of Standards and Technology (NIST, then NBS) established &amp;ldquo;DES,&amp;rdquo; based on an IBM design, as the standard cipher.
DES adopts an architecture called a &amp;ldquo;Feistel Network&amp;rdquo; and has a block length of 64 bits and a key length of 56 bits. It had the implementation advantage that the encryption and decryption algorithms were structurally almost identical.&lt;/p>
&lt;p>However, as computer computational power improved, it became clear that a 56-bit key length (about $7.2 \times 10^{16}$ combinations) was insufficient. In 1998, the Electronic Frontier Foundation (EFF) developed a dedicated machine called &amp;ldquo;Deep Crack&amp;rdquo; and demonstrated that they could crack DES in just a few days.&lt;/p>
&lt;h2 id="aes-advanced-encryption-standard">AES (Advanced Encryption Standard)
&lt;/h2>&lt;p>As a new standard to replace DES, &amp;ldquo;AES&amp;rdquo; was established in 2001. The &amp;ldquo;Rijndael&amp;rdquo; algorithm, submitted by Belgian cryptographers through an open competition, was adopted.&lt;/p>
&lt;p>AES adopts an &amp;ldquo;SPN structure (Substitution-Permutation Network)&amp;rdquo; rather than a Feistel Network, and utilizes mathematical operations over the Galois field (finite field) $GF(2^8)$. The key length can be chosen from 128, 192, or 256 bits, and it continues to be widely used around the world today as the standard symmetric-key cipher.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "One Round of AES Processing (SPN Structure)"
A["Input State (128-bit)"] --> B("SubBytes (Byte Substitution / S-Box)")
B --> C("ShiftRows (Row Shift)")
C --> D("MixColumns (Column Mix / Multiplication over GF(2^8))")
D --> E("AddRoundKey (XOR with Round Key)")
E --> F["To Next Round"]
end&lt;/div>
&lt;hr>
&lt;h1 id="5-the-public-key-cryptography-revolution-from-diffie-hellman-to-rsa">5. The Public-key Cryptography Revolution: From Diffie-Hellman to RSA
&lt;/h1>&lt;p>Symmetric-key cryptography had a fatal weakness. It was the &amp;ldquo;Key Distribution Problem&amp;rdquo;: how to securely share a &amp;ldquo;common key&amp;rdquo; with a distant party before starting encrypted communication. The &amp;ldquo;public-key cryptography&amp;rdquo; born in the 1970s solved this problem.&lt;/p>
&lt;h2 id="diffie-hellman-key-exchange">Diffie-Hellman Key Exchange
&lt;/h2>&lt;p>In 1976, Whitfield Diffie and Martin Hellman published a groundbreaking paper, &amp;ldquo;New Directions in Cryptography.&amp;rdquo; They proposed a method that allows for the secure sharing of keys even over wiretapped communication channels by utilizing the mathematical difficulty of the &amp;ldquo;Discrete Logarithm Problem.&amp;rdquo;&lt;/p>
&lt;ol>
&lt;li>Publish a large prime number $p$ and a generator $g$.&lt;/li>
&lt;li>Alice chooses a secret value $a$ and sends $A = g^a \pmod{p}$ to Bob.&lt;/li>
&lt;li>Bob chooses a secret value $b$ and sends $B = g^b \pmod{p}$ to Alice.&lt;/li>
&lt;li>Alice calculates $K = B^a \pmod{p}$, and Bob calculates $K = A^b \pmod{p}$.&lt;/li>
&lt;li>By the laws of exponents, $K = (g^b)^a = (g^a)^b = g^{ab} \pmod{p}$, and they successfully share the exact same key $K$.&lt;/li>
&lt;/ol>
&lt;h2 id="rsa-cryptography">RSA Cryptography
&lt;/h2>&lt;p>The following year, in 1977, &amp;ldquo;RSA cryptography&amp;rdquo; was devised by Ron Rivest, Adi Shamir, and Leonard Adleman. It is based on the property that &amp;ldquo;factoring the product of two very large prime numbers is difficult.&amp;rdquo;&lt;/p>
&lt;p>&lt;strong>Mathematical Mechanism of RSA:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Choose two large prime numbers $p$ and $q$, and calculate $n = p \times q$.&lt;/li>
&lt;li>Calculate Euler&amp;rsquo;s totient function $\phi(n) = (p-1)(q-1)$.&lt;/li>
&lt;li>Choose an integer $e$ (public key) that is coprime to $\phi(n)$.&lt;/li>
&lt;li>Calculate an integer $d$ (private key) such that $e \times d \equiv 1 \pmod{\phi(n)}$.&lt;/li>
&lt;/ol>
&lt;p>Encryption: For plaintext $M$, $C \equiv M^e \pmod{n}$
Decryption: For ciphertext $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"># Python code demonstrating the concept of RSA cryptography (not for practical use)&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"># Calculation of modular inverse using the Extended Euclidean Algorithm&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"># Example using small prime numbers&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"># Value coprime to 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;Public Key: (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;Private Key: (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"># Encryption and decryption of a message&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;Plaintext: &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; Ciphertext: &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; Decrypted: &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-the-rise-of-elliptic-curve-cryptography-ecc">6. The Rise of Elliptic Curve Cryptography (ECC)
&lt;/h1>&lt;p>While RSA cryptography is powerful, as computer performance improved, it became necessary to increase the key length to maintain security (currently 2048 or 3072 bits), which caused the problem of increased computational cost.&lt;/p>
&lt;p>Thus, in 1985, &amp;ldquo;Elliptic Curve Cryptography (ECC)&amp;rdquo; was proposed. This utilizes point addition on elliptic curves over finite fields (generally of the form $y^2 = x^3 + ax + b$).&lt;/p>
&lt;p>The Elliptic Curve Discrete Logarithm Problem (ECDLP) is known to be even harder to solve than the integer factorization problem, and &lt;strong>ECC can achieve security equivalent to a 3072-bit RSA key with a key length of only 256 bits&lt;/strong>. This made fast and secure encrypted communication (such as ECDSA and ECDH) possible even in environments with limited computational resources, like smartphones and IoT devices.&lt;/p>
&lt;hr>
&lt;h1 id="7-the-threat-of-quantum-computers-and-post-quantum-cryptography-pqc">7. The Threat of Quantum Computers and Post-Quantum Cryptography (PQC)
&lt;/h1>&lt;p>Cryptographic technology seemed rock-solid, but in 1994, a massive shockwave hit with the announcement of &amp;ldquo;Shor&amp;rsquo;s Algorithm&amp;rdquo; by Peter Shor.&lt;/p>
&lt;p>Quantum computers perform calculations utilizing the properties of quantum mechanics, namely &amp;ldquo;superposition&amp;rdquo; and &amp;ldquo;quantum entanglement.&amp;rdquo; It was mathematically proven that if Shor&amp;rsquo;s algorithm is executed on a sufficiently capable quantum computer, the integer factorization problem and the discrete logarithm problem could be solved in &amp;ldquo;polynomial time.&amp;rdquo; This means that on the day a practical quantum computer is completed (Q-Day), all currently used public-key cryptosystems like RSA and ECC will instantaneously collapse.&lt;/p>
&lt;h2 id="the-emergence-of-pqc-post-quantum-cryptography">The Emergence of PQC (Post-Quantum Cryptography)
&lt;/h2>&lt;p>To prepare for this unprecedented threat, research is rapidly progressing on &amp;ldquo;Post-Quantum Cryptography (PQC),&amp;rdquo; based on new mathematical problems that are difficult to break even for quantum computers. NIST (National Institute of Standards and Technology) has been running a PQC standardization process for many years, and the following mathematical approaches are primarily considered the most promising.&lt;/p>
&lt;h3 id="1-lattice-based-cryptography">1. Lattice-based Cryptography
&lt;/h3>&lt;p>This is currently the most promising approach and has been adopted in NIST&amp;rsquo;s standardized algorithms (ML-KEM / Kyber, ML-DSA / Dilithium). It is based on the difficulty of problems like finding specific points on a &amp;ldquo;lattice&amp;rdquo; in a multi-dimensional space (Shortest Vector Problem: SVP, etc.) or the LWE (Learning With Errors) problem.&lt;/p>
&lt;p>The concept of the LWE problem utilizes the property that if you intentionally add a &amp;ldquo;small noise (error)&amp;rdquo; to a system of linear equations, it suddenly becomes extremely difficult to find the solution.
System of equations: $\mathbf{A}\mathbf{s} + \mathbf{e} \equiv \mathbf{b} \pmod{q}$
($\mathbf{A}$ and $\mathbf{b}$ are public, $\mathbf{s}$ is the private key, and $\mathbf{e}$ is a tiny noise)&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"># Conceptual pseudocode for the LWE problem (for educational purposes)&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"># Dimension&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"># Modulus&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"># Number of equations&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"># Private key s and small error 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"># Public matrix A and public vector 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"># Even with a quantum computer, recovering s from A and b is considered extremely difficult&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="2-hash-based-cryptography">2. Hash-based Cryptography
&lt;/h3>&lt;p>This is a digital signature scheme that bases its security solely on the collision resistance of hash functions. Since it does not have a mathematical structure, it is resilient to quantum attacks, but the signature sizes tend to be large (e.g., SPHINCS+).&lt;/p>
&lt;h3 id="3-code-based-cryptography">3. Code-based Cryptography
&lt;/h3>&lt;p>An encryption scheme based on the theory of error-correcting codes. The McEliece cryptosystem, proposed in 1978, is famous; it has a long history and an established reputation for security, but it faces the challenge of extremely large public key sizes (sometimes reaching several megabytes).&lt;/p>
&lt;div class="mermaid">timeline
title "History of the Evolution of Cryptography and Computers"
"Ancient to Middle Ages" : "Caesar Cipher" : "Vigenère Cipher" : "Birth of Frequency Analysis"
"1930s-1940s" : "Enigma Operation and Decryption" : "Development of Turing Machine/Bombe"
"1970s" : "DES Standardization (1977)" : "Diffie-Hellman Key Exchange (1976)" : "Birth of RSA Cryptography (1977)"
"1980s-1990s" : "Proposal of Elliptic Curve Cryptography (ECC)" : "Publication of Shor's Algorithm (1994)"
"2000s" : "AES Standardization (2001)"
"2010s to Present" : "Acceleration of Quantum Computer Research" : "Start of PQC Standardization Project by NIST"
"Near Future (Q-Day)" : "Realization of Large-Scale Quantum Computers?" : "Full Transition to PQC (ML-KEM/ML-DSA)"&lt;/div>
&lt;hr>
&lt;h1 id="8-conclusion-the-endless-battle-of-shield-and-spear">8. Conclusion: The Endless Battle of Shield and Spear
&lt;/h1>&lt;p>The history of cryptography is a history of an endless battle between the invention of new cryptographic schemes (the shield) and new decryption methods to break them (the spear).&lt;/p>
&lt;p>The Caesar cipher was defeated by frequency analysis, and the invincible Enigma was defeated by Turing&amp;rsquo;s genius mind and the power of machines. And now, the powerful ciphers like RSA and ECC that form the backbone of modern internet society are exposed to the threat of a new &amp;ldquo;spear,&amp;rdquo; the quantum computer.&lt;/p>
&lt;p>However, humanity is already looking towards the future beyond that and is preparing a new &amp;ldquo;shield&amp;rdquo; called Post-Quantum Cryptography (PQC). Currently, preparing for the transition from existing public-key cryptography to PQC (ensuring Crypto Agility) is an urgent task for IT infrastructures worldwide.&lt;/p>
&lt;p>Cryptography is not just an arcane mathematical puzzle; it is the strongest defensive wall for protecting our privacy, property, and the social infrastructure itself.&lt;/p></description></item><item><title>[Math Explanation] Explaining How RSA Encryption Works So Even a High Schooler Can Understand</title><link>http://kenji.blog/en/p/rsa-encryption-math-explained-for-beginners/</link><pubDate>Fri, 11 Sep 2026 13:00:00 +0900</pubDate><guid>http://kenji.blog/en/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 [Math Explanation] Explaining How RSA Encryption Works So Even a High Schooler Can Understand" />&lt;p>One of the technologies supporting the safety of our internet society from the ground up is &amp;ldquo;RSA Encryption&amp;rdquo;. Many of the communications we casually use every day, such as credit card payments in online shopping, SNS exchanges with friends, and the transmission/reception of company confidential information, are protected by this RSA encryption and its successor technologies.&lt;/p>
&lt;p>However, when you hear the word &amp;ldquo;cryptography&amp;rdquo;, you might imagine complex cipher machines like those in spy movies, or super advanced mathematics that only a few geniuses can understand. It is true that modern cryptographic theory is based on advanced mathematics, but &lt;strong>the fundamental mechanism of RSA encryption can be fully understood if you have the knowledge of high school mathematics (properties of integers, prime numbers, congruences, etc.)&lt;/strong>.&lt;/p>
&lt;p>In this article, taking high school math knowledge as a starting point, I will thoroughly explain step-by-step the mathematical principles by which RSA encryption operates and why it is so difficult to crack. I will explain carefully with concrete examples so that even those who are not very good at math can understand.&lt;/p>
&lt;hr>
&lt;h2 id="1-symmetric-key-and-public-key-cryptography">1. Symmetric-key and Public-key Cryptography
&lt;/h2>&lt;p>Before getting into the mathematical mechanisms of RSA encryption, let&amp;rsquo;s first organize the basic ideas of cryptography. Cryptographic methods can be broadly divided into two types: &amp;ldquo;Symmetric-key Cryptography&amp;rdquo; and &amp;ldquo;Public-key Cryptography&amp;rdquo;.&lt;/p>
&lt;h3 id="11-limitations-of-symmetric-key-cryptography">1.1 Limitations of Symmetric-key Cryptography
&lt;/h3>&lt;p>Many of the traditionally used ciphers are what is called the &amp;ldquo;Symmetric-key Cryptography&amp;rdquo; method. This is a method that uses &lt;strong>the same key for both &amp;ldquo;encryption (converting a message into secret ciphertext)&amp;rdquo; and &amp;ldquo;decryption (restoring the ciphertext back to the original message)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>For example, suppose Alice sends a secret letter to Bob. Alice uses a padlock (symmetric key) to put the letter in a box and lock it. In order for Bob to open that box, he needs to have the exact same key that Alice used.&lt;/p>
&lt;p>There is a major problem with this method. It is the &amp;ldquo;key distribution problem&amp;rdquo;. When Alice and Bob, who are far apart, communicate for the first time, how should they share the key without it being eavesdropped on? If the key is stolen by a third party while being mailed, all subsequent encrypted communications will be completely leaked.&lt;/p>
&lt;h3 id="12-the-breakthrough-invention-public-key-cryptography">1.2 The Breakthrough Invention: &amp;ldquo;Public-key Cryptography&amp;rdquo;
&lt;/h3>&lt;p>&amp;ldquo;Public-key Cryptography&amp;rdquo; was invented to solve this key distribution problem. RSA encryption is also one of this kind.&lt;/p>
&lt;p>In public-key cryptography, we use &lt;strong>two different keys: a &amp;ldquo;key for encryption (public key)&amp;rdquo; and a &amp;ldquo;key for decryption (private key)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>The receiver, Bob, creates a pair of &amp;ldquo;public key&amp;rdquo; and &amp;ldquo;private key&amp;rdquo;.&lt;/li>
&lt;li>Bob publishes the &amp;ldquo;public key&amp;rdquo; to the world (it doesn&amp;rsquo;t matter who gets it).&lt;/li>
&lt;li>The sender, Alice, encrypts her message using Bob&amp;rsquo;s &amp;ldquo;public key&amp;rdquo; and sends it.&lt;/li>
&lt;li>The encrypted message can only be decrypted with the &amp;ldquo;private key&amp;rdquo; that only Bob possesses.&lt;/li>
&lt;/ol>
&lt;p>Comparing this to padlocks, Bob makes many &amp;ldquo;open padlocks (public keys)&amp;rdquo; and scatters them all over the world. Alice puts her message addressed to Bob into a box and snaps it shut using a padlock of Bob&amp;rsquo;s that she picked up. Once the padlock is closed, it can only be opened with the &amp;ldquo;master key (private key)&amp;rdquo; that Bob holds. Even if someone steals the box on the way, they cannot open it because they don&amp;rsquo;t have the master key.&lt;/p>
&lt;div class="mermaid">graph TD
A["Alice (Sender)"] --> B["Plaintext (Message)"]
B --> C["Encryption Process"]
D["Bob's Public Key (Available to anyone)"] --> C
C --> E["Send via Internet: Ciphertext"]
E --> F["Decryption Process"]
G["Bob's Private Key (Held only by Bob)"] --> F
F --> H["Restored Plaintext (Message)"]
H --> I["Bob (Receiver)"]&lt;/div>
&lt;p>In order to realize this epoch-making system, a kind of &lt;strong>&amp;ldquo;one-way function (a one-way mathematical puzzle)&amp;rdquo;&lt;/strong> is necessary, one where &amp;ldquo;encryption with the public key is easy, but decryption without the private key is absolutely impossible.&amp;rdquo; What was focused on as a component of that puzzle was the &amp;ldquo;prime numbers&amp;rdquo; we all know so well.&lt;/p>
&lt;hr>
&lt;h2 id="2-the-mathematical-foundation-supporting-rsa-1-prime-numbers-and-prime-factorization">2. The Mathematical Foundation Supporting RSA 1: Prime Numbers and Prime Factorization
&lt;/h2>&lt;p>The security of RSA encryption is based on the mathematical fact that &lt;strong>&amp;ldquo;prime factorization of huge numbers is extremely difficult.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;h3 id="21-what-are-prime-numbers">2.1 What are Prime Numbers?
&lt;/h3>&lt;p>A prime number is &amp;ldquo;a natural number greater than 1 that can only be divided by 1 and itself.&amp;rdquo;
Example: $2, 3, 5, 7, 11, 13, 17, 19, 23...$&lt;/p>
&lt;p>Prime numbers are like the &amp;ldquo;atoms&amp;rdquo; of all integers. Any natural number can be broken down into the product of prime numbers. This is called &lt;strong>prime factorization&lt;/strong>. For example, it is known as the &amp;ldquo;Fundamental Theorem of Arithmetic&amp;rdquo; that a number can be uniquely factorized into primes (ignoring order), such as $60 = 2^2 \times 3 \times 5$.&lt;/p>
&lt;h3 id="22-the-difficulty-of-prime-factorization-one-way-function">2.2 The Difficulty of Prime Factorization (One-way Function)
&lt;/h3>&lt;p>What&amp;rsquo;s important here is the asymmetry that &lt;strong>&amp;ldquo;multiplication is easy, but prime factorization is difficult.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;p>For example, try doing mental arithmetic for the multiplication of the following two prime numbers.
$11 \times 13 = ?$
This is easy. The answer is $143$.&lt;/p>
&lt;p>Then, how about the following number?
Please prime factorize $323$.
How is it? It should take a little time. (The answer is $17 \times 19$).&lt;/p>
&lt;p>If the numbers are small, humans can manage to calculate them, but as the numbers get larger, it becomes explosively difficult to calculate even using computers. In mainstream RSA encryption today, we use a number $N = p \times q$, which is the product of two incredibly huge prime numbers $p$ and $q$ of 2048 bits (about 600 digits in decimal).&lt;/p>
&lt;p>Given two huge prime numbers $p$ and $q$, it takes an instant (less than a millisecond) for a computer to calculate $N$. However, conversely, given only $N$, finding the original $p$ and $q$ takes so much time that even the current fastest supercomputer could not solve it if it ran for trillions of years.&lt;/p>
&lt;p>This &lt;strong>&amp;ldquo;computational asymmetry (one way is easy, the reverse is difficult)&amp;rdquo;&lt;/strong> is the foundation that creates the relationship between the public key and the private key.&lt;/p>
&lt;hr>
&lt;h2 id="3-the-mathematical-foundation-supporting-rsa-2-congruence-modulo-arithmetic">3. The Mathematical Foundation Supporting RSA 2: Congruence (Modulo Arithmetic)
&lt;/h2>&lt;p>The calculations for RSA encryption are not done with addition or multiplication where numbers grow infinitely like we normally use, but rather in a world of &amp;ldquo;remainders&amp;rdquo; after dividing by a certain number. This is called &lt;strong>congruence (modulo arithmetic)&lt;/strong>.&lt;/p>
&lt;h3 id="31-clock-math">3.1 Clock Math
&lt;/h3>&lt;p>Modulo arithmetic is often compared to &amp;ldquo;clock math&amp;rdquo;. If it is currently 10 o&amp;rsquo;clock, what time will it be 5 hours from now? $10 + 5 = 15$ o&amp;rsquo;clock, but on a normal 12-hour clock, we answer &amp;ldquo;3 o&amp;rsquo;clock&amp;rdquo;. This is because the remainder of 15 divided by 12 is 3.&lt;/p>
&lt;p>In the world of mathematics, this is written as follows:
&lt;/p>
$$ 15 \equiv 3 \pmod{12} $$
&lt;p>
You read this as &amp;ldquo;15 is congruent to 3 modulo 12 (the remainder when divided by 12 is equal).&amp;rdquo;&lt;/p>
&lt;h3 id="32-basic-properties-of-congruences">3.2 Basic Properties of Congruences
&lt;/h3>&lt;p>Congruences have very convenient properties very similar to equalities ($=$). Let the modulus (the divisor) be $N$.
When $a \equiv b \pmod N$ and $c \equiv d \pmod N$, the following hold true:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Addition:&lt;/strong> $a + c \equiv b + d \pmod N$&lt;/li>
&lt;li>&lt;strong>Subtraction:&lt;/strong> $a - c \equiv b - d \pmod N$&lt;/li>
&lt;li>&lt;strong>Multiplication:&lt;/strong> $a \times c \equiv b \times d \pmod N$&lt;/li>
&lt;li>&lt;strong>Exponentiation:&lt;/strong> $a^k \equiv b^k \pmod N$ ($k$ is a natural number)&lt;/li>
&lt;/ol>
&lt;p>Particularly important is the property of &amp;ldquo;exponentiation&amp;rdquo;. This means that &lt;strong>&amp;ldquo;the power of a remainder is equal to the remainder of the power&amp;rdquo;&lt;/strong>.
For example, suppose you want to find the remainder of $7^{100}$ divided by $5$. Multiplying $7$ a hundred times and then dividing by $5$ in earnest is very hard, but if you use the properties of congruences, since $7 \equiv 2 \pmod 5$, it becomes $7^{100} \equiv 2^{100} \pmod 5$, and you can drastically simplify the calculation. This property is indispensable in the world of cryptography because we deal with exponentiations of very large numbers.&lt;/p>
&lt;hr>
&lt;h2 id="4-the-mathematical-foundation-supporting-rsa-3-eulers-totient-function-and-eulers-theorem">4. The Mathematical Foundation Supporting RSA 3: Euler&amp;rsquo;s Totient Function and Euler&amp;rsquo;s Theorem
&lt;/h2>&lt;p>From here on is the magic mathematics that forms the core of RSA encryption. &amp;ldquo;Euler&amp;rsquo;s Theorem&amp;rdquo;, a generalization of &amp;ldquo;Fermat&amp;rsquo;s Little Theorem&amp;rdquo;, makes its appearance.&lt;/p>
&lt;h3 id="41-eulers-totient-function-phin">4.1 Euler&amp;rsquo;s Totient Function $\phi(N)$
&lt;/h3>&lt;p>For a given natural number $N$, Euler&amp;rsquo;s totient function (the $\phi$ function) is a function that returns &lt;strong>&amp;ldquo;the number of natural numbers from 1 to $N$ that are coprime with $N$ (meaning their greatest common divisor is 1).&amp;rdquo;&lt;/strong>&lt;/p>
&lt;p>Let&amp;rsquo;s look at some examples.&lt;/p>
&lt;ul>
&lt;li>$\phi(5)$: Among 1, 2, 3, 4, 5, the numbers coprime with 5 are 1, 2, 3, 4, which is 4 numbers. Therefore, $\phi(5) = 4$.&lt;/li>
&lt;li>$\phi(6)$: Among 1, 2, 3, 4, 5, 6, the numbers coprime with 6 are 1, 5, which is 2 numbers. Therefore, $\phi(6) = 2$.&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[Special Property in the Case of Prime Numbers]&lt;/strong>
If $p$ is a prime number, all numbers from 1 to $p-1$ are coprime with $p$. Therefore,
&lt;/p>
$$ \phi(p) = p - 1 $$
&lt;p>&lt;strong>[Special Property in the Case of the Product of Prime Numbers]&lt;/strong>
For two distinct prime numbers $p$ and $q$, if $N = p \times q$, $\phi(N)$ can be easily calculated as follows.
&lt;/p>
$$ \phi(N) = \phi(p) \times \phi(q) = (p - 1)(q - 1) $$
&lt;p>
This property functions as the &amp;ldquo;secret backdoor (trapdoor)&amp;rdquo; in RSA encryption. The person who knows $p$ and $q$ (the creator of the key) can calculate $\phi(N)$ instantly, but a third party who only knows $N$ cannot determine $\phi(N)$ unless they prime factorize $N$.&lt;/p>
&lt;h3 id="42-eulers-theorem">4.2 Euler&amp;rsquo;s Theorem
&lt;/h3>&lt;p>Leonhard Euler used this $\phi(N)$ to prove the following beautiful theorem.&lt;/p>
&lt;p>&lt;strong>Euler&amp;rsquo;s Theorem:&lt;/strong>
When the integer $a$ and $N$ are coprime, the following congruence holds.
&lt;/p>
$$ a^{\phi(N)} \equiv 1 \pmod N $$
&lt;p>This is an amazing property that says, &amp;ldquo;If you multiply a number $a$ by itself $\phi(N)$ times and divide by $N$, the remainder will always be $1$.&amp;rdquo; (When $N$ is a prime number $p$, it becomes $a^{p-1} \equiv 1 \pmod p$, which is called Fermat&amp;rsquo;s Little Theorem).&lt;/p>
&lt;p>Let&amp;rsquo;s modify this Euler&amp;rsquo;s Theorem. Multiply both sides by $a$ one more time.
&lt;/p>
$$ a^{\phi(N) + 1} \equiv a \pmod N $$
&lt;p>Furthermore, for any integer $k$, since $a^{k \cdot \phi(N)}$ also becomes $1^k = 1$, the following equation holds.
&lt;/p>
$$ a^{k \cdot \phi(N) + 1} \equiv a \pmod N $$
&lt;p>This very equation is the fundamental principle that makes the magic of RSA encryption work: &lt;strong>&amp;ldquo;If you encrypt and then decrypt, it returns to the original.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;hr>
&lt;h2 id="5-the-rsa-algorithm-steps-for-key-generation-encryption-and-decryption">5. The RSA Algorithm: Steps for Key Generation, Encryption, and Decryption
&lt;/h2>&lt;p>Now that we have the basic knowledge, let&amp;rsquo;s finally look at the specific steps of RSA encryption. RSA encryption is roughly divided into three phases: &amp;ldquo;1. Key Generation,&amp;rdquo; &amp;ldquo;2. Encryption,&amp;rdquo; and &amp;ldquo;3. Decryption.&amp;rdquo;&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Choose prime numbers p, q"] --> A2["Calculate N = p × q"]
A1 --> A3["Calculate φ(N) = (p-1)(q-1)"]
A3 --> A4["Choose e coprime with φ(N)"]
A3 --> A5["Calculate d such that e × d ≡ 1 (mod φ(N))"]
A2 --> A6["Public Key (N, e)"]
A4 --> A6
A5 --> A7["Private Key d"]
B1["2. Plaintext message M"] --> B2["Calculate C ≡ M^e (mod N)"]
A6 -.-> B2
B2 --> B3["Send ciphertext C"]
B3 --> C1["3. Received ciphertext C"]
C1 --> C2["Calculate M ≡ C^d (mod N)"]
A7 -.-> C2
C2 --> C3["Obtain original plaintext message M"]&lt;/div>
&lt;h3 id="51-key-generation">5.1 Key Generation
&lt;/h3>&lt;p>The receiver, Bob, generates a &amp;ldquo;public key&amp;rdquo; and a &amp;ldquo;private key&amp;rdquo; for himself.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Choice of Primes:&lt;/strong> Randomly choose two large prime numbers $p$ and $q$.&lt;/li>
&lt;li>&lt;strong>Calculation of Modulus $N$:&lt;/strong> Calculate $N = p \times q$. This $N$ is made public.&lt;/li>
&lt;li>&lt;strong>Calculation of $\phi(N)$:&lt;/strong> Calculate Euler&amp;rsquo;s function $\phi(N) = (p - 1)(q - 1)$. This is a secret number only Bob knows.&lt;/li>
&lt;li>&lt;strong>Choice of Public Key $e$:&lt;/strong> Choose an integer $e$ such that $1 &lt; e &lt; \phi(N)$ and $e$ is coprime with $\phi(N)$.&lt;/li>
&lt;li>&lt;strong>Calculation of Private Key $d$:&lt;/strong> Find an integer $d$ that satisfies the following condition.
$$ e \times d \equiv 1 \pmod{\phi(N)} $$
In other words, this is &amp;ldquo;a number $d$ such that the remainder is $1$ when $e \times d$ is divided by $\phi(N)$.&amp;rdquo;&lt;/li>
&lt;/ol>
&lt;p>Now the key preparation is complete.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Public Key:&lt;/strong> The pair $(N, e)$. It is published to the whole world.&lt;/li>
&lt;li>&lt;strong>Private Key:&lt;/strong> $d$. Never tell anyone under any circumstances.&lt;/li>
&lt;/ul>
&lt;h3 id="52-encryption">5.2 Encryption
&lt;/h3>&lt;p>Suppose Alice wants to send a secret message $M$ to Bob. (Let $M$ be a number formed by digitizing characters, and assume $0 \le M &lt; N$). Alice calculates as follows using Bob&amp;rsquo;s public key $(N, e)$.&lt;/p>
$$ C \equiv M^e \pmod N $$
&lt;p>She calculates &amp;ldquo;the remainder $C$ when message $M$ is raised to the power of $e$, divided by $N$&amp;rdquo;. This $C$ is the ciphertext.&lt;/p>
&lt;h3 id="53-decryption">5.3 Decryption
&lt;/h3>&lt;p>Bob receives the ciphertext $C$. Bob calculates as follows using his private key $d$.&lt;/p>
$$ M \equiv C^d \pmod N $$
&lt;p>By calculating &amp;ldquo;the remainder when ciphertext $C$ is raised to the power of $d$, divided by $N$&amp;rdquo;, amazingly, the original message $M$ is restored!&lt;/p>
&lt;hr>
&lt;h2 id="6-why-does-decryption-revert-it-to-the-original-mathematical-proof">6. Why Does Decryption Revert it to the Original? (Mathematical Proof)
&lt;/h2>&lt;p>You might be wondering, &amp;ldquo;Why does simply raising $C$ to the power of $d$ return it to the original $M$?&amp;rdquo; This is where the aforementioned &amp;ldquo;Euler&amp;rsquo;s Theorem&amp;rdquo; demonstrates its power.&lt;/p>
&lt;p>Let&amp;rsquo;s substitute the encryption formula $C = M^e$ into the decryption calculation formula $C^d \pmod N$.
&lt;/p>
$$ C^d \equiv (M^e)^d \equiv M^{ed} \pmod N $$
&lt;p>Here, recall Step 5 of the key generation. When Bob made $d$, he chose it so that $e \times d \equiv 1 \pmod{\phi(N)}$. This means &amp;ldquo;the number $ed$ is a multiple of $\phi(N)$ plus $1$.&amp;rdquo; Using an integer $k$, it can be written as follows:
&lt;/p>
$$ ed = k \cdot \phi(N) + 1 $$
&lt;p>Substitute this into the exponent part, and decompose it using exponent rules.
&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>Here, assuming that the message $M$ and $N$ are coprime, from &lt;strong>Euler&amp;rsquo;s Theorem&lt;/strong>, we get $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>Therefore, the following formula beautifully holds true.
&lt;/p>
$$ C^d \equiv M \pmod N $$
&lt;p>Alice does not know $d$, and an eavesdropper does not know $d$ either, so only Bob, who has $d$, can extract $M$ from $C$.&lt;/p>
&lt;hr>
&lt;h2 id="7-concrete-example-experiencing-rsa-by-hand-calculation-using-small-primes">7. Concrete Example: Experiencing RSA by Hand Calculation Using Small Primes
&lt;/h2>&lt;p>Let&amp;rsquo;s actually try encrypted communication from Alice to Bob using small numbers (prime numbers).&lt;/p>
&lt;p>&lt;strong>[Bob&amp;rsquo;s Key Generation Phase]&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Choose two prime numbers $p=11$, $q=13$.&lt;/li>
&lt;li>Calculate $N = 11 \times 13 = 143$.&lt;/li>
&lt;li>Calculate $\phi(N) = (11 - 1) \times (13 - 1) = 10 \times 12 = 120$.&lt;/li>
&lt;li>Choose a public key $e$ that is coprime with $\phi(N)=120$. Here we will use $e=7$.&lt;/li>
&lt;li>Find the private key $d$. Look for $d$ such that $7 \times d \equiv 1 \pmod{120}$.
In the equation $7d = 120k + 1$, when $k=6$, it becomes $721$, and $721 \div 7 = 103$.
Therefore, $d = 103$.&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Public Key: $(N=143, e=7)$&lt;/li>
&lt;li>Private Key: $d=103$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>[Alice&amp;rsquo;s Encryption Phase]&lt;/strong>
Suppose she wants to send the message $M = 9$.
Formula: $C \equiv 9^7 \pmod{143}$
$9^7 = 4,782,969$. Dividing this by 143 gives $33447$ with a remainder of $48$.
The ciphertext became $C = 48$.&lt;/p>
&lt;p>&lt;strong>[Bob&amp;rsquo;s Decryption Phase]&lt;/strong>
Bob receives the ciphertext $C = 48$ and decrypts it using his private key $d = 103$.
Formula: $M \equiv 48^{103} \pmod{143}$
If you run &lt;code>(48 ** 103) % 143&lt;/code> on a calculator, the result wonderfully turns out to be &amp;ldquo;&lt;strong>9&lt;/strong>&amp;rdquo;! The original message was successfully received.&lt;/p>
&lt;hr>
&lt;h2 id="8-how-to-find-the-private-key-d-extended-euclidean-algorithm">8. How to Find the Private Key $d$: Extended Euclidean Algorithm
&lt;/h2>&lt;p>In the hand calculation example, we found $d=103$ by guessing to find $k$, but this method is impossible when the numbers are hundreds of digits long. In actual programs, an algorithm called the &lt;strong>&amp;ldquo;Extended Euclidean Algorithm&amp;rdquo;&lt;/strong> is used.&lt;/p>
&lt;p>Solving $7d \equiv 1 \pmod{120}$ is the same as finding integers $d, y$ that satisfy $7d + 120y = 1$. By working backwards through the Euclidean Algorithm, this can be calculated mechanically.&lt;/p>
&lt;ol>
&lt;li>$120 \div 7 = 17$ remainder $1$&lt;/li>
&lt;li>Transforming this, $1 = 120 - 17 \times 7$&lt;/li>
&lt;li>In other words, $-17 \times 7 \equiv 1 \pmod{120}$&lt;/li>
&lt;/ol>
&lt;p>In the world of modulo $120$, $-17$ has the same meaning as $120 - 17 = 103$. Therefore, $d = 103$ is found in an instant. This method can calculate very quickly no matter how huge the numbers are.&lt;/p>
&lt;hr>
&lt;h2 id="9-another-face-of-rsa-encryption-digital-signatures">9. Another Face of RSA Encryption: Digital Signatures
&lt;/h2>&lt;p>The wonderful thing about RSA encryption is that it can also be used as a &lt;strong>&amp;ldquo;digital signature&amp;rdquo;&lt;/strong> by reversing the roles of the public and private keys.&lt;/p>
&lt;p>When encrypting, it was &amp;ldquo;Encrypt with public key $\Rightarrow$ Decrypt with private key&amp;rdquo;, but
for digital signatures, it takes the steps &amp;ldquo;Encrypt with private key $\Rightarrow$ Decrypt with public key&amp;rdquo;.&lt;/p>
&lt;div class="mermaid">flowchart TD
A1["1. Alice creates a signature with her private key"] --> A2["S ≡ M^d (mod N)"]
A2 --> A3["Sends the message M and signature S"]
A3 --> B1["2. Bob verifies the signature with the public key"]
B1 --> B2["Calculates M' ≡ S^e (mod N)"]
B2 --> B3["Checks if M' matches M"]&lt;/div>
&lt;p>Alice transforms the message using her own private key $d$ (this is the signature $S$), and sends it to Bob. Bob performs the verification calculation using Alice&amp;rsquo;s public key $e$. If the calculation result matches the original message, it simultaneously proves that &amp;ldquo;it is data that could only be created with Alice&amp;rsquo;s private key&amp;rdquo; and that &amp;ldquo;the message has not been tampered with along the way&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="10-experiencing-rsa-encryption-with-programming">10. Experiencing RSA Encryption with Programming
&lt;/h2>&lt;p>Exponentiation calculations that are tough by hand can be implemented very easily using Python. Below is a Python code that lets you experience the core logic of RSA encryption.&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;Find the greatest common divisor&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;Find the private key d (using built-in feature in 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. Key Generation&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;Public Key: (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">), Private Key: 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. Encryption&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;Ciphertext: &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. Decryption&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;Decrypted Message: &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>Python&amp;rsquo;s &lt;code>pow(base, exp, mod)&lt;/code> function internally uses a fast algorithm called &amp;ldquo;Exponentiation by squaring&amp;rdquo;, so calculations finish in an instant even for numbers with hundreds of digits.&lt;/p>
&lt;hr>
&lt;h2 id="11-conclusion-and-future-cryptographic-technology">11. Conclusion and Future Cryptographic Technology
&lt;/h2>&lt;p>Based on the knowledge of high school mathematics, we have uncovered how RSA encryption works.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Difficulty of Prime Factorization:&lt;/strong> $p \times q = N$ is easy, but finding $p, q$ from $N$ is extremely difficult.&lt;/li>
&lt;li>&lt;strong>Congruence and Euler&amp;rsquo;s Theorem:&lt;/strong> With the rule $a^{\phi(N)} \equiv 1 \pmod N$, the magic trapdoor &amp;ldquo;raising to a certain power brings it back to the original&amp;rdquo; is completed.&lt;/li>
&lt;li>&lt;strong>Public and Private Keys:&lt;/strong> Anyone can encrypt, but only the legitimate receiver can decrypt.&lt;/li>
&lt;/ol>
&lt;p>The $N$ in currently used RSA encryption has over 600 digits, and even mobilizing all the supercomputers in the world, prime factorization would take more time than the age of the universe. However, when the &amp;ldquo;quantum computers&amp;rdquo; currently being researched become practical in the future, there is a possibility that this prime factorization will be solved in an instant by &amp;ldquo;Shor&amp;rsquo;s algorithm&amp;rdquo;. For this reason, the development of &amp;ldquo;Post-quantum cryptography&amp;rdquo; that cannot be cracked even by quantum computers is progressing rapidly worldwide.&lt;/p>
&lt;p>Advanced mathematics, which is often thought of as &amp;ldquo;useless,&amp;rdquo; is actually protecting our daily lives from the ground up. RSA encryption is the best teaching material to show us the depth and beauty of such mathematics. I hope this article has helped you feel the fascination of cryptography and mathematics, even just a little.&lt;/p></description></item><item><title>What is Fully Homomorphic Encryption (FHE)? Explaining the Keystone of Next-Generation Security</title><link>http://kenji.blog/en/p/fully-homomorphic-encryption-fhe-explained/</link><pubDate>Fri, 11 Sep 2026 11:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/fully-homomorphic-encryption-fhe-explained/</guid><description>&lt;img src="http://kenji.blog/p/fully-homomorphic-encryption-fhe-explained/img/eyecatch.jpg" alt="Featured image of post What is Fully Homomorphic Encryption (FHE)? Explaining the Keystone of Next-Generation Security" />&lt;p>As cloud computing and AI technologies become established as societal infrastructure, the tradeoff between &amp;ldquo;data privacy&amp;rdquo; and &amp;ldquo;data utilization&amp;rdquo; has become one of the most critical challenges. While there is a growing demand to have AI analyze highly sensitive data—such as medical records, financial information, and personal biometric data—on the cloud, many companies hesitate to send data externally due to security concerns.&lt;/p>
&lt;p>Traditional encryption technologies (like AES and RSA) excel at protecting data stored in storage (Data at Rest) and data flowing over networks (Data in Transit). However, &lt;strong>when performing processing (computations) such as searching or machine learning on the server side (Data in Use), the ciphertext must first be decrypted back into plaintext&lt;/strong>. If the server is hacked at this decrypted moment, or if a malicious internal administrator peeks at the data, it directly leads to information leakage.&lt;/p>
&lt;p>The dream technology that overcomes this fundamental weakness of &amp;ldquo;decryption during processing&amp;rdquo; is &lt;strong>Fully Homomorphic Encryption (FHE)&lt;/strong>. By using FHE, it becomes possible to perform computational processing while keeping the data encrypted, without ever decrypting it, and returning only the resulting ciphertext to the client.&lt;/p>
&lt;p>In this article, we will thoroughly and deeply explain FHE, the keystone of next-generation security, covering everything from its concept and history, the groundbreaking breakthrough by Craig Gentry, mathematical foundations (such as Ring-LWE), its biggest challenge &amp;ldquo;noise&amp;rdquo; and its solution (bootstrapping), up to the latest implementation libraries.&lt;/p>
&lt;hr>
&lt;h2 id="1-what-is-homomorphic-encryption-basic-concepts">1. What is Homomorphic Encryption? Basic Concepts
&lt;/h2>&lt;p>&amp;ldquo;Homomorphic&amp;rdquo; is an algebraic term referring to the property where mappings can be made between sets with a certain structure while preserving the structure of the operations. &amp;ldquo;Homomorphism&amp;rdquo; in cryptography is the property where &lt;strong>operations in the plaintext space correspond to operations in the ciphertext space&lt;/strong>.&lt;/p>
&lt;p>Expressed in simple formulas, let $m_1$ and $m_2$ be plaintexts, $E(\cdot)$ be the encryption function, and $D(\cdot)$ be the decryption function. If we let $\circ$ be an operation on the plaintext (such as addition or multiplication) and $\diamond$ be an operation on the ciphertext, the following relationship holds:&lt;/p>
$$ D(E(m_1) \diamond E(m_2)) = m_1 \circ m_2 $$
&lt;p>In other words, if you decrypt the result of applying some operation $\diamond$ to the ciphertexts $E(m_1)$ and $E(m_2)$, it matches the result of operating $\circ$ on the original plaintexts.&lt;/p>
&lt;h3 id="data-flow-in-cloud-computing">Data Flow in Cloud Computing
&lt;/h3>&lt;p>The architecture of cloud processing using FHE is completely different from traditional ones. The following diagram shows the flow of secure data processing utilizing FHE.&lt;/p>
&lt;div class="mermaid">graph TD
A["Client (Holds secret key)"] -->|1. Encrypt plaintext x: E(x)| B["Cloud Server (Encrypted data only)"]
B -->|2. Apply function f to ciphertext: E(f(x))| B
B -->|3. Ciphertext of calculation result E(y)| A
A -->|4. Decrypt with secret key: y = f(x)| A
style A fill:#d4edda,stroke:#28a745
style B fill:#f8d7da,stroke:#dc3545&lt;/div>
&lt;p>The server receives the encrypted data $E(x)$, but since it does not have the secret key, it can never know the contents of the data. However, by utilizing the properties of FHE, it can apply a function $f$ (for example, an inference model for machine learning) to the ciphertext and generate $E(f(x))$. The client receives this and decrypts it with their own secret key to obtain the desired result $y = f(x)$.&lt;/p>
&lt;hr>
&lt;h2 id="2-history-of-homomorphic-encryption-evolution-phe-she-fhe">2. History of Homomorphic Encryption Evolution: PHE, SHE, FHE
&lt;/h2>&lt;p>Homomorphic encryption did not reach its current &amp;ldquo;fully&amp;rdquo; form all at once. It is broadly classified into three stages depending on the types and number of operations it can achieve.&lt;/p>
&lt;h3 id="partially-homomorphic-encryption-phe">Partially Homomorphic Encryption (PHE)
&lt;/h3>&lt;p>PHE is an encryption scheme that can perform &lt;strong>only one of either&lt;/strong> addition or multiplication indefinitely. In fact, ciphers with this property have existed for a long time.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>RSA Encryption (Homomorphism for multiplication)&lt;/strong>
RSA encryption unintentionally possessed a multiplicative homomorphic property. Given plaintexts $m_1, m_2$ and a public key $(e, N)$:
$$ E(m_1) = m_1^e \pmod N $$
$$ E(m_2) = m_2^e \pmod N $$
Multiplying these gives:
$$ E(m_1) \times E(m_2) = (m_1 \cdot m_2)^e \pmod N = E(m_1 \times m_2) $$
Thus, the multiplication of ciphertexts corresponds to the multiplication of plaintexts.&lt;/li>
&lt;li>&lt;strong>Paillier Encryption (Homomorphism for addition)&lt;/strong>
The Paillier cryptosystem, invented in 1999, has an additive homomorphic property. It has been put to practical use in applications like electronic voting (aggregating encrypted votes and decrypting only the final result).&lt;/li>
&lt;/ul>
&lt;h3 id="somewhat-homomorphic-encryption-she">Somewhat Homomorphic Encryption (SHE)
&lt;/h3>&lt;p>This scheme can execute &lt;strong>both&lt;/strong> addition and multiplication, but there is a &lt;strong>limit to the number of operations (circuit depth)&lt;/strong> that can be performed. Due to the accumulation of &amp;ldquo;noise,&amp;rdquo; which will be discussed later, decryption becomes impossible after a certain number of multiplications. The BGN (Boneh-Goh-Nissim) cryptosystem of 2005 falls under this category, but it had limitations in performing practical, complex computations (like deep learning).&lt;/p>
&lt;h3 id="fully-homomorphic-encryption-fhe">Fully Homomorphic Encryption (FHE)
&lt;/h3>&lt;p>This is an encryption scheme that can execute both addition and multiplication an &lt;strong>unlimited number of times&lt;/strong>. Similar to Turing completeness in information theory, if addition (equivalent to XOR) and multiplication (equivalent to AND) can be combined infinitely, it means that in principle, any computable function or algorithm can be executed while remaining encrypted.&lt;/p>
&lt;p>FHE was long called the &amp;ldquo;holy grail of cryptography&amp;rdquo; and was even said to be impossible to realize. However, in 2009, &lt;strong>Craig Gentry&lt;/strong>, who was a doctoral student at Stanford University at the time, proposed the first FHE scheme using Ideal Lattices, sending shockwaves through the world.&lt;/p>
&lt;hr>
&lt;h2 id="3-mathematical-foundations-of-fhe-the-lwe-problem-and-ring-lwe">3. Mathematical Foundations of FHE: The LWE Problem and Ring-LWE
&lt;/h2>&lt;p>Many of the current mainstream FHE schemes are based on the &lt;strong>LWE (Learning With Errors) problem&lt;/strong>, a mathematical hard problem in &amp;ldquo;Lattice-based Cryptography,&amp;rdquo; which is also known as Post-Quantum Cryptography.&lt;/p>
&lt;h3 id="intuitive-understanding-of-the-lwe-problem">Intuitive Understanding of the LWE Problem
&lt;/h3>&lt;p>Solving a system of linear equations is easy if you use methods like Gaussian elimination.&lt;/p>
$$ \begin{cases} 3s_1 + 4s_2 + 2s_3 \equiv 12 \pmod{17} \\ 1s_1 + 9s_2 + 5s_3 \equiv 8 \pmod{17} \\ \vdots \end{cases} $$
&lt;p>However, what happens if we add a very small &amp;ldquo;random error (noise)&amp;rdquo; $e$ to the results of these equations?&lt;/p>
$$ \begin{cases} 3s_1 + 4s_2 + 2s_3 + e_1 \equiv 13 \pmod{17} \\ 1s_1 + 9s_2 + 5s_3 + e_2 \equiv 7 \pmod{17} \\ \vdots \end{cases} $$
&lt;p>With just the addition of this error $e$, the problem of finding the secret variable vector $\vec{s}$ transforms into an NP-hard problem that is difficult to decipher even using current supercomputers or quantum computers. This is the LWE problem.&lt;/p>
&lt;h3 id="ring-lwe-problem-rlwe">Ring-LWE Problem (RLWE)
&lt;/h3>&lt;p>The standard LWE problem involves matrix operations, which means the key size is extremely large (sometimes in gigabytes) and computational efficiency is poor. To solve this, the &lt;strong>Ring-LWE (RLWE) problem&lt;/strong>, which uses operations over polynomial rings, was introduced.&lt;/p>
&lt;p>In RLWE, elements belong to the polynomial ring $R_q = \mathbb{Z}_q[x] / (x^N + 1)$ (where $N$ is a power of 2, and $q$ is the modulus prime).
Let the secret key be a polynomial $s(x)$, and with a random polynomial $a(x)$ and a small noise polynomial $e(x)$, the public key becomes the following pair:&lt;/p>
$$ (a(x), b(x)) \quad \text{where} \quad b(x) = -a(x) \cdot s(x) + e(x) \pmod q $$
&lt;p>During encryption, the plaintext $m(x)$ is encoded using the properties of this polynomial to generate the ciphertext.&lt;/p>
&lt;hr>
&lt;h2 id="4-the-biggest-barrier-noise-and-gentrys-bootstrapping">4. The Biggest Barrier &amp;ldquo;Noise&amp;rdquo; and Gentry&amp;rsquo;s Bootstrapping
&lt;/h2>&lt;p>The most important concept in understanding FHE is &lt;strong>&amp;ldquo;noise management.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;p>In LWE/RLWE-based cryptography, small &amp;ldquo;noise (errors)&amp;rdquo; are intentionally included to ensure security.
The process of decrypting a ciphertext $c$ of a plaintext $m$ can be roughly represented by the following formula:&lt;/p>
$$ D(c) = (c \cdot s) \pmod q = m + \text{noise} $$
&lt;p>During decryption, this &lt;code>noise&lt;/code> is removed through rounding processes or similar to obtain the correct plaintext $m$. However, when homomorphic operations (especially multiplication) are performed between ciphertexts, this noise is dramatically amplified.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Homomorphic Addition&lt;/strong>: Noise increases additively ($e_1 + e_2$). This is a relatively gradual increase.&lt;/li>
&lt;li>&lt;strong>Mathematical Representation of Homomorphism by Homomorphic Addition&lt;/strong>:
$$ E(m_1) \oplus E(m_2) = E(m_1 + m_2) $$&lt;/li>
&lt;li>&lt;strong>Homomorphic Multiplication&lt;/strong>: Noise explodes multiplicatively (because it includes terms like $e_1 \times e_2$). After just a few multiplications, the noise exceeds the threshold $q/2$, preventing correct rounding and causing decryption to fail.&lt;/li>
&lt;li>&lt;strong>Mathematical Representation of Homomorphism by Homomorphic Multiplication&lt;/strong>:
$$ E(m_1) \otimes E(m_2) = E(m_1 \times m_2) $$&lt;/li>
&lt;/ul>
&lt;p>This is the reason why FHE could not be realized for a long time and remained at the level of SHE (with a limited number of operations).&lt;/p>
&lt;h3 id="the-magic-of-bootstrapping">The Magic of Bootstrapping
&lt;/h3>&lt;p>Craig Gentry&amp;rsquo;s genius contribution was inventing a noise reduction technique called &lt;strong>&amp;ldquo;bootstrapping.&amp;rdquo;&lt;/strong> This was a paradigm shift in cryptography.&lt;/p>
&lt;p>Intuitively, it is the operation of &amp;ldquo;&amp;lsquo;decrypting&amp;rsquo; the ciphertext to clean it while it remains encrypted, and putting it into a new ciphertext before it becomes too noisy and breaks.&amp;rdquo;&lt;/p>
&lt;ol>
&lt;li>Suppose we have a highly noisy ciphertext $C_{noisy}$.&lt;/li>
&lt;li>The client provides the server in advance with the secret key $sk$ &amp;ldquo;encrypted with the public key,&amp;rdquo; $E_{pk}(sk)$ (this is called the bootstrapping key).&lt;/li>
&lt;li>The server runs a &lt;strong>Decryption Circuit&lt;/strong> homomorphically on $C_{noisy}$.&lt;/li>
&lt;li>Specifically, it performs a &amp;ldquo;decryption within the encrypted space&amp;rdquo; on $E_{pk}(C_{noisy})$ using $E_{pk}(sk)$.&lt;/li>
&lt;li>Since this decryption circuit itself is a homomorphic operation, it generates new noise, but the noise of the newly output ciphertext $C_{fresh}$ is reset to a fixed &amp;ldquo;constant level.&amp;rdquo;&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph LR
A["High noise ciphertext C_noisy"] --> B["Homomorphic decryption circuit (Eval_Dec)"]
C["Encrypted secret key E(sk)"] --> B
B --> D["Low noise ciphertext C_fresh"]
style B fill:#ffeeba,stroke:#ffc107&lt;/div>
&lt;p>By executing this bootstrapping periodically during computation, it theoretically became possible to compute circuits of infinite depth (achieving FHE). However, Gentry&amp;rsquo;s early scheme was desperately expensive computationally, with a single bootstrapping operation taking anywhere from tens of minutes to hours.&lt;/p>
&lt;hr>
&lt;h2 id="5-generations-of-fhe-and-the-evolution-of-major-schemes">5. Generations of FHE and the Evolution of Major Schemes
&lt;/h2>&lt;p>In the race toward practical FHE, cryptographers around the world have competed to improve the algorithms. Currently, FHE is mainly classified into four generations or families.&lt;/p>
&lt;h3 id="2nd-generation-exact-integer-arithmetic-bgv-bfv">2nd Generation: Exact Integer Arithmetic (BGV, BFV)
&lt;/h3>&lt;p>The &lt;strong>BGV (Brakerski-Gentry-Vaikuntanathan)&lt;/strong> and &lt;strong>BFV (Brakerski/Fan-Vercauteren)&lt;/strong> schemes appeared between 2011 and 2012. These are based on RLWE and are suitable for integer modular arithmetic (exact calculations).
They support batching techniques like SIMD (Single Instruction, Multiple Data), characterized by the ability to pack thousands of data slots into a single large polynomial ciphertext and compute them in parallel all at once.&lt;/p>
&lt;h3 id="3rd-generation-accelerated-bootstrapping-gsw-fhew-tfhe">3rd Generation: Accelerated Bootstrapping (GSW, FHEW, TFHE)
&lt;/h3>&lt;p>The &lt;strong>GSW (Gentry-Sahai-Waters)&lt;/strong> scheme of 2013 made the structure of FHE simpler. This was developed further into &lt;strong>TFHE (Fast Fully Homomorphic Encryption over the Torus)&lt;/strong>, one of the mainstream schemes today.
The hallmark of TFHE is its extremely fast bootstrapping (on the order of milliseconds). It excels at gate-level operations (logic circuits like AND, XOR), and since the ciphertext size is relatively small, it is suited for fast evaluation of arbitrary logic circuits.&lt;/p>
&lt;h3 id="4th-generation-specialization-for-approximate-calculation-and-machine-learning-ckks">4th Generation: Specialization for Approximate Calculation and Machine Learning (CKKS)
&lt;/h3>&lt;p>The &lt;strong>CKKS (Cheon-Kim-Kim-Song)&lt;/strong> scheme proposed by Cheon et al. in 2017 can be called the definitive technology for privacy protection in current AI and machine learning.
While previous FHEs insisted on &amp;ldquo;exact integer calculations,&amp;rdquo; CKKS supports &lt;strong>&amp;ldquo;approximate calculations of floating-point numbers&amp;rdquo;&lt;/strong> while remaining encrypted. It demonstrates overwhelming performance in real number calculations where small errors are tolerable, such as the training and inference of neural networks.&lt;/p>
&lt;p>The table below summarizes how to choose a scheme by purpose.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Scheme Name&lt;/th>
&lt;th style="text-align:left">Preferred Data Type&lt;/th>
&lt;th style="text-align:left">Recommended Use Cases&lt;/th>
&lt;th style="text-align:left">Features&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>BFV / BGV&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Integer&lt;/td>
&lt;td style="text-align:left">Exact statistical calculations, financial data aggregation, DB queries&lt;/td>
&lt;td style="text-align:left">High throughput via SIMD batching&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>CKKS&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Real/Complex&lt;/td>
&lt;td style="text-align:left">Machine learning (DNN, logistic regression), signal processing&lt;/td>
&lt;td style="text-align:left">Acceleration via approximate calculation, rescaling&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>TFHE&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Boolean&lt;/td>
&lt;td style="text-align:left">Arbitrary logic circuits, string search, evaluation of non-linear functions&lt;/td>
&lt;td style="text-align:left">Ultra-fast bootstrapping (millisecond range)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="6-practice-fhe-libraries-and-conceptual-code">6. Practice: FHE Libraries and Conceptual Code
&lt;/h2>&lt;p>Today, many open-source libraries are provided that allow you to use FHE without deep cryptographic knowledge.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Microsoft SEAL (Simple Encrypted Arithmetic Library)&lt;/strong>: A C++ library supporting BFV, BGV, and CKKS. One of the industry standards. Its Python binding, &lt;strong>TenSEAL&lt;/strong>, is popular among AI engineers.&lt;/li>
&lt;li>&lt;strong>Zama (Concrete)&lt;/strong>: A framework based on TFHE. You can write in Rust/Python, and it provides functionality (Concrete ML) to compile existing PyTorch models and run them on FHE.&lt;/li>
&lt;li>&lt;strong>OpenFHE&lt;/strong>: The successor to PALISADE, a comprehensive C++ library supporting all major schemes.&lt;/li>
&lt;/ul>
&lt;h3 id="example-of-fhe-programming-using-python-tenseal">Example of FHE Programming using Python (TenSEAL)
&lt;/h3>&lt;p>Here, we show a conceptual Python code example using the CKKS scheme to add and multiply real number vectors while they remain encrypted.&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-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">tenseal&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">ts&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. Context setup (including key generation)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Use CKKS scheme, set polynomial degree to 8192&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">SCHEME_TYPE&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CKKS&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">poly_modulus_degree&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">8192&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">coeff_mod_bit_sizes&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">60&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">60&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="n">context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">generate_galois_keys&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">global_scale&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">40&lt;/span> &lt;span class="c1"># Scaling factor for real numbers&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. Client side: Data encryption&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">vector1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">1.5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">2.5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">3.5&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">vector2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">2.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">3.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">4.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"># Convert plaintext vectors to ciphertexts (should be executed on the client side)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_v1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ckks_vector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vector1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_v2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ckks_vector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">context&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">vector2&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. Server side: Computations while encrypted (Protection of Data in Use)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># The server does not know the plaintexts but can perform addition and multiplication&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_add&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_v1&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">enc_v2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">enc_mul&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_v1&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">enc_v2&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"># 4. Client side: Decryption of results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Only the client with the secret key can view the results&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">res_add&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_add&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decrypt&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">res_mul&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">enc_mul&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decrypt&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;Decrypted addition result: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">res_add&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="c1"># Example output: [3.5000001, 5.5000001, 7.5000002] (Includes minute errors due to approximate calculation)&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;Decrypted multiplication result: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">res_mul&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="c1"># Example output: [3.0000002, 7.5000005, 14.0000003]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>As you can see from the code above, you can intuitively describe computations between ciphertexts by overloading normal Python operators, such as &lt;code>enc_v1 + enc_v2&lt;/code>. On the server side, vector operations are completed without knowing the contents of the vectors.&lt;/p>
&lt;hr>
&lt;h2 id="7-fhe-challenges-performance-and-hardware-acceleration">7. FHE Challenges: Performance and Hardware Acceleration
&lt;/h2>&lt;p>While FHE provides theoretically perfect security, its biggest challenge for practical use is &lt;strong>&amp;ldquo;performance overhead.&amp;rdquo;&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Computational Overhead&lt;/strong>: Compared to computing in plaintext, computing in ciphertext is thousands to tens of thousands of times slower on a CPU. Polynomial multiplications and bootstrapping require massive amounts of FFT (Fast Fourier Transform) or NTT (Number Theoretic Transform) calculations.&lt;/li>
&lt;li>&lt;strong>Ciphertext Expansion&lt;/strong>: A few bytes of plaintext can expand to several megabytes when encrypted. This puts severe pressure on memory bandwidth and network bandwidth.&lt;/li>
&lt;/ol>
&lt;h3 id="approaches-to-hardware-solutions">Approaches to Hardware Solutions
&lt;/h3>&lt;p>To overcome this overhead, the development of dedicated FHE hardware accelerators (ASIC, FPGA, GPU support) is progressing worldwide.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>GPU Acceleration&lt;/strong>: Efforts are underway to parallelize NTT operations and bootstrapping using powerful GPUs from NVIDIA and others, with reports of speeds tens of times faster than software implementations (e.g., 100x.ai, Zama&amp;rsquo;s TFHE-rs CUDA backend).&lt;/li>
&lt;li>&lt;strong>DARPA DPRIVE Project&lt;/strong>: The US Defense Advanced Research Projects Agency (DARPA) is promoting the &amp;ldquo;DPRIVE (Data Protection in Virtual Environments)&amp;rdquo; project to develop dedicated hardware to bring the computational speed of FHE to parity with plaintext processing (within a 10x overhead). Intel, Microsoft, and Intellectual Ventures are participating.&lt;/li>
&lt;li>&lt;strong>Emergence of FPUs (FHE Processing Units)&lt;/strong>: Startups like Cornami and Optalysys are embarking on the development of FHE-specific chips using optical computing and specialized silicon architectures.&lt;/li>
&lt;/ul>
&lt;p>In the near future, an era may come where &amp;ldquo;FPUs&amp;rdquo; become a standard feature in server and cloud infrastructure, just like NPUs (Neural Processing Units) in AI.&lt;/p>
&lt;hr>
&lt;h2 id="8-expected-use-cases">8. Expected Use Cases
&lt;/h2>&lt;p>Now that FHE is approaching practical speeds, disruptive innovations are expected in areas such as:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Privacy Protection in Medical and Genomic Analysis&lt;/strong>:
By having a cloud AI learn from patients&amp;rsquo; medical records and DNA data held by multiple hospitals while keeping it encrypted with FHE, highly accurate cancer diagnostic models and new drug development can be performed without violating privacy laws (like HIPAA or GDPR).&lt;/li>
&lt;li>&lt;strong>Fraud Detection and Anti-Money Laundering (AML) for Financial Institutions&lt;/strong>:
Competing banks can cross-analyze data in an encrypted state to detect massive illegal money transfer networks, without revealing customer account information or transaction histories to each other.&lt;/li>
&lt;li>&lt;strong>Secure AI Inference APIs (MaaS: Model as a Service)&lt;/strong>:
Users encrypt their voice, facial images, and prompts before sending them to AI services (like LLMs such as ChatGPT). The AI provider generates the answer without ever knowing the user&amp;rsquo;s input and returns it as a ciphertext. This completely dispels the concern of &amp;ldquo;AI learning or peeking at personal information.&amp;rdquo;&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="9-conclusion-the-future-of-cryptography-is-unseen-computation">9. Conclusion: The Future of Cryptography is &amp;ldquo;Unseen Computation&amp;rdquo;
&lt;/h2>&lt;p>Just as the invention of public key cryptography (RSA) in the 1970s enabled secure communication on the Internet (such as HTTPS), Craig Gentry&amp;rsquo;s invention of FHE is one of the most important milestones in the history of cryptography.&lt;/p>
&lt;p>Today, Fully Homomorphic Encryption (FHE) has leapt from the theories of laboratories into the stage where Microsoft, IBM, Intel, Google, and many startups are fiercely competing toward practical application. While challenges regarding computational cost and data size still exist, thanks to the refinement of algorithms and the evolution of hardware accelerators, performance improvements continue at a pace exceeding Moore&amp;rsquo;s Law.&lt;/p>
&lt;p>In a few years, &amp;ldquo;computing data while keeping it encrypted&amp;rdquo; will not be something special, but will likely become the standard data protection best practice in cloud services. FHE is the keystone of next-generation security, realizing the &lt;strong>ultimate combination of privacy and data utilization&lt;/strong> in a data-driven society.&lt;/p></description></item><item><title>Mathematical Foundations of Elliptic Curve Cryptography (ECC) and Implementation in C++</title><link>http://kenji.blog/en/p/elliptic-curve-cryptography-math-cpp/</link><pubDate>Fri, 11 Sep 2026 10:00:00 +0900</pubDate><guid>http://kenji.blog/en/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 Mathematical Foundations of Elliptic Curve Cryptography (ECC) and Implementation in C++" />&lt;h1 id="mathematical-foundations-of-elliptic-curve-cryptography-ecc-and-implementation-in-c">Mathematical Foundations of Elliptic Curve Cryptography (ECC) and Implementation in C++
&lt;/h1>&lt;p>In modern cryptographic technology, &lt;strong>Elliptic Curve Cryptography (ECC)&lt;/strong> plays a tremendously important role. It is no exaggeration to say that the foundation of trust in our modern digital society—from everyday Internet communications (HTTPS/TLS) and smartphone secure enclaves, to server authentication via SSH, passwordless authentication like FIDO, and even crypto assets like Bitcoin and Ethereum—is supported by ECC.&lt;/p>
&lt;p>In this article, we will thoroughly explain how elliptic curve cryptography works, starting from the beautiful yet complex mathematical theory behind it (algebraic geometry over finite fields), to actual implementation methods in C++, and even secure coding techniques to prevent side-channel attacks (timing attacks), with an overwhelming volume of detail.&lt;/p>
&lt;hr>
&lt;h2 id="1-why-elliptic-curve-cryptography-comparison-with-rsa">1. Why Elliptic Curve Cryptography? (Comparison with RSA)
&lt;/h2>&lt;p>For a long time, &lt;strong>RSA cryptography&lt;/strong> was synonymous with public-key cryptography. The security of RSA relies on the &amp;ldquo;difficulty of factoring large composite numbers.&amp;rdquo; However, as the computational power of computers has increased, it has become necessary to continuously lengthen the RSA key size (number of modulus bits) to maintain security. Currently, a key size of at least 2048 bits is recommended, and 3072 or 4096 bits if greater security is desired.&lt;/p>
&lt;p>In contrast, Elliptic Curve Cryptography (ECC) bases its security on a different mathematical difficulty: the &lt;strong>&amp;ldquo;Elliptic Curve Discrete Logarithm Problem (ECDLP)&amp;rdquo;&lt;/strong>. To this day, no efficient algorithms (such as sub-exponential time algorithms) for solving the ECDLP have been discovered, and even the most efficient known attack methods require exponential time.&lt;/p>
&lt;p>Because of this property, ECC has the decisive advantage of being able to &lt;strong>achieve security strength equivalent to RSA with significantly shorter key lengths&lt;/strong>.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:center">Security Strength (bits)&lt;/th>
&lt;th style="text-align:center">RSA Key Length (bits)&lt;/th>
&lt;th style="text-align:center">ECC Key Length (bits)&lt;/th>
&lt;th style="text-align:center">Key Length Ratio&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>As shown in the table above, to achieve a security strength of 128 bits (currently a standard strength), RSA requires a 3072-bit key, whereas ECC requires only 256 bits. This reduces computational complexity, lowers memory usage, and saves network bandwidth, making ECC overwhelmingly superior, especially in resource-constrained IoT devices and smart card environments.&lt;/p>
&lt;hr>
&lt;h2 id="2-mathematical-preparation-the-world-of-group-theory-and-finite-fields">2. Mathematical Preparation: The World of Group Theory and Finite Fields
&lt;/h2>&lt;p>To truly understand elliptic curve cryptography, it is necessary to grasp the basic concepts of abstract algebra (group theory and field theory). Here, we briefly summarize the prerequisite knowledge for constructing ECC.&lt;/p>
&lt;h3 id="21-groups-and-abelian-groups">2.1. Groups and Abelian Groups
&lt;/h3>&lt;p>A &lt;strong>Group&lt;/strong> is a pair consisting of a set $G$ and a binary operation on that set (here we&amp;rsquo;ll use addition $+$), denoted as $(G, +)$, which satisfies the following four axioms:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Closure&lt;/strong>: For any $a, b \in G$, $a + b \in G$.&lt;/li>
&lt;li>&lt;strong>Associativity&lt;/strong>: For any $a, b, c \in G$, $(a + b) + c = a + (b + c)$.&lt;/li>
&lt;li>&lt;strong>Identity element&lt;/strong>: There exists an element $e \in G$ such that for any $a \in G$, $a + e = e + a = a$. For additive groups, this identity element is usually denoted as $0$ or $\mathcal{O}$.&lt;/li>
&lt;li>&lt;strong>Inverse element&lt;/strong>: For any $a \in G$, there exists an element $b \in G$ such that $a + b = b + a = e$. This $b$ is denoted as $-a$.&lt;/li>
&lt;/ol>
&lt;p>Furthermore, a group that satisfies the following condition, where the result does not change even if the order of the operation is swapped, is called an &lt;strong>Abelian group (commutative group)&lt;/strong>.&lt;/p>
&lt;ol start="5">
&lt;li>&lt;strong>Commutativity&lt;/strong>: For any $a, b \in G$, $a + b = b + a$.&lt;/li>
&lt;/ol>
&lt;p>The set of points on an elliptic curve, by defining a specific addition rule, constitutes this &lt;strong>Abelian group&lt;/strong>.&lt;/p>
&lt;h3 id="22-finite-fields">2.2. Finite Fields
&lt;/h3>&lt;p>In cryptography, we do not use fields with continuous and infinite elements like real or complex numbers, but rather &lt;strong>Finite Fields&lt;/strong> (or Galois Fields), which have a finite number of elements.&lt;/p>
&lt;p>The most basic finite field is the &lt;strong>prime field $\mathbb{F}_p$&lt;/strong> using a prime number $p$. This defines the four basic arithmetic operations (addition, subtraction, multiplication, division) modulo $p$ (the remainder when divided by $p$) on the set of integers $\{0, 1, 2, \dots, p-1\}$.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Addition&lt;/strong>: $(a + b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Subtraction&lt;/strong>: $(a - b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Multiplication&lt;/strong>: $(a \times b) \pmod p$&lt;/li>
&lt;li>&lt;strong>Division&lt;/strong>: $a \times b^{-1} \pmod p$ (where $b^{-1}$ is the modular multiplicative inverse of $b$ modulo $p$)&lt;/li>
&lt;/ul>
&lt;p>Calculating the &lt;strong>Modular Multiplicative Inverse&lt;/strong> is extremely important in cryptographic implementations. To find $b^{-1}$ satisfying $b \times b^{-1} \equiv 1 \pmod p$, the following two main algorithms are used:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Extended Euclidean Algorithm&lt;/strong>: Fast, but depending on the implementation, the processing time can depend on the input values, leading to a risk of timing attacks.&lt;/li>
&lt;li>&lt;strong>Fermat&amp;rsquo;s Little Theorem&lt;/strong>: When $p$ is prime and $b \neq 0$, $b^{p-1} \equiv 1 \pmod p$ holds. Dividing both sides by $b$ yields $b^{p-2} \equiv b^{-1} \pmod p$. That is, the inverse is found by raising $b$ to the power of $p-2$. Exponentiation is easier to implement in constant time, so this method is preferred in cryptographic implementations.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="3-elliptic-curve-equations-and-geometry">3. Elliptic Curve Equations and Geometry
&lt;/h2>&lt;h3 id="31-weierstrass-normal-form">3.1. Weierstrass Normal Form
&lt;/h3>&lt;p>An &lt;strong>Elliptic Curve&lt;/strong> is generally a plane curve defined by the following equation, known as the &lt;strong>Weierstrass normal form&lt;/strong>.&lt;/p>
$$ y^2 = x^3 + ax + b $$
&lt;p>Here, $a$ and $b$ are constants, and as a condition for the curve to have no singular points (self-intersections or cusps) (i.e., to be a smooth curve), the following &lt;strong>Discriminant $\Delta$&lt;/strong> must not be zero.&lt;/p>
$$ \Delta = -16(4a^3 + 27b^2) \neq 0 $$
&lt;p>Since curves with singular points compromise cryptographic security, coefficients $a, b$ that satisfy this condition are always chosen.&lt;/p>
&lt;h3 id="32-point-at-infinity">3.2. Point at Infinity
&lt;/h3>&lt;p>To make an elliptic curve a mathematically complete group, a virtual point called the &lt;strong>&amp;ldquo;Point at Infinity&amp;rdquo;&lt;/strong> is introduced in addition to the points on the plane. This is denoted as $\mathcal{O}$.&lt;/p>
&lt;p>The point at infinity $\mathcal{O}$ is defined as the point where all vertical lines intersect infinitely far away. In group theory, this point at infinity $\mathcal{O}$ functions as the &lt;strong>identity element&lt;/strong> (zero) for addition.&lt;/p>
&lt;p>In other words, for any point $P$ on the curve, the following holds:
&lt;/p>
$$ P + \mathcal{O} = \mathcal{O} + P = P $$
&lt;p>Also, the inverse $-P$ of point $P = (x, y)$ is defined as the point symmetrical with respect to the x-axis, $(x, -y)$. Therefore:
&lt;/p>
$$ P + (-P) = \mathcal{O} $$
&lt;p>
holds.&lt;/p>
&lt;hr>
&lt;h2 id="4-group-operations-on-elliptic-curves-point-addition-and-point-doubling">4. Group Operations on Elliptic Curves (Point Addition and Point Doubling)
&lt;/h2>&lt;p>The core of elliptic curve cryptography is the operation called &lt;strong>&amp;ldquo;Addition&amp;rdquo;&lt;/strong> between points on the curve. This is different from the addition of ordinary integers and is defined based on geometric operations.&lt;/p>
&lt;h3 id="41-geometric-addition-tangent-and-chord-method">4.1. Geometric Addition (Tangent and Chord Method)
&lt;/h3>&lt;p>The procedure for finding a new point $R$ ($R = P + Q$) by adding two distinct points $P$ and $Q$ on the curve is as follows:&lt;/p>
&lt;ol>
&lt;li>Draw a straight line (chord) connecting point $P$ and point $Q$.&lt;/li>
&lt;li>This straight line will definitely intersect the elliptic curve at a third point (let&amp;rsquo;s call it $-R$). (*Based on a theorem in algebraic geometry)&lt;/li>
&lt;li>The point $R$ we are looking for is the point obtained by reflecting the intersection point $-R$ symmetrically across the x-axis (the point with the inverted sign of the y-coordinate).&lt;/li>
&lt;/ol>
&lt;div class="mermaid">graph TD
Step1["Draw a line connecting P(x1, y1) and Q(x2, y2)"] --> Step2["Find the 3rd intersection -R with the curve"]
Step2 --> Step3["Reflect -R across the x-axis to get R(x3, y3)"]
Step3 -.-> Result["This is R = P + Q"]&lt;/div>
&lt;h3 id="42-point-doubling">4.2. Point Doubling
&lt;/h3>&lt;p>When adding the same point $P$ to point $P$ ($P + P = 2P$), we cannot draw a line connecting two points. In this case, we draw the &lt;strong>tangent line to the curve at point $P$&lt;/strong>.&lt;/p>
&lt;ol>
&lt;li>Draw the tangent line to the curve at point $P$.&lt;/li>
&lt;li>This tangent line intersects the curve at another point $-R$.&lt;/li>
&lt;li>The point $R = 2P$ we are looking for is obtained by reflecting the intersection symmetrically across the x-axis.&lt;/li>
&lt;/ol>
&lt;h3 id="43-algebraic-calculation-formulas">4.3. Algebraic Calculation Formulas
&lt;/h3>&lt;p>We translate the geometric operations into algebraic formulas so they can be computed by a computer.
All operations are performed &lt;strong>over the finite field $\mathbb{F}_p$ (modulo $p$)&lt;/strong>.&lt;/p>
&lt;p>Let point $P = (x_1, y_1)$ and point $Q = (x_2, y_2)$.
Also, let the resulting point be $R = P + Q = (x_3, y_3)$.&lt;/p>
&lt;p>Let the slope of the line be $\lambda$ (lambda).&lt;/p>
&lt;p>&lt;strong>[Case 1: When $P \neq Q$ (Point Addition)]&lt;/strong>
The slope $\lambda$ is the rate of change between the two points.
&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>Using this $\lambda$, $x_3, y_3$ are found as follows:
&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>[Case 2: When $P = Q$ (Point Doubling)]&lt;/strong>
The slope $\lambda$ becomes the slope of the tangent line obtained by differentiation. (We implicitly differentiate $y^2 = x^3 + ax + b$)
&lt;/p>
$$ 2y \cdot y' = 3x^2 + a \implies y' = \frac{3x^2 + a}{2y} $$
&lt;p>
Therefore,
&lt;/p>
$$ \lambda \equiv (3x_1^2 + a) \cdot (2y_1)^{-1} \pmod p $$
&lt;p>The formulas for $x_3, y_3$ take the same form as addition, but since $x_2 = x_1$, they are as follows:
&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]
These formulas include &lt;strong>division (calculation of modular inverses)&lt;/strong>, such as $(x_2 - x_1)^{-1}$ and $(2y_1)^{-1}$. Since calculating modular inverses incurs a very high computational cost, practical implementations generally use projective coordinate systems like &lt;strong>&amp;ldquo;Jacobian Coordinates&amp;rdquo;&lt;/strong>, which delay division.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="5-scalar-multiplication-and-the-elliptic-curve-discrete-logarithm-problem-ecdlp">5. Scalar Multiplication and the Elliptic Curve Discrete Logarithm Problem (ECDLP)
&lt;/h2>&lt;p>In elliptic curve cryptography, the operation that requires the most computation and forms the core of its security is &lt;strong>Scalar Multiplication&lt;/strong>.&lt;/p>
&lt;h3 id="51-what-is-scalar-multiplication">5.1. What is Scalar Multiplication?
&lt;/h3>&lt;p>The operation of adding a point $P$ to itself $k$ times is called scalar multiplication, denoted as $kP$.
&lt;/p>
$$ kP = \underbrace{P + P + \dots + P}_{k \text{ times}} $$
&lt;p>Here, $k$ is a very large integer (for example, a 256-bit integer).&lt;/p>
&lt;h3 id="52-elliptic-curve-discrete-logarithm-problem-ecdlp">5.2. Elliptic Curve Discrete Logarithm Problem (ECDLP)
&lt;/h3>&lt;p>The security of elliptic curve cryptography depends on the difficulty of the following problem.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>Elliptic Curve Discrete Logarithm Problem (ECDLP)&lt;/strong>
Given a known point $P$ (base point) and the resulting point $Q$, find the scalar $k$ that satisfies $Q = kP$.&lt;/p>
&lt;/blockquote>
&lt;p>Calculating $Q$ from $k$ and $P$ (forward direction) is easy (polynomial time) using the algorithm described below, but inversely calculating $k$ from $P$ and $Q$ (reverse direction) is practically impossible as there is no efficient solution other than exhaustive search (a one-way function).
In cryptographic protocols, &lt;strong>$k$ corresponds to the &amp;ldquo;private key&amp;rdquo; and $Q$ to the &amp;ldquo;public key&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="53-double-and-add-algorithm">5.3. Double-and-Add Algorithm
&lt;/h3>&lt;p>When $k$ is a huge number (e.g., $2^{256}$), naively adding $P$ for $k$ times will not finish even if the life of the universe ends. Therefore, to perform scalar multiplication quickly, the &lt;strong>Double-and-Add method (binary method)&lt;/strong> is used.&lt;/p>
&lt;p>This is the elliptic curve version of the &amp;ldquo;exponentiation by squaring&amp;rdquo; method used for rapid calculation of integer powers. The scalar $k$ is represented in binary, and processed sequentially starting from the most significant bit.&lt;/p>
&lt;ol>
&lt;li>Initialize the point $R$ holding the result to $\mathcal{O}$.&lt;/li>
&lt;li>Repeat the following from the most significant bit to the least significant bit of $k$:
&lt;ul>
&lt;li>Double $R$ (Point Doubling: $R = 2R$)&lt;/li>
&lt;li>If the current bit is &lt;code>1&lt;/code>, add $P$ to $R$ (Point Addition: $R = R + P$)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>With this algorithm, the computational complexity is dramatically reduced from $O(k)$ to $O(\log_2 k)$, enabling calculation in a realistic amount of time (milliseconds).&lt;/p>
&lt;hr>
&lt;h2 id="6-elliptic-curve-diffie-hellman-ecdh-key-exchange">6. Elliptic Curve Diffie-Hellman (ECDH) Key Exchange
&lt;/h2>&lt;p>Here, we explain the mechanics of the &lt;strong>ECDH (Elliptic Curve Diffie-Hellman) key exchange protocol&lt;/strong>, which is the most representative application of ECC. ECDH is a mechanism for Alice and Bob to securely generate and share a common secret key (session key) over a communication channel that could be wiretapped (it is the core of the TLS handshake).&lt;/p>
&lt;p>&lt;strong>[Prerequisite Parameters (Domain Parameters)]&lt;/strong>
Both parties share the elliptic curve $E$, a prime number $p$, and a base point $G$ to be used beforehand. (e.g., NIST P-256 or secp256k1)&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Alice as "Alice"
participant Bob as "Bob"
Note over Alice,Bob: "Public parameters: Curve E, Base point G, Prime p"
Alice->>Alice: "Generate private key d_A (random integer)"
Alice->>Alice: "Calculate public key Q_A = d_A * G"
Bob->>Bob: "Generate private key d_B (random integer)"
Bob->>Bob: "Calculate public key Q_B = d_B * G"
Alice->>Bob: "Send public key Q_A (plaintext)"
Bob->>Alice: "Send public key Q_B (plaintext)"
Alice->>Alice: "Calculate shared secret S = d_A * Q_B"
Bob->>Bob: "Calculate shared secret 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: "Both parties' calculation results S perfectly match!"&lt;/div>
&lt;p>An eavesdropper (Eve) can intercept $G$, $Q_A$, and $Q_B$ flowing over the communication path, but due to the difficulty of the ECDLP, she cannot determine Alice&amp;rsquo;s private key $d_A$ from $Q_A = d_A \cdot G$. Also, even if she multiplies $Q_A$ and $Q_B$, it will not result in the shared key $S$, so the eavesdropper cannot calculate $S$.&lt;/p>
&lt;hr>
&lt;h2 id="7-implementation-pitfalls-side-channel-attacks-and-countermeasures">7. Implementation Pitfalls: Side-Channel Attacks and Countermeasures
&lt;/h2>&lt;p>Even a theoretically perfect cryptographic algorithm can harbor vulnerabilities introduced during the process of implementing it as a program. This is known as a &lt;strong>&amp;ldquo;Side-Channel Attack&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;h3 id="71-timing-attack">7.1. Timing Attack
&lt;/h3>&lt;p>Let&amp;rsquo;s look back at the Double-and-Add algorithm mentioned earlier.&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">// Vulnerable pseudo-code for 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">// Always executed
&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">// Executed ONLY when bit is 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>This implementation has a fatal flaw. Because Point Addition is executed when the bit is &lt;code>1&lt;/code>, the calculation time is &lt;strong>slightly longer&lt;/strong> than when the bit is &lt;code>0&lt;/code>. Also, the behavior of the processor&amp;rsquo;s branch prediction and cache memory will change.
By statistically observing this minute difference in calculation time (or power consumption) thousands of times, an attacker can &lt;strong>completely recover the bit sequence of the private key $k$, one bit at a time&lt;/strong>. This is a timing attack.&lt;/p>
&lt;h3 id="72-constant-time-implementation-montgomery-ladder">7.2. Constant-Time Implementation: Montgomery Ladder
&lt;/h3>&lt;p>To prevent timing attacks, it is necessary to adopt algorithms where &lt;strong>the sequence of executed instructions and the calculation time are always constant (Constant-Time), regardless of the bit values of the private key&lt;/strong>.&lt;/p>
&lt;p>A representative example of this is the &lt;strong>Montgomery Ladder&lt;/strong>.&lt;/p>
&lt;div class="mermaid">graph TD
Start["Initialization: R0 = O, R1 = P"] --> LoopStart["For each bit i (from MSB)"]
LoopStart --> Cond{"Value of 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["Next bit"]
Branch1 --> LoopEnd
LoopEnd --> LoopStart
LoopStart -.->|"All bits processed"| End["End: R0 is the result (kP)"]&lt;/div>
&lt;p>The beauty of the Montgomery Ladder is that whether the bit is &lt;code>0&lt;/code> or &lt;code>1&lt;/code>, &lt;strong>&amp;ldquo;exactly one Point Addition and one Point Doubling&amp;rdquo;&lt;/strong> are always executed. This completely eliminates the data dependency of the computation time.&lt;/p>
&lt;p>However, if a branch (&lt;code>if (k_i == 0)&lt;/code>) itself exists, the risk of execution time fluctuating due to compiler optimization and CPU branch prediction remains. Therefore, in actual Constant-Time implementations, conditional branches (&lt;code>if&lt;/code> statements) are eliminated, and a &lt;strong>Conditional Swap using bitwise operations&lt;/strong> is utilized.&lt;/p>
&lt;hr>
&lt;h2 id="8-implementation-of-elliptic-curve-cryptography-in-c">8. Implementation of Elliptic Curve Cryptography in C++
&lt;/h2>&lt;p>From here, we will translate the theory into C++ code. While practical cryptographic libraries (like OpenSSL or libsodium) use highly advanced assembly optimizations and Jacobian coordinates, we present the skeleton of an &lt;strong>easy-to-understand Constant-Time implementation using affine coordinates&lt;/strong> to deepen mathematical understanding.&lt;/p>
&lt;p>We assume the use of &lt;code>boost::multiprecision::cpp_int&lt;/code> for operations on huge integers.&lt;/p>
&lt;h3 id="81-modular-arithmetic-and-inverses">8.1. Modular Arithmetic and Inverses
&lt;/h3>&lt;p>First, we define helper functions for operations over finite fields. We implement inverse calculation using Fermat&amp;rsquo;s Little Theorem.&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">// Prime p and parameters for secp256k1 as an example
&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">// Modulo operation returning a positive remainder
&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">// Modular exponentiation (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">// Modular inverse using Fermat&amp;#39;s Little Theorem
&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">// Assuming m is prime: 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-point-representation-and-group-operations-additiondoubling">8.2. Point Representation and Group Operations (Addition/Doubling)
&lt;/h3>&lt;p>We implement the &lt;code>Point&lt;/code> structure, which manages the point at infinity with a flag, and the addition formulas.&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">// Creation of the point at infinity
&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">// Creation of a normal point
&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">// Addition of points on the elliptic curve (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) = Point at infinity
&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 (when 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 (when 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-implementation-of-constant-time-conditional-swap">8.3. Implementation of Constant-Time Conditional Swap
&lt;/h3>&lt;p>When swapping the contents of variables based on the bit value of the private key, we use only bitwise operations (masks) without using an &lt;code>if&lt;/code> statement. This ensures the execution path is completely constant.&lt;/p>
&lt;blockquote>
&lt;p>[!TIP]
In an actual implementation, dynamically allocated multiple-precision integer classes like &lt;code>cpp_int&lt;/code> are not suitable for Constant-Time processing. This is because timing information leaks due to variations in memory allocation and array sizes. Practical libraries represent them with fixed lengths (for example, an array of 4 uint64_t elements) and implement bit-level masking. The following is a conceptual example.&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">// Conceptual Constant-Time Swap (assuming fixed-length integers)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// If bit is 1, swap P1 and P2; if 0, do not swap
&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 is 0 or 1. Mask is all 1s (0xFF..) if bit=1, all 0s if 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">// (Here we assume each word of a fixed-length BigInt class is w for explanation)
&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"> // Process y-coordinate and isInfinity flag similarly
&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">// * Perfect constant-time swapping is difficult with 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">// so here we limit it to simulating with a branch for the sake of understanding the logic.
&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-scalar-multiplication-using-the-montgomery-ladder">8.4. Scalar Multiplication using the Montgomery Ladder
&lt;/h3>&lt;p>We combine the aforementioned &lt;code>pointAdd&lt;/code> and &lt;code>cswap&lt;/code> to implement secure scalar multiplication.&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">// Scalar multiplication k * P (Montgomery Ladder method)
&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">// Point at infinity
&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">// Get the bit length of k (256 bits for 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">// Get the value of the i-th bit (0 or 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">// Swap R0 and R1 if 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="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">// Always execute the same operations (Point Addition and 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">// Swap back to restore state if 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="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>With this implementation logic, whether each bit of the scalar $k$ is &lt;code>0&lt;/code> or &lt;code>1&lt;/code>, the operations executed within each loop iteration (&lt;code>cswap&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>pointAdd&lt;/code> $\to$ &lt;code>cswap&lt;/code>) follow the exact same flow. This powerfully prevents the leakage of secret information through differences in timing or cache access patterns.&lt;/p>
&lt;hr>
&lt;h2 id="9-conclusion">9. Conclusion
&lt;/h2>&lt;p>At first glance, Elliptic Curve Cryptography (ECC) might seem puzzling: &amp;ldquo;Why does a geometric operation like drawing a line and reflecting the intersection point become cryptography?&amp;rdquo; However, by mapping it to the discrete world of finite fields, an excellent one-way function (the discrete logarithm problem) can be constructed, making it a product of the miraculous fusion of mathematics and cryptography.&lt;/p>
&lt;p>In this article, we covered the following key points:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Superiority over RSA&lt;/strong>: Provides strong security with very short key lengths, making it ideal for the modern mobile and IoT era.&lt;/li>
&lt;li>&lt;strong>Basics of Group Theory and Finite Fields&lt;/strong>: The mathematical structure that forms the foundation of ECC.&lt;/li>
&lt;li>&lt;strong>Addition and Doubling Formulas&lt;/strong>: Implementation methods of algebraic group operations using Weierstrass equations.&lt;/li>
&lt;li>&lt;strong>Threat of Side-Channel Attacks&lt;/strong>: Conditional branches dependent on private key bits create fatal vulnerabilities.&lt;/li>
&lt;li>&lt;strong>Constant-Time Implementation&lt;/strong>: C++ coding techniques that uniformize hardware-level behavior using the Montgomery Ladder and Conditional Swap to prevent attacks.&lt;/li>
&lt;/ol>
&lt;p>Writing your own cryptographic library to run in a production environment is highly discouraged (&amp;ldquo;Don&amp;rsquo;t roll your own crypto&amp;rdquo;) because the security risks are extremely high. However, deeply understanding the underlying algorithms and mathematical background should serve as an invaluable and powerful weapon for engineers designing and operating more secure and performant systems.&lt;/p>
&lt;p>In the next article, we would like to dig even deeper into the mechanics of the &lt;strong>ECDSA (Elliptic Curve Digital Signature Algorithm)&lt;/strong>, which is a digital signature algorithm using these elliptic curves, as well as &lt;strong>Schnorr signatures&lt;/strong>, which are adopted in Bitcoin.&lt;/p></description></item><item><title>Is There an Algorithm Beyond GNFS (General Number Field Sieve)?</title><link>http://kenji.blog/en/p/beyond-gnfs-integer-factorization-algorithms/</link><pubDate>Fri, 11 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/beyond-gnfs-integer-factorization-algorithms/</guid><description>&lt;img src="http://kenji.blog/p/beyond-gnfs-integer-factorization-algorithms/img/eyecatch.jpg" alt="Featured image of post Is There an Algorithm Beyond GNFS (General Number Field Sieve)?" />&lt;h2 id="1-introduction-integer-factorization-and-the-foundation-of-modern-cryptography">1. Introduction: Integer Factorization and the Foundation of Modern Cryptography
&lt;/h2>&lt;p>The security of internet communication in modern society heavily relies on the security of the RSA cryptosystem, a public-key encryption. And the security of RSA is based on the mathematical assumption of &amp;ldquo;the difficulty of factoring huge composite numbers&amp;rdquo;. If an extremely efficient integer factorization algorithm were discovered, the world&amp;rsquo;s communication infrastructure would collapse from its foundation.&lt;/p>
&lt;p>Currently, the &lt;strong>General Number Field Sieve (GNFS)&lt;/strong> reigns as the fastest and strongest algorithm for factoring huge integers using classical computers. GNFS was born as an extension of the Special Number Field Sieve (SNFS) proposed in the late 1980s, and to this day, it has established factorization records for huge composite numbers such as RSA-768 and RSA-250.&lt;/p>
&lt;p>However, cryptographers and mathematicians always harbor the following questions: &amp;ldquo;Is there a classical algorithm that surpasses GNFS?&amp;rdquo; &amp;ldquo;Where are the limits of classical computers?&amp;rdquo; And, &amp;ldquo;How will quantum computers break through this situation?&amp;rdquo;&lt;/p>
&lt;p>In this article, we thoroughly dissect the profound mathematical structures behind GNFS and conduct a detailed technical analysis of polynomial selection, the sieving phase, and the linear algebra step using the block Wiedemann method. Furthermore, we consider extension methods of GNFS such as Coppersmith&amp;rsquo;s improvements, and compare and explain the decisive differences between classical sub-exponential time algorithms and quantum polynomial time algorithms from a mathematical perspective.&lt;/p>
&lt;hr>
&lt;h2 id="2-asymptotic-complexity-and-l-notation">2. Asymptotic Complexity and L-notation
&lt;/h2>&lt;p>When evaluating the computational complexity of integer factorization algorithms, instead of standard polynomial time notation (such as $O(n^k)$), &lt;strong>L-notation&lt;/strong> is used to express the sub-exponential time relative to the number of digits of the input $n$. L-notation is defined as follows:&lt;/p>
$$
L_n[\alpha, c] = \exp \left( (c + o(1)) (\ln n)^\alpha (\ln \ln n)^{1-\alpha} \right)
$$
&lt;p>Here, $n$ is the integer to be factored, and $\ln n$ is the natural logarithm, which is proportional to the bit length of $n$.&lt;/p>
&lt;ul>
&lt;li>When $\alpha = 0$: $L_n[0, c] = \exp(c \ln \ln n) = (\ln n)^c$, representing &lt;strong>polynomial time&lt;/strong> relative to the bit length.&lt;/li>
&lt;li>When $\alpha = 1$: $L_n[1, c] = \exp(c \ln n) = n^c$, representing &lt;strong>exponential time&lt;/strong> relative to the bit length.&lt;/li>
&lt;li>When $0 &lt; \alpha &lt; 1$: It becomes &lt;strong>sub-exponential time&lt;/strong>, positioned between polynomial time and exponential time.&lt;/li>
&lt;/ul>
&lt;p>The history of the evolution of past integer factorization algorithms has also been a history of gradually reducing this value of $\alpha$.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Continued Fraction Factorization (CFRAC) and Multiple Polynomial Quadratic Sieve (MPQS)&lt;/strong>: Belong to the class of $\alpha = 1/2$, with a complexity of around $L_n[1/2, 1]$.&lt;/li>
&lt;li>&lt;strong>General Number Field Sieve (GNFS)&lt;/strong>: Achieved $\alpha = 1/3$, boasting a complexity of $L_n[1/3, (64/9)^{1/3}]$, the fastest among currently known classical algorithms.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="3-the-full-picture-and-mathematical-structure-of-the-gnfs-algorithm">3. The Full Picture and Mathematical Structure of the GNFS Algorithm
&lt;/h2>&lt;p>GNFS has a very complex and advanced mathematical foundation. The basic idea is an extension of Fermat&amp;rsquo;s Little Theorem and the Quadratic Sieve (QS), finding a non-trivial pair $(X, Y)$ that satisfies the congruence $X^2 \equiv Y^2 \pmod n$ and $X \not\equiv \pm Y \pmod n$, thereby deriving the factor $\gcd(X-Y, n)$ of $n$.&lt;/p>
&lt;p>However, the essence of GNFS is that it does not do this only in the rational number field $\mathbb{Q}$, but simultaneously searches for &amp;ldquo;smooth numbers&amp;rdquo; in both an extension field called an Algebraic Number Field $\mathbb{Q}(\alpha)$ and the rational number field, building congruence relations through homomorphisms.&lt;/p>
&lt;p>The GNFS process is broadly divided into five phases.&lt;/p>
&lt;div class="mermaid">graph TD
A["Integer Factorization Problem (Input n)"] --> B["1. Polynomial Selection"]
B --> C["2. Sieving Phase"]
C --> D["3. Filtering Phase"]
D --> E["4. Linear Algebra Phase"]
E --> F["5. Square Root Phase"]
F --> G["Output prime factors p, q"]&lt;/div>
&lt;h3 id="31-phase-1-polynomial-selection">3.1 Phase 1: Polynomial Selection
&lt;/h3>&lt;p>The success of GNFS heavily depends on the selection of appropriate polynomials. The goal is to find two irreducible polynomials $f_1(x)$ (rational side) and $f_2(x)$ (algebraic side) that share a common root $m$. That is, it satisfies:
$f_1(m) \equiv f_2(m) \equiv 0 \pmod n$&lt;/p>
&lt;p>Usually, a polynomial of degree 1 is chosen for the rational side, $f_1(x) = x - m$, and a monic polynomial of degree $d$ (typically 5 or 6) is chosen for the algebraic side, $f_2(x)$. The most classical approach is the &lt;strong>Base-$m$ method&lt;/strong>.
Choose an integer $m = \lfloor n^{1/(d+1)} \rfloor$ close to the $1/(d+1)$ power of $n$, and expand $n$ in base $m$.
$n = c_d m^d + c_{d-1} m^{d-1} + \dots + c_1 m + c_0$
This gives the polynomial $f_2(x) = c_d x^d + c_{d-1} x^{d-1} + \dots + c_0$. Obviously, $f_2(m) = n \equiv 0 \pmod n$.&lt;/p>
&lt;p>However, in modern implementations, &lt;strong>Kleinjung&amp;rsquo;s algorithm&lt;/strong> is used. This optimizes algebraic properties (Murphy&amp;rsquo;s $E$ value and $\alpha$-value) while preventing the coefficients of the polynomial from becoming extremely large (optimizing skewness), exploring polynomials that are likely to generate smooth numbers during the sieving phase. A massive amount of computational resources is invested in this step alone.&lt;/p>
&lt;h3 id="32-phase-2-sieving-phase">3.2 Phase 2: Sieving Phase
&lt;/h3>&lt;p>Once the polynomials are determined, the algorithm enters the &amp;ldquo;Sieving&amp;rdquo; phase, which has the highest computational load. Here, we search for pairs $(a, b)$. This pair is coprime, and the following two values are simultaneously required to be &amp;ldquo;smooth&amp;rdquo;.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Norm on the rational side&lt;/strong>: $F_1(a, b) = b \cdot f_1(a/b) = a - bm$&lt;/li>
&lt;li>&lt;strong>Norm on the algebraic side&lt;/strong>: $F_2(a, b) = b^d \cdot f_2(a/b)$&lt;/li>
&lt;/ol>
&lt;p>&amp;ldquo;Smooth&amp;rdquo; means that it can be factored only by primes up to a specified limit (Sieve bound). A prime base (Factor base) for the rational side and a prime base for the algebraic side are prepared, and smooth numbers are efficiently found over a huge search space using an approach similar to the Sieve of Eratosthenes.
Currently, a method called &lt;strong>Lattice Sieving&lt;/strong> is mainstream. By fixing a specific prime $q$ and sieving only the $(a, b)$ pairs on a sublattice where both the rational side and the algebraic side become multiples of $q$, extremely high efficiency is realized.&lt;/p>
&lt;h3 id="33-phase-3-filtering-phase">3.3 Phase 3: Filtering Phase
&lt;/h3>&lt;p>The number of smooth relations found in the sieving phase reaches hundreds of millions to billions. However, these also contain a lot of useless information.
The purpose of filtering is to construct a huge sparse matrix while reducing its dimensions as much as possible.&lt;/p>
&lt;p>Specifically, operations such as the following are performed.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Singleton removal&lt;/strong>: Remove relations that contain a prime factor that appears only once.&lt;/li>
&lt;li>&lt;strong>Clique removal / Merging&lt;/strong>: Multiply relations that share prime factors appearing two or more times, eliminating variables and reducing to a denser but smaller-dimensional system of equations.&lt;/li>
&lt;/ul>
&lt;p>As a result, a matrix with billions of rows is compressed into a huge sparse matrix $\mathbf{A}$ with tens of millions of rows (elements are 0 and 1 over the field $\mathbb{F}_2$).&lt;/p>
&lt;h3 id="34-phase-4-linear-algebra-phase">3.4 Phase 4: Linear Algebra Phase
&lt;/h3>&lt;p>Here, we find a non-trivial solution vector $\mathbf{x}$ for the equation $\mathbf{A} \mathbf{x} \equiv \mathbf{0} \pmod 2$. In other words, this is the problem of finding the left nullspace of a huge sparse matrix.&lt;/p>
&lt;p>Because the matrix size is extremely large, normal Gaussian elimination ($O(N^3)$) is completely impossible to compute. Therefore, an iterative method, a type of Krylov subspace method, is used. Historically, the &lt;strong>Block Lanczos method&lt;/strong> has been used, but in modern distributed computing environments, the &lt;strong>Block Wiedemann Algorithm&lt;/strong>, which can dramatically reduce communication overhead, is mainstream.&lt;/p>
&lt;p>The Block Wiedemann method calculates the minimal polynomial from the matrix $\mathbf{A}$ and a sequence of vectors, and constructs the basis of the nullspace using the Berlekamp-Massey algorithm. This step is extremely difficult to parallelize, and is one of the biggest bottlenecks of GNFS, requiring a tightly coupled communication network of supercomputers or large-scale clusters.&lt;/p>
&lt;h3 id="35-phase-5-square-root-phase">3.5 Phase 5: Square Root Phase
&lt;/h3>&lt;p>From the solution of linear algebra, a product that becomes a &amp;ldquo;perfect square&amp;rdquo; is constructed on each of the rational and algebraic sides.
On the rational side, $\prod (a-bm)$ becomes the square $X^2$ of some integer $X$, and on the algebraic side, the corresponding product of ideals becomes a perfect square $\gamma^2$ over the algebraic field.
By computing this $\gamma$ over the algebraic field and applying the homomorphism $\phi: \alpha \mapsto m \pmod n$ to the ring of rational integers, the congruence:
$X^2 \equiv \phi(\gamma)^2 \equiv Y^2 \pmod n$
is obtained.&lt;/p>
&lt;p>Computing the square root over the algebraic field requires deep knowledge of algebraic number theory, using complex algorithms such as &lt;strong>Montgomery&amp;rsquo;s Method&lt;/strong>. Finally, $\gcd(X-Y, n)$ is calculated, and if a non-trivial factor is obtained, the factorization is complete.&lt;/p>
&lt;hr>
&lt;h2 id="4-are-there-classical-algorithms-beyond-gnfs">4. Are There Classical Algorithms Beyond GNFS?
&lt;/h2>&lt;p>To date, no classical algorithm has been discovered whose asymptotic complexity falls below $L_n[1/3, c]$ for the factorization of general integers. However, there are some attempts and derivative algorithms to break through theoretical and practical limits.&lt;/p>
&lt;h3 id="41-multiple-number-field-sieve-mnfs">4.1 Multiple Number Field Sieve (MNFS)
&lt;/h3>&lt;p>As an approach extending GNFS, there is the &lt;strong>Multiple Number Field Sieve (MNFS)&lt;/strong> by D. Coppersmith. While GNFS uses two polynomials (rational side and algebraic side), MNFS uses multiple different algebraic side polynomials simultaneously for a single rational side polynomial.&lt;/p>
$$ f_1(x), f_{2,1}(x), f_{2,2}(x), \dots, f_{2,V}(x) $$
&lt;p>By utilizing multiple algebraic fields, the probability of &amp;ldquo;becoming smooth in any of the algebraic fields&amp;rdquo; can be dramatically increased in each sieving step. Coppersmith succeeded in slightly reducing the constant $c$ in the complexity $L_n[1/3, c]$ through this approach.
Specifically, while the constant of GNFS is $c = (64/9)^{1/3} \approx 1.923$, it has been theoretically shown that optimizing MNFS can reduce the complexity to about $c \approx 1.902$.
However, in practice, the overhead of managing multiple fields is large, and it has not yet led to a decisive breakthrough for RSA moduli on a practical scale.&lt;/p>
&lt;h3 id="42-is-an-l_n14-class-algorithm-possible">4.2 Is an $L_n[1/4]$ Class Algorithm Possible?
&lt;/h3>&lt;p>Regarding the limits of classical integer factorization algorithms, a theme that has been debated among mathematicians for many years is the question, &amp;ldquo;Does an algorithm with an exponent $\alpha = 1/4$ exist?&amp;rdquo;
Current GNFS and its derivatives are strongly bound to the framework of &amp;ldquo;searching for smoothness&amp;rdquo; by sieving, and within this paradigm, it is widely believed that $\alpha = 1/3$ is the limit. Even from the analysis of the distribution probability of smooth integers using the Dickman function, it is thought that with the current combination of algebraic field construction methods and sieves, the barrier of $O(L_n[1/3])$ cannot be crossed no matter how much it is optimized.&lt;/p>
&lt;p>If an $L_n[1/4]$ or even a classical polynomial-time algorithm were to exist, it would have to rely on entirely new mathematical structures that humanity currently cannot conceive of (for example, a more advanced algebraic geometry approach like Schoof&amp;rsquo;s algorithm for elliptic curve cryptography), completely different from the &amp;ldquo;smoothness-based&amp;rdquo; approach like GNFS. However, there are no signs of such at present.&lt;/p>
&lt;hr>
&lt;h2 id="5-breakthrough-by-quantum-computers-shors-algorithm">5. Breakthrough by Quantum Computers: Shor&amp;rsquo;s Algorithm
&lt;/h2>&lt;p>While classical computers face the barrier of $L_n[1/3]$, &lt;strong>Shor&amp;rsquo;s Algorithm&lt;/strong>, published by Peter Shor in 1994, smashed this barrier by fundamentally changing the computation model itself.&lt;/p>
&lt;h3 id="51-the-impact-of-quantum-polynomial-time">5.1 The Impact of Quantum Polynomial Time
&lt;/h3>&lt;p>Shor&amp;rsquo;s algorithm reduces the integer factorization problem to the &amp;ldquo;Order Finding Problem&amp;rdquo;. For a certain integer $a$, it is the problem of finding the period (order) $r$ of the function $f(x) = a^x \pmod n$.
While classical computers require exponential time to find this period, by using &lt;strong>Quantum Phase Estimation (QPE)&lt;/strong> and the &lt;strong>Quantum Fourier Transform (QFT)&lt;/strong> on a quantum computer, it is possible to evaluate all superpositions of states in parallel and extract the period $r$ with high probability.&lt;/p>
&lt;p>In terms of computational complexity, the execution time of Shor&amp;rsquo;s algorithm is &lt;strong>quantum polynomial time&lt;/strong>, specifically as follows:
&lt;/p>
$$ O((\log n)^3) $$
&lt;p>
Considering recent optimized circuit implementations, it is said that it can be reduced to $O((\log n)^2 \log \log n)$.&lt;/p>
&lt;div class="mermaid">graph LR
A["Classical Algorithm (GNFS)"] -->|Limit| B["Sub-exponential Time L_n[1/3]"]
C["Quantum Algorithm (Shor)"] -->|Breakthrough| D["Polynomial Time O((log n)^3)"]
B --> E["Continued use of RSA (Increase key length)"]
D --> F["Complete collapse of RSA cryptography"]&lt;/div>
&lt;h3 id="52-classical-sub-exponential-time-vs-quantum-polynomial-time">5.2 Classical Sub-exponential Time vs. Quantum Polynomial Time
&lt;/h3>&lt;p>The difference between these two complexity classes holds decisive meaning in real-world cryptographic security.&lt;/p>
&lt;p>For example, consider the case of factoring RSA-2048 (a 2048-bit composite number).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>GNFS (Classical)&lt;/strong>: Substituting $n \approx 2^{2048}$ into $L_n[1/3, 1.923]$, about $2^{112}$ operations are required. This is an astronomical amount of computation that would take longer than the lifespan of the universe even if all the computing resources on Earth today were mobilized.&lt;/li>
&lt;li>&lt;strong>Shor&amp;rsquo;s Algorithm (Quantum)&lt;/strong>: With an $O((\log n)^3)$ algorithm, about $2048^3 \approx 8.5 \times 10^9$ logical gate operations are sufficient. This means that if appropriate hardware (a universal quantum computer with millions of physical qubits and error correction capabilities) exists, the calculation could be completed in just a few hours to a few days.&lt;/li>
&lt;/ul>
&lt;p>The paradigm shift from the sub-exponential function of &amp;ldquo;exponent $\alpha=1/3$&amp;rdquo; to &amp;ldquo;polynomial time&amp;rdquo; neutralizes the traditional cryptographic strategy of ensuring security by increasing the key length.&lt;/p>
&lt;hr>
&lt;h2 id="6-conclusion-outlook-for-the-next-generation">6. Conclusion: Outlook for the Next Generation
&lt;/h2>&lt;p>The current scientific consensus on the question &amp;ldquo;Are there classical algorithms beyond GNFS?&amp;rdquo; is as follows:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Practical improvements continue, but there are no asymptotic leaps&lt;/strong>: Attempts to improve the constant term $c$ of GNFS, such as MNFS, optimization of polynomial selection, and parallelization of the Block Wiedemann method, are ongoing. However, the possibility of discovering a classical algorithm with $\alpha$ falling below $1/3$ is considered extremely low.&lt;/li>
&lt;li>&lt;strong>The security of RSA on classical computers remains strong&lt;/strong>: The computational complexity of GNFS remains enormous, and RSA-2048 and RSA-4096 will continue to maintain their security against attacks by classical computers for decades to come.&lt;/li>
&lt;li>&lt;strong>The true threat is quantum algorithms&lt;/strong>: What crossed the barrier of computational complexity was Shor&amp;rsquo;s algorithm, based on the principles of quantum mechanics. As a result, the world is forced to transition to Post-Quantum Cryptography (PQC). The transition to new mathematical problems that are considered difficult to solve even for quantum computers (cannot be solved in polynomial time), such as lattice-based cryptography and hash-based cryptography, is currently at the forefront of cryptography.&lt;/li>
&lt;/ol>
&lt;p>The General Number Field Sieve (GNFS) is one of the &amp;ldquo;highest peaks&amp;rdquo; humanity has reached by challenging the limits of classical mathematics and algorithm design. Understanding the profound mathematical structure of GNFS is not merely learning the history of cryptanalysis, but also an intellectual journey of exploration that touches upon the beauty of computational complexity theory and algebraic number theory. Until the day quantum computers are put into practical use, GNFS will likely continue to defend its throne as the strongest integer factorization algorithm.&lt;/p></description></item><item><title>[Illustrated PQC] Comparison of Major Post-Quantum Cryptography Algorithms</title><link>http://kenji.blog/en/p/post-quantum-cryptography-algorithms-comparison/</link><pubDate>Fri, 11 Sep 2026 07:00:00 +0900</pubDate><guid>http://kenji.blog/en/p/post-quantum-cryptography-algorithms-comparison/</guid><description>&lt;img src="http://kenji.blog/p/post-quantum-cryptography-algorithms-comparison/img/eyecatch.jpg" alt="Featured image of post [Illustrated PQC] Comparison of Major Post-Quantum Cryptography Algorithms" />&lt;h2 id="1-introduction-the-cryptography-crisis-brought-by-quantum-computers">1. Introduction: The &amp;ldquo;Cryptography Crisis&amp;rdquo; Brought by Quantum Computers
&lt;/h2>&lt;p>In modern internet society, public-key cryptography is indispensable infrastructure for protecting the confidentiality of communications and data integrity. The widely used RSA cryptography and Elliptic Curve Cryptography (ECC) rely on the mathematical barriers of &amp;ldquo;the difficulty of factoring large composite numbers&amp;rdquo; and &amp;ldquo;the difficulty of the discrete logarithm problem on elliptic curves,&amp;rdquo; respectively. It has been proven that classical computers (including the supercomputers we use today) would take longer than the age of the universe to solve these mathematical problems, which has been the basis of their security.&lt;/p>
&lt;p>However, this solid premise is about to be completely overturned by the theory and practical advancement of &lt;strong>quantum computers&lt;/strong>. The &amp;ldquo;&lt;strong>Shor&amp;rsquo;s Algorithm&lt;/strong>&amp;rdquo;, published by cryptographer Peter Shor in 1994, theoretically proved that the integer factorization problem and the discrete logarithm problem can be solved in &amp;ldquo;polynomial time&amp;rdquo; by running it on a sufficiently capable Cryptographically Relevant Quantum Computer (CRQC). This means that all public-key cryptography currently in use will be rendered powerless.&lt;/p>
&lt;div class="mermaid">graph TD
A["Large-scale Quantum Computer (CRQC)"] -->|Execution| B["Shor's Algorithm"]
B -->|Decryption in polynomial time| C["Integer Factorization Problem (RSA)"]
B -->|Decryption in polynomial time| D["Discrete Logarithm Problem (ECC / ECDSA)"]
C --> E["Eavesdropping, data tampering, and spoofing of encrypted communications"]
D --> E
F["Store Now, Decrypt Later (SNDL)"] --> E&lt;/div>
&lt;p>It is extremely dangerous to think that &amp;ldquo;there is no problem because the full-scale completion of quantum computers is still decades away.&amp;rdquo; This is because an attack method called &lt;strong>Store Now, Decrypt Later (SNDL)&lt;/strong> is already a real threat. This is an attack where malicious states or hacker organizations save a massive amount of currently encrypted communication data (such as TLS traffic) in storage and decrypt all of it the moment a powerful quantum computer becomes available in the future. State secrets, infrastructure information, and medical data that need long-term protection are already exposed to this threat.&lt;/p>
&lt;p>Furthermore, for symmetric-key cryptography (such as AES) and hash functions (such as SHA-256), there is &lt;strong>Grover&amp;rsquo;s Algorithm&lt;/strong>, discovered in 1996. This reduces the computational complexity of a brute-force attack to its square root. In other words, the security level of AES-128 is effectively halved to $2^{64}$, so it is recommended to use longer keys and hash lengths, such as AES-256 and SHA-384, in the quantum era.&lt;/p>
&lt;p>To counter this unprecedented cryptography crisis, &lt;strong>Post-Quantum Cryptography (PQC)&lt;/strong> was born, which is based on new mathematical problems that are difficult to decrypt even with a quantum computer. This article provides an extremely detailed explanation of the major PQC algorithms, from their mathematical background to their mechanisms and architectural comparisons, based on the results of the PQC standardization process led by the National Institute of Standards and Technology (NIST) in the United States.&lt;/p>
&lt;hr>
&lt;h2 id="2-overview-and-history-of-the-nist-pqc-standardization-project">2. Overview and History of the NIST PQC Standardization Project
&lt;/h2>&lt;p>Transitioning cryptographic technologies takes years to decades, including redesigning protocols, updating systems, and replacing hardware. Therefore, cryptographers around the world have been advancing PQC research since early on. The US NIST (National Institute of Standards and Technology) has played a central role in this. In 2016, NIST announced a public call for the PQC standardization process and accepted entirely new cryptographic algorithm proposals from the global cryptographic community.&lt;/p>
&lt;p>The targets for standardization were the following two main categories:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Public-Key Cryptography / Key Encapsulation Mechanism (KEM)&lt;/strong>: A mechanism for securely sharing (distributing) a shared key to encrypt the communication path, such as in TLS connections.&lt;/li>
&lt;li>&lt;strong>Digital Signatures&lt;/strong>: A mechanism to prove that data has not been tampered with and that there is no spoofing of the sender (authenticity) in software updates and electronic certificates.&lt;/li>
&lt;/ol>
&lt;p>After a fierce competition of evaluation, analysis, and cryptanalysis spanning about 6 years (Round 1 to Round 3), further evaluation for Round 4 was conducted for some algorithms. As a result, the following algorithms were officially published as Federal Information Processing Standards (FIPS) in 2024 and established as the future global standards:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>FIPS 203 (ML-KEM)&lt;/strong>: KEM based on CRYSTALS-Kyber&lt;/li>
&lt;li>&lt;strong>FIPS 204 (ML-DSA)&lt;/strong>: Digital signature based on CRYSTALS-Dilithium&lt;/li>
&lt;li>&lt;strong>FIPS 205 (SLH-DSA)&lt;/strong>: Stateless hash-based signature based on SPHINCS+&lt;/li>
&lt;li>&lt;strong>(Scheduled for future formulation) FN-DSA&lt;/strong>: Digital signature based on FALCON&lt;/li>
&lt;/ul>
&lt;p>These selected algorithms rely on different mathematical &amp;ldquo;hardness problems,&amp;rdquo; ensuring diversity (Crypto Agility) so that even if a fatal vulnerability is discovered in one algorithm in the future, the entire system will not collapse. In the standardization process, lattice-based cryptography became the main player mainly due to its performance, but hash-based cryptography and code-based cryptography were adopted as powerful backups.&lt;/p>
&lt;hr>
&lt;h2 id="3-classification-of-major-mathematical-approaches-in-pqc">3. Classification of Major Mathematical Approaches in PQC
&lt;/h2>&lt;p>PQC algorithms are broadly divided into the following five categories based on the mathematical problems that form the basis of their security. This article delves deeply into the top three in particular.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Lattice-based Cryptography&lt;/strong>:
Based on the Shortest Vector Problem (SVP) and Closest Vector Problem (CVP) in multidimensional lattice spaces, and the derived LWE problem. It is the center of NIST standardization, and Kyber, Dilithium, and FALCON fall into this category. It has the best balance of processing speed, public key size, and ciphertext size, making it suitable for general-purpose use.&lt;/li>
&lt;li>&lt;strong>Hash-based Cryptography&lt;/strong>:
Relies solely on the &amp;ldquo;collision resistance&amp;rdquo; and &amp;ldquo;one-wayness&amp;rdquo; of cryptographic hash functions (such as SHA-2 and SHAKE) for its security basis. It is only applicable to digital signatures (such as SPHINCS+), but its security proof is the strongest, and it features extremely high resistance to unknown mathematical attacks.&lt;/li>
&lt;li>&lt;strong>Code-based Cryptography&lt;/strong>:
Based on the theory of error-correcting codes, it relies on the difficulty of the Syndrome Decoding Problem. Classic McEliece, proposed in the 1970s, is a representative example, having a very long history and proven security, but on the other hand, the public key size is extremely large, in the megabyte range.&lt;/li>
&lt;li>&lt;strong>Multivariate Polynomial Cryptography&lt;/strong>:
Based on the difficulty of finding a solution to a system of multivariate quadratic equations over a finite field (MQ problem). It was mainly proposed as digital signatures (such as Rainbow), but during the final round of NIST, a powerful attack method that could crack it in a few days on a single PC was discovered, and many algorithms dropped out of the standardization.&lt;/li>
&lt;li>&lt;strong>Isogeny-based Cryptography&lt;/strong>:
Based on the path-finding problem on an isogeny graph of elliptic curves. The key size is very small, and it was expected to be a legitimate successor to ECC, but &amp;ldquo;SIKE,&amp;rdquo; the final candidate, was completely broken in just a few hours on a normal PC in 2022 using classical mathematics (such as the Castryck-Decru attack), marking a dramatic end that symbolized the difficulty and terror of PQC design.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="4-the-abyss-of-lattice-cryptography-mathematical-foundation-of-the-lwe-problem-and-module-lwe">4. The Abyss of Lattice Cryptography: Mathematical Foundation of the LWE Problem and Module-LWE
&lt;/h2>&lt;p>&lt;strong>Lattice-based cryptography&lt;/strong> is currently considered the most promising and has become the center of standardization. At the root of its security is the &lt;strong>LWE (Learning with Errors) problem&lt;/strong>. Proposed by Oded Regev in 2005, this groundbreaking achievement earned him the Gödel Prize. One cannot talk about modern PQC without understanding the LWE problem.&lt;/p>
&lt;h3 id="41-what-is-the-lwe-learning-with-errors-problem">4.1. What is the LWE (Learning with Errors) Problem?
&lt;/h3>&lt;p>First, consider a simple system of linear equations. Suppose there is a known random matrix $A$ and an unknown secret vector $\vec{s}$ under a certain modulus $q$ (modulo $q$), and their product $\vec{b}$ is given:&lt;/p>
$$ \vec{b} = A\vec{s} \pmod q $$
&lt;p>In this case, it is easy to find the unknown $\vec{s}$ from the public information $A$ and $\vec{b}$. Using the classical algorithm &amp;ldquo;Gaussian elimination,&amp;rdquo; $\vec{s}$ can be easily calculated in polynomial time.&lt;/p>
&lt;p>However, adding a &amp;ldquo;small intentional error (noise)&amp;rdquo; to this equation dramatically increases the difficulty of the problem. This is the &lt;strong>LWE problem&lt;/strong>.&lt;/p>
&lt;p>Prepare an unknown secret vector $\vec{s} \in \mathbb{Z}_q^n$ and a randomly chosen matrix $A \in \mathbb{Z}_q^{m \times n}$. Furthermore, prepare an error vector $\vec{e} \in \mathbb{Z}_q^m$ whose &amp;ldquo;elements have sufficiently small values,&amp;rdquo; chosen according to a normal or binomial distribution, and calculate $\vec{b}$ as follows:&lt;/p>
$$ \vec{b} = A\vec{s} + \vec{e} \pmod q $$
&lt;p>The &lt;strong>Search LWE problem&lt;/strong> is the problem of &amp;ldquo;finding the secret information $\vec{s}$ from the public information $(A, \vec{b})$.&amp;rdquo; Due to the existence of this error $\vec{e}$, if one attempts an algebraic solution such as Gaussian elimination, the error $\vec{e}$ amplifies like a snowball in the process of adding and subtracting equations, ultimately becoming indistinguishable from random values and breaking down.&lt;/p>
&lt;p>The greatness of the LWE problem lies in the fact that there is a powerful theoretical proof (reduction) that unless there is a quantum algorithm that can solve GapSVP (Decision Shortest Vector Problem) and SIVP (Shortest Independent Vector Problem), which are &amp;ldquo;worst-case hardness&amp;rdquo; problems on lattices, the LWE problem cannot be solved in the average-case either. In other words, even for a randomly generated cryptographic key, it is guaranteed to have robust security backed by a theoretical upper bound.&lt;/p>
&lt;h3 id="42-dramatic-efficiency-improvement-by-ring-lwe-and-module-lwe">4.2. Dramatic Efficiency Improvement by Ring-LWE and Module-LWE
&lt;/h3>&lt;p>The normal LWE problem (Standard LWE) has a very clear basis for security, but the size of the matrix $A$ becomes very large, and the key size reaches the megabyte class, making it impractical. Therefore, an approach was proposed to provide an algebraic structure by utilizing Polynomial Rings.&lt;/p>
&lt;p>In the &lt;strong>Ring-LWE problem&lt;/strong>, instead of simple vectors and matrices, elements (polynomials) of a certain polynomial ring $R_q$ are used. The following cyclotomic polynomial ring is generally used in the NIST standard:&lt;/p>
$$ R_q = \mathbb{Z}_q[X]/(X^n + 1) $$
&lt;p>Here, $n$ is a power of 2 (e.g., 256), and $q$ is an appropriate prime number. Over this ring, using elements $a, s, e \in R_q$, $b = a \cdot s + e \pmod q$ is calculated. Because a single polynomial $a$ has $n$ coefficients, data can be significantly compressed, and by using the finite field version of the Fast Fourier Transform (FFT) called &lt;strong>NTT (Number Theoretic Transform)&lt;/strong>, ultra-fast polynomial multiplication becomes possible with a computational complexity of $O(n \log n)$.&lt;/p>
&lt;p>However, Ring-LWE had concerns that &amp;ldquo;there might be an unknown vulnerability due to the special algebraic structure of the ring.&amp;rdquo; Furthermore, there was an engineering challenge that when changing the security level (such as AES-128, 192, 256 equivalent), the degree $n$ of the polynomial itself had to be changed, and the entire implementation, such as the NTT algorithm, had to be rewritten accordingly.&lt;/p>
&lt;p>Therefore, the &lt;strong>Module-LWE (M-LWE) problem&lt;/strong> was adopted by standardization algorithms such as Kyber and Dilithium. Module-LWE is a compromise situated exactly halfway between the structureless Standard LWE and the overly structured Ring-LWE, using a $k \times k$ matrix (module) whose components are elements of the polynomial ring $R_q$:&lt;/p>
$$ \vec{b} = A\vec{s} + \vec{e} \pmod{R_q} \quad (A \in R_q^{k \times k}, \vec{s}, \vec{e} \in R_q^k) $$
&lt;p>The greatest advantage of Module-LWE is that the security level can be easily scaled simply by changing the matrix dimension $k$ while keeping the polynomial degree $n$ (in the NIST standard, $n=256$) fixed.
For example, in Kyber, the dimension $k$ is adjusted as follows:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Kyber512 (Level 1)&lt;/strong>: $k = 2$ (equivalent to AES-128)&lt;/li>
&lt;li>&lt;strong>Kyber768 (Level 3)&lt;/strong>: $k = 3$ (equivalent to AES-192)&lt;/li>
&lt;li>&lt;strong>Kyber1024 (Level 5)&lt;/strong>: $k = 4$ (equivalent to AES-256)&lt;/li>
&lt;/ul>
&lt;p>This made it possible to reuse 100% of the underlying NTT code and polynomial operation hardware circuits across all security levels, dramatically improving implementation security and efficiency.&lt;/p>
&lt;hr>
&lt;h2 id="5-crystals-kyber-ml-kem-next-generation-key-encapsulation-mechanism">5. CRYSTALS-Kyber (ML-KEM): Next-Generation Key Encapsulation Mechanism
&lt;/h2>&lt;p>CRYSTALS-Kyber, officially standardized as &lt;strong>FIPS 203 (ML-KEM)&lt;/strong>, is a Key Encapsulation Mechanism (KEM) based on the aforementioned Module-LWE problem. It will become the de facto global standard for securely sharing session keys in TLS 1.3, SSH, and the like in the future.&lt;/p>
&lt;h3 id="51-architecture-of-kem-key-encapsulation-mechanism">5.1. Architecture of KEM (Key Encapsulation Mechanism)
&lt;/h3>&lt;p>In the PQC era, instead of a direct approach like RSA where &amp;ldquo;the client creates a common key, encrypts it with the server&amp;rsquo;s public key, and sends it,&amp;rdquo; a KEM encapsulation framework becomes the standard.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant Client as "Client (Alice)"
participant Server as "Server (Bob)"
Note over Client: "ML-KEM KeyGen()"
Client->>Client: "Generate secret key (sk) and public key (pk)"
Client->>Server: "Send public key (pk)"
Note over Server: "ML-KEM Encaps()"
Server->>Server: "Generate a random shared key (K)"
Server->>Server: "Encapsulate K with pk to create ciphertext (c)"
Server->>Client: "Send ciphertext (c)"
Note over Client: "ML-KEM Decaps()"
Client->>Client: "Decrypt ciphertext (c) using secret key (sk)"
Client->>Client: "Decapsulate and extract the shared key (K)"
Note over Client, Server: "Start encrypted communication (e.g. AES) using the shared key (K)"&lt;/div>
&lt;h3 id="52-kybers-internal-algorithm-mechanism-and-the-fujisaki-okamoto-transform">5.2. Kyber&amp;rsquo;s Internal Algorithm Mechanism and the Fujisaki-Okamoto Transform
&lt;/h3>&lt;p>Kyber&amp;rsquo;s design is highly sophisticated. First, it constructs a public-key encryption scheme (Kyber.CPAPKE) that is secure only against CPA (Chosen Plaintext Attack), and then adopts a design that upgrades it into a complete KEM that is secure against CCA (Adaptive Chosen Ciphertext Attack) by applying a cryptographically extremely powerful method called the &lt;strong>Fujisaki-Okamoto Transform&lt;/strong>.&lt;/p>
&lt;p>The core encryption and decryption mechanisms of CPAPKE are as follows:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Key Generation&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>From a random seed value, generate a matrix $A \in R_q^{k \times k}$ in the NTT domain. The modulus $q$ used is $3329$.&lt;/li>
&lt;li>Sample a secret vector $\vec{s}$ and an error vector $\vec{e}$ with small coefficients from a Centered Binomial Distribution (CBD).&lt;/li>
&lt;li>Calculate $\vec{t} = A\vec{s} + \vec{e}$. The public key is $(A, \vec{t})$, and the secret key is $\vec{s}$. (In reality, $A$ is published as a seed value to save bandwidth).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Encryption&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>Encode the 32-byte message to be shared (shared key material) $m$ into a polynomial.&lt;/li>
&lt;li>Generate a new random vector $\vec{r}$ and small errors $\vec{e_1}, e_2$.&lt;/li>
&lt;li>$\vec{u} = A^T\vec{r} + \vec{e_1}$&lt;/li>
&lt;li>$v = \vec{t}^T\vec{r} + e_2 + \lfloor q/2 \rceil \cdot m$&lt;/li>
&lt;li>The ciphertext is $(\vec{u}, v)$.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Decryption&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>The receiver calculates $v - \vec{s}^T\vec{u}$.&lt;/li>
&lt;li>Expanding this formula mathematically yields the following:
$v - \vec{s}^T\vec{u} = (\vec{t}^T\vec{r} + e_2 + \lfloor q/2 \rceil \cdot m) - \vec{s}^T(A^T\vec{r} + \vec{e_1})$&lt;/li>
&lt;li>Substituting $\vec{t} = A\vec{s} + \vec{e}$ here cancels out the main term $\vec{s}^TA^T\vec{r}$.&lt;/li>
&lt;li>What remains is $\lfloor q/2 \rceil \cdot m + (\vec{e}^T\vec{r} + e_2 - \vec{s}^T\vec{e_1})$.&lt;/li>
&lt;li>Since the terms in parentheses are &amp;ldquo;products and sums of small errors,&amp;rdquo; they remain sufficiently small values (noise) as a whole. Therefore, by making a threshold judgment on whether each coefficient is close to $0$ or close to $q/2$, the bits (0 or 1) of the original message $m$ can be completely restored without error.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;p>Kyber&amp;rsquo;s greatest strengths are its overwhelming &lt;strong>processing speed&lt;/strong> and &lt;strong>moderate key size&lt;/strong>. For Kyber768, the public key size is 1,184 bytes and the ciphertext size is 1,088 bytes. While larger compared to RSA-3072 (key size around 384 bytes), it can fit within the MTU (Maximum Transmission Unit) of modern internet communications without packet fragmentation, having almost no adverse effect on network latency.&lt;/p>
&lt;hr>
&lt;h2 id="6-crystals-dilithium-ml-dsa-general-purpose-lattice-based-digital-signature">6. CRYSTALS-Dilithium (ML-DSA): General-Purpose Lattice-Based Digital Signature
&lt;/h2>&lt;p>In the standardization of digital signatures, algorithms with different design philosophies within the same lattice cryptography approach competed against each stands. Among them, &lt;strong>CRYSTALS-Dilithium&lt;/strong> was selected as &lt;strong>FIPS 204 (ML-DSA)&lt;/strong> for general-purpose digital signatures.&lt;/p>
&lt;h3 id="61-the-fiat-shamir-with-aborts-paradigm">6.1. The Fiat-Shamir with Aborts Paradigm
&lt;/h3>&lt;p>Like Kyber, Dilithium is a digital signature scheme based on the Module-LWE (and Module-SIS problem). The design base uses an extremely important paradigm called &amp;ldquo;&lt;strong>Fiat-Shamir with Aborts&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>The Fiat-Shamir transform itself is a standard method for converting an interactive zero-knowledge proof protocol into a non-interactive digital signature. The prover (signer) generates a commitment $y$, calculates $w = Ay$, passes it through a hash function to obtain a random challenge $c$, and calculates the response $z = y + cs$.&lt;/p>
&lt;p>However, simply applying this to lattice cryptography caused a fatal problem (side-channel-like mathematical leakage) where the distribution of the response $z$ was distorted depending on the value of the secret key $s$, gradually leaking information about the secret key $s$ to an attacker observing many signatures.&lt;/p>
&lt;p>The Dilithium design team (Lyubashevsky et al.) introduced a method called &amp;ldquo;&lt;strong>Rejection Sampling&lt;/strong>&amp;rdquo;, where if the coefficients of the calculated signature $z$ do not fall within a pre-set safe threshold, the entire signature process is aborted and recalculated from the beginning using a new random number $y$.&lt;/p>
&lt;p>As a result, the finally output signature $z$ has a completely uniform distribution independent of the secret key, succeeding in completely preventing mathematical information leakage.&lt;/p>
&lt;h3 id="62-dilithiums-advantages-and-ease-of-implementation">6.2. Dilithium&amp;rsquo;s Advantages and Ease of Implementation
&lt;/h3>&lt;p>A major design advantage of Dilithium is that it &lt;strong>does not use&lt;/strong> complex &amp;ldquo;sampling from a Gaussian distribution&amp;rdquo; or &amp;ldquo;floating-point arithmetic&amp;rdquo; at all in the signature generation process. Because it can be implemented using only sampling from a uniform distribution, simple integer modulo arithmetic, NTT, and a hash function (SHAKE), it is easy to implement securely and in constant-time in a wide range of environments, from embedded microcontrollers to cloud servers. This gives it robust resistance against physical side-channel attacks such as timing attacks.&lt;/p>
&lt;hr>
&lt;h2 id="7-falcon-fn-dsa-ultimately-compact-lattice-signature">7. FALCON (FN-DSA): Ultimately Compact Lattice Signature
&lt;/h2>&lt;p>NIST selected &lt;strong>FALCON (Fast-Fourier Lattice-based Compact Signatures over NTRU)&lt;/strong>, another lattice-based signature with different characteristics from Dilithium, as a standardization candidate (currently drafting as FN-DSA).&lt;/p>
&lt;h3 id="71-ntru-lattices-and-gaussian-sampling">7.1. NTRU Lattices and Gaussian Sampling
&lt;/h3>&lt;p>FALCON&amp;rsquo;s greatest feature is that it uses not the LWE problem but the historical &lt;strong>NTRU (N-th degree Truncated polynomial Ring Units) lattices&lt;/strong> that have existed since 1996. Furthermore, it adopts the &amp;ldquo;&lt;strong>Hash-and-Sign&lt;/strong>&amp;rdquo; paradigm based on the GPV (Gentry-Peikert-Vaikuntanathan) framework.&lt;/p>
&lt;p>In Hash-and-Sign, the hash value of a message is set as a target point in space, and finding the point on the lattice closest to that point (an approximate solution to the closest vector problem) serves as the signature. To do this, it is necessary to sample points according to a discrete Gaussian distribution using a &amp;ldquo;high-quality short basis&amp;rdquo; as the secret key.&lt;/p>
&lt;p>FALCON dramatically accelerated this heavy computation using a method called &amp;ldquo;&lt;strong>Fast Fourier Orthogonalization (FFO)&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;h3 id="72-pros-and-cons-of-falcon">7.2. Pros and Cons of FALCON
&lt;/h3>&lt;p>The overwhelming advantage of FALCON is that its &lt;strong>signature size and public key size are extremely small (compact)&lt;/strong>. While the signature size of Dilithium3 is about 3,309 bytes, the signature size of FALCON-512 is only about 666 bytes. The public key is also very small at 897 bytes, making it a lifesaver in environments with extremely limited communication bandwidth, IoT devices, or specific network protocols.&lt;/p>
&lt;p>However, there is a significant drawback. Because discrete Gaussian sampling, which involves complex &lt;strong>floating-point arithmetic (64-bit IEEE 754)&lt;/strong>, is essential during signature generation, constant-time implementation to prevent timing leakage is extremely difficult, and the code becomes huge. For this reason, FALCON is positioned as a powerful specialized algorithm for specific uses, in contrast to the general-purpose Dilithium.&lt;/p>
&lt;div class="mermaid">graph LR
A["Requirements for Digital Signatures"] --> B{"What is the top priority constraint?"}
B -->|"Simplicity of implementation, versatility, ease of constant-time implementation"| C["Dilithium (ML-DSA)"]
B -->|"Minimization of communication bandwidth, compactness of data size"| D["FALCON (FN-DSA)"]
C --> E["General-purpose TLS certificates, digital signatures for software"]
D --> F["Protocols with strict packet size limits, special environments"]&lt;/div>
&lt;hr>
&lt;h2 id="8-sphincs-slh-dsa-hash-based-signature-boasting-the-strongest-security">8. SPHINCS+ (SLH-DSA): Hash-Based Signature Boasting the Strongest Security
&lt;/h2>&lt;p>To prepare for the worst-case scenario (a rare event) where the security of lattice cryptography is broken by a brilliant mathematician&amp;rsquo;s breakthrough in the future, NIST formulated &lt;strong>FIPS 205 (SLH-DSA)&lt;/strong>, namely &lt;strong>SPHINCS+&lt;/strong>, as a standard with a completely different approach from lattice cryptography.&lt;/p>
&lt;p>SPHINCS+ is classified as a &lt;strong>hash-based signature&lt;/strong>. The basis of its security relies solely on &amp;ldquo;the cryptographic hash functions used (such as SHA-2 and SHAKE256) having collision resistance and one-wayness.&amp;rdquo; Because it does not depend on mathematical problems with specific algebraic structures like LWE or integer factorization, it boasts extremely robust security (the most conservative security) where even if any powerful quantum algorithm appears in the future, one can simply counter it by increasing the output length of the hash function.&lt;/p>
&lt;h3 id="81-stateless-architecture-with-wots-and-fors">8.1. Stateless Architecture with WOTS+ and FORS
&lt;/h3>&lt;p>The history of hash-based signatures is old, dating back to Lamport signatures and Winternitz One-Time Signatures (WOTS) in the 1970s. These were disposable keys that could &amp;ldquo;securely sign only once.&amp;rdquo; To make them usable multiple times, algorithms like XMSS (eXtended Merkle Signature Scheme) and LMS were developed, combining a Merkle Tree to manage countless one-time keys with a single root hash.&lt;/p>
&lt;p>However, XMSS and LMS had a fatal flaw of being &amp;ldquo;&lt;strong>stateful&lt;/strong>&amp;rdquo;. It was necessary to strictly record the index state of &amp;ldquo;which one-time key was used&amp;rdquo; in non-volatile memory every time a signature was made, and if the state rolled back due to something like restoring a virtual machine snapshot and the same one-time key was used twice, the secret key would leak immediately, and the system would collapse.&lt;/p>
&lt;p>SPHINCS+ is a &amp;ldquo;&lt;strong>stateless&lt;/strong>&amp;rdquo; hash-based signature that solves this state management hassle.
Its core technology is the following combination:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>WOTS+ (Winternitz One-Time Signature Plus)&lt;/strong>: A basic one-time signature.&lt;/li>
&lt;li>&lt;strong>FORS (Forest of Random Subsets)&lt;/strong>: A Few-Time Signature technology. It remains secure even if the same key is reused a few times.&lt;/li>
&lt;li>&lt;strong>Hyper-Tree&lt;/strong>: A massive structure of multi-layered Merkle Trees.&lt;/li>
&lt;/ol>
&lt;p>When signing with SPHINCS+, instead of managing state, it uses a pseudorandom number to randomly select one of a vast number of FORS keys at the bottom of the Hyper-Tree to sign. Because the number of leaves in the tree is astronomically large, the probability of accidentally picking the same key twice (collision) is negligibly small, resulting in a stateless realization.&lt;/p>
&lt;p>The sole and greatest weakness of SPHINCS+ is that its &lt;strong>signature size is extremely large&lt;/strong>. Depending on the parameters, the signature size can reach 17 to 49 kilobytes, and the signature generation speed is also overwhelmingly slower than lattice cryptography. Therefore, rather than for daily web browsing, it is intended for uses where signatures are not made frequently and long-term absolute security is strongly required, such as software update signatures and root Certificate Authority (CA) certificates.&lt;/p>
&lt;hr>
&lt;h2 id="9-code-based-cryptography-the-good-old-giant-classic-mceliece">9. Code-Based Cryptography: The Good Old Giant, Classic McEliece
&lt;/h2>&lt;p>In the NIST standardization process, an important approach still being evaluated as a final candidate for Round 4 is &lt;strong>Classic McEliece&lt;/strong> of &lt;strong>code-based cryptography&lt;/strong>.&lt;/p>
&lt;p>Proposed by Robert McEliece in 1978, this algorithm is one of the oldest in the history of public-key cryptography, alongside RSA. It utilizes algebraic geometry codes called &amp;ldquo;Goppa codes,&amp;rdquo; where a message is intentionally encrypted with an error (noise vector) added, and only the person holding the parity check matrix of the Goppa code as a secret key can remove the error using powerful error-correcting capabilities to decrypt the original message. This is based on the &amp;ldquo;&lt;strong>Syndrome Decoding Problem&lt;/strong>&amp;rdquo;.&lt;/p>
$$ \vec{c} = \vec{m} G + \vec{e} $$
&lt;p>
(where $G$ is the scrambled generator matrix which is the public key, and $\vec{e}$ is the error vector of weight $t$)&lt;/p>
&lt;p>The amazing thing about Classic McEliece is its overwhelming track record: &lt;strong>despite more than 40 years passing since its proposal and being exposed to intense cryptanalysis research by cryptographers worldwide, no fundamental vulnerability has ever been discovered&lt;/strong>. It possesses the most &amp;ldquo;time-proven robust security&amp;rdquo; among PQC.&lt;/p>
&lt;p>Furthermore, it has the advantage of a very small ciphertext size (only about 100 to 200 bytes). However, it has a fatal flaw in that &lt;strong>the public key size is in the megabyte (MB) range&lt;/strong>. Even at the lowest security level (AES-128 equivalent), the public key is about 250KB, and it exceeds 1MB at higher levels.&lt;/p>
&lt;p>For this reason, it cannot be applied at all to uses where the public key is transmitted over a network during every communication, such as in TLS handshakes. However, in special use cases where public keys can be pre-deployed in systems, such as sharing pre-shared keys for VPNs, hardcoding public keys in firmware, or satellite communications, it continues to be considered a highly promising option due to its robust security.&lt;/p>
&lt;hr>
&lt;h2 id="10-performance-comparison-and-trade-offs-of-each-pqc-algorithm">10. Performance Comparison and Trade-offs of Each PQC Algorithm
&lt;/h2>&lt;p>The performance characteristics of the major algorithms explained so far at typical security levels (equivalent to NIST Level 2-3, AES-128-192 levels) are summarized in the table below.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Algorithm (Standard Name)&lt;/th>
&lt;th style="text-align:left">Category&lt;/th>
&lt;th style="text-align:left">Mathematical Basis&lt;/th>
&lt;th style="text-align:left">Public Key Size&lt;/th>
&lt;th style="text-align:left">Secret Key Size&lt;/th>
&lt;th style="text-align:left">Ciphertext/Signature Size&lt;/th>
&lt;th style="text-align:left">Processing Speed Trend&lt;/th>
&lt;th style="text-align:left">Main Features and Uses&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Kyber768&lt;/strong>&lt;br>(ML-KEM)&lt;/td>
&lt;td style="text-align:left">KEM&lt;/td>
&lt;td style="text-align:left">Module-LWE&lt;/td>
&lt;td style="text-align:left">1,184 Bytes&lt;/td>
&lt;td style="text-align:left">2,400 Bytes&lt;/td>
&lt;td style="text-align:left">1,088 Bytes&lt;/td>
&lt;td style="text-align:left">Very fast&lt;/td>
&lt;td style="text-align:left">Best balance of key size and speed. General-purpose KEM standard such as TLS 1.3.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Dilithium3&lt;/strong>&lt;br>(ML-DSA)&lt;/td>
&lt;td style="text-align:left">Signature&lt;/td>
&lt;td style="text-align:left">Module-LWE&lt;/td>
&lt;td style="text-align:left">1,952 Bytes&lt;/td>
&lt;td style="text-align:left">4,032 Bytes&lt;/td>
&lt;td style="text-align:left">3,309 Bytes&lt;/td>
&lt;td style="text-align:left">Fast for both generation and verification&lt;/td>
&lt;td style="text-align:left">Simple implementation. General-purpose digital signature standard.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>FALCON-512&lt;/strong>&lt;br>(FN-DSA)&lt;/td>
&lt;td style="text-align:left">Signature&lt;/td>
&lt;td style="text-align:left">NTRU Lattice&lt;/td>
&lt;td style="text-align:left">897 Bytes&lt;/td>
&lt;td style="text-align:left">1,281 Bytes&lt;/td>
&lt;td style="text-align:left">666 Bytes&lt;/td>
&lt;td style="text-align:left">Signature generation is slower, verification is ultra-fast&lt;/td>
&lt;td style="text-align:left">Minimal signature size. However, requires floating-point operations. For embedded/IoT.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>SPHINCS+&lt;/strong>&lt;br>(SLH-DSA)&lt;/td>
&lt;td style="text-align:left">Signature&lt;/td>
&lt;td style="text-align:left">Hash Function&lt;/td>
&lt;td style="text-align:left">32 Bytes&lt;/td>
&lt;td style="text-align:left">64 Bytes&lt;/td>
&lt;td style="text-align:left">Approx. 17,000 Bytes&lt;/td>
&lt;td style="text-align:left">Generation is very slow&lt;/td>
&lt;td style="text-align:left">Mathematical failure risk is almost zero. High security uses like root certificates.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;strong>Classic McEliece&lt;/strong>&lt;/td>
&lt;td style="text-align:left">KEM&lt;/td>
&lt;td style="text-align:left">Goppa Code&lt;/td>
&lt;td style="text-align:left">&lt;strong>Approx. 1.04 MB&lt;/strong>&lt;/td>
&lt;td style="text-align:left">13,568 Bytes&lt;/td>
&lt;td style="text-align:left">&lt;strong>188 Bytes&lt;/strong>&lt;/td>
&lt;td style="text-align:left">Encapsulation is fast&lt;/td>
&lt;td style="text-align:left">40 years of security track record. Giant public key. For hardcodable environments.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="understanding-the-trade-offs">Understanding the Trade-offs
&lt;/h3>&lt;p>In the world of PQC, there is no single magical algorithm that has &amp;ldquo;small size, fast speed, and perfect mathematical guarantees.&amp;rdquo;&lt;/p>
&lt;ul>
&lt;li>&lt;strong>The Internet Standard (Kyber / Dilithium)&lt;/strong>: The best balance of performance, making it the most suitable for a drop-in replacement of current RSA/ECC.&lt;/li>
&lt;li>&lt;strong>Ultimate Conservatism (SPHINCS+)&lt;/strong>: Chosen when one wants absolute insurance against future mathematical breakthroughs, even at the expense of data size or processing speed.&lt;/li>
&lt;li>&lt;strong>For Special Environments (FALCON / Classic McEliece)&lt;/strong>: Specialized weapons chosen according to environmental constraints, such as when communication bandwidth is extremely narrow or when pre-distribution is possible.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="11-challenges-toward-practical-application-and-the-practical-solution-of-hybrid-cryptography">11. Challenges Toward Practical Application and the Practical Solution of &amp;ldquo;Hybrid Cryptography&amp;rdquo;
&lt;/h2>&lt;p>With the completion of standardization by NIST and the official issuance of FIPS standards, the PQC migration of IT infrastructure worldwide has begun in earnest. Google&amp;rsquo;s Chrome browser, Apple&amp;rsquo;s iMessage (PQ3 protocol), and network providers like Cloudflare have already implemented PQC support in their protocols and started actual operations.&lt;/p>
&lt;p>However, completely switching to new cryptographic algorithms all at once comes with a very high risk. If a brilliant mathematician were to discover a fatal attack method (a mathematical flaw solvable even by classical computers) against lattice cryptography like Kyber a few years from now, entire systems relying on it would instantly become completely defenseless.&lt;/p>
&lt;p>A practical and recommended approach to mitigate this uncertainty risk is &amp;ldquo;&lt;strong>Hybrid Cryptography&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>In hybrid cryptography, key exchange is performed using both a classical cryptographic algorithm with a long track record (e.g., Elliptic Curve Cryptography like X25519) and a new PQC algorithm (e.g., Kyber768) simultaneously. Shared key components are generated individually with each algorithm, and finally, a secure Key Derivation Function (KDF) is used to mix the two components to generate the final master secret.&lt;/p>
&lt;div class="mermaid">graph TD
A["Client"] -->|1. Send X25519 Public Key + Kyber Public Key| B["Server"]
B -->|2. Return X25519 Shared Key + Kyber Encapsulated Ciphertext| A
A --> C{"Derive Master Secret (KDF)"}
B --> C
C -->|Input: (X25519 Shared Key) || (Kyber Shared Key)| D["Secure Communication Key (AES-256 / ChaCha20)"]
D -->|"Resistant to both quantum threats &amp; classical vulnerabilities"| E["Secure Hybrid Encrypted Communication (TLS 1.3)"]&lt;/div>
&lt;p>This achieves a robust two-tiered security: &amp;ldquo;even if a quantum computer becomes a reality and ECC is broken, Kyber protects the communication,&amp;rdquo; and conversely, &amp;ldquo;even if an unknown mathematical flaw is found in Kyber, ECC protects the communication.&amp;rdquo; A representative example is the &lt;strong>X25519MLKEM768 (formerly X25519Kyber768)&lt;/strong> draft being standardized by the IETF, and communications between current web browsers and cutting-edge servers are already being carried out precisely using this hybrid method.&lt;/p>
&lt;p>Furthermore, the concept of &lt;strong>Crypto Agility&lt;/strong>, building a system architecture that &amp;ldquo;does not overly rely on a specific cryptographic algorithm and can quickly switch to another algorithm (e.g., from Kyber to McEliece, or Dilithium to SPHINCS+) in the event an algorithm fails,&amp;rdquo; will be an essential requirement in future system development.&lt;/p>
&lt;hr>
&lt;h2 id="12-conclusion-a-new-horizon-for-cryptographic-technology">12. Conclusion: A New Horizon for Cryptographic Technology
&lt;/h2>&lt;p>Ironically, quantum computers, the dream technology of humanity, have become the greatest threat to breaking the mathematical defenses of &amp;ldquo;integer factorization&amp;rdquo; and &amp;ldquo;discrete logarithm problems&amp;rdquo; that we have trusted for many years. However, cryptographers around the world did not succumb to this; they pioneered more complex and profound multi-dimensional mathematical fields such as lattice theory, hash function trees, and error-correcting codes, and built a new defense called Post-Quantum Cryptography (PQC).&lt;/p>
&lt;p>The completion of standardizations by NIST for FIPS 203 (ML-KEM), FIPS 204 (ML-DSA), and FIPS 205 (SLH-DSA) is not the goal. It is just the first step in the grand journey of PQC migration that will continue for decades to come. For software engineers and system architects, how to optimally adapt the &amp;ldquo;increased key sizes&amp;rdquo; and &amp;ldquo;changed computational costs&amp;rdquo; brought by these new algorithms into network protocols and systems will be a major technical challenge moving forward.&lt;/p>
&lt;p>The battle between quantum computers and cryptography is an exciting area where humanity&amp;rsquo;s mathematical exploration and the evolution of technology intersect most fiercely. Through this article, we hope you have deeply understood the beautiful mathematical theories behind PQC and the amazing mechanisms of each algorithm that will shape the future of cybersecurity.&lt;/p>
&lt;hr>
&lt;p>&lt;em>References:&lt;/em>&lt;/p>
&lt;ul>
&lt;li>&lt;em>NIST Post-Quantum Cryptography Standardization Program&lt;/em>&lt;/li>
&lt;li>&lt;em>FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard&lt;/em>&lt;/li>
&lt;li>&lt;em>FIPS 204: Module-Lattice-Based Digital Signature Standard&lt;/em>&lt;/li>
&lt;li>&lt;em>FIPS 205: Stateless Hash-Based Digital Signature Standard&lt;/em>&lt;/li>
&lt;/ul></description></item></channel></rss>