Mathematical Foundations

If you are an absolute beginner in mathematics, you can take a look to my article on the Mathematical Language.

Prime numbers

Mathematically, a prime number can be defined precisely as follows:

A natural number \(p\) greater than 1 is called prime if it has exactly two positive divisors, 1 and itself. Formally:

\[ \begin{align*} p &\in \mathbb{N}, \quad p > 1 \\ \forall d \in \mathbb{N}, \quad d \mid p &\implies (d = 1 \text{ or } d = p) \end{align*} \]

Usually, we define the set of prime numbers as $$ \mathbb{P} = \left\{2, 3, 5, 7, 11, \dots\right\} $$

Examples

  • 7 is prime: divisors are {1, 7}
  • 12 is NOT prime: divisors are {1, 2, 3, 4, 6, 12}

Exercices

1| Is 92 prime ?

Solution

No, 92 is NOT prime : Divisors are {1, 2, 4, 23, 92}

2| Is 2 prime ?

Solution

Yes, 2 is prime : Divisors are {1, 2}

3| Is 209 prime ?

Solution

No, 209 is NOT prime : Divisors are {1, 11, 19, 209}

4| Is 19 prime ?

Solution

Yes, 19 is prime : Divisors are {1, 19}

Short introduction to modular arithmetic

In mathematics, modular arithmetic is a system of arithmetic operations for integers, where numbers "wrap around" when reaching a certain value, called the modulus.

Congruent meme

The modern approach was developed by Carl Friedrich Gauss in his book Disquisitiones Arithmeticae, published in 1801.

The Clock Analogy

One easy way to introduce modular arithmetic is to look at a clock.

When it's 8 o'clock and you add 5 hours, it becomes 1 o'clock (not 13 o'clock). This is because time "wraps around" after 12 hours.

We can represent this mathematically as: $$ 8 + 5 \equiv 1 \pmod{12} $$

Congruence

\(\forall n \in \mathbb{N},\ n > 1, \forall a, b \in \mathbb{Z},\) We say that \(a\) and \(b\) are congruent modulo \(n\) if \(n \mid (a-b)\), which is denoted by \(a \equiv b \pmod{n}\)

When we divide \(a\) by \(n\), we get: $$ a = nq + r \quad \text{where } 0 \leq r < n $$ We write: \(a \equiv r \pmod{n}\), and \(r\) is called the remainder.

Example

Let \(n\) = 5, \(a\) = 17 and \(b\) = 2:

We calculate :

\[ a-b = 17 - 2 = 15 \]

Since \(5|15\), we have: $$ 17 \equiv 2 \pmod{5} $$

Alternative Definition

Another way to define the congruence is: $$ a \equiv b \pmod{n} \leftrightarrow \exists k \in \mathbb{Z}, a = kn + b\ $$ This means \(a\) and \(b\) have the same remainder when divided by \(n\).

Exercices

Is it true? \(100 \equiv 5 \pmod{50}\)

Solution

False, Because \(100 = 2\cdot50 + 0\), so \(100 \equiv 0 \pmod{50}\)

\(15 \equiv 3 \pmod{12}\)

Solution

True, Because \(15 = 12\cdot1 + 3\), so \(15 \equiv 3 \pmod{12}\)

\(9 \equiv 19 \pmod{10}\)

Solution

True, Because \(19 - 9 = 10\), and \(10 \mid 10\), so \(9 \equiv 19 \pmod{10}\)

\(46 \equiv -4 \pmod{50}\)

Solution

True, Because \(46 = 50 \cdot (1) + (-4)\) so \(46 \equiv -4 \pmod{50}\)

\(11 \equiv 5 \pmod{7}\)

Solution

False, Because \(11 = 7 \cdot 1 + 4\), so \(11 \equiv 4 \pmod{7}\)

Properties of Modular Arithmetic

If \(a \equiv b \pmod{n}\) and \(c \equiv d \pmod{n}\), then:

  • \(a + c \equiv b + d \pmod{n}\)
  • \(a - c \equiv b - d \pmod{n}\)
  • \(a \cdot c \equiv b \cdot d \pmod{n}\)
  • \(a^k \equiv b^k \pmod{n}\) for any \(k \in \mathbb{N}\)

Why use "\(\equiv\)" instead of "\(=\)"?

In modular arithmetic, we use the symbol "\(\equiv\)" (congruence) rather than "\(=\)" (equality) because:

  • The "\(=\)" sign means exact equality: the two numbers or expressions are exactly the same.

    Example:

    \(7 + 3 = 10\), the sum is exactly 10.

  • The "\(\equiv\)" sign means congruence modulo n: two numbers are congruent modulo \(n\) if they leave the same remainder when divided by \(n\).
    We write:
    $$ a \equiv b \pmod{n} $$ which is equivalent to
    $$ n \mid (a-b) $$ In other words, \(a\) and \(b\) have the same remainder modulo \(n\).

    Example:

    \(17 \equiv 5 \pmod{12}\)

    Because \(17 - 5 = 12\) is divisible by 12. Here, 17 and 5 are not equal, but they are congruent modulo 12.

  • Summary:

    • "\(=\)" → exact equality
    • "\(\equiv\)" → equality modulo \(n\) (same remainder)

Greatest Common Divisor (GCD)

The GCD of two integers \(a\) and \(b\) is the largest positive integer that divides both \(a\) and \(b\). Usually, we can write the GCD of \(a\) and \(b\) as \(\gcd(a, b)\)

Example:

\(\gcd(48, 18) = 6\)

Because \(18 = 2 \cdot 3^2\) and \(48 = 2^4 \cdot 3\). The common factors are \(2 \cdot 3 = 6\), so \(\gcd(48, 18) = 6\).

Coprime Numbers

Two integers \(a\) and \(b\) are called coprime (or relatively prime) if : $$ \gcd(a, b) = 1 $$ This means they share no common factors other than 1.

Examples:

15 and 28 are coprime:

  • Because \(15 = 3*5\) and \(28 = 7 \cdot 2 \cdot 2 = 7 \cdot 2^2\), 15 and 28 don't share common factor, \(\gcd(15, 28) = 1\), so 15 and 28 are coprime.

15 and 25 are NOT coprime:

  • Because \(15 = 3 *5\) and \(25=5 \cdot 5\), 15 and 25 have 5 in common factor, \(\gcd(15,25) = 5\), so 15 and 25 are NOT coprime.

Exercices

1| Calculate \(\gcd(125, 15)\)

Solution

We start by calculate the decomposition in prime factor of 125 and 15

  • \(125 = 5 * 25 = 5 * 5 * 5 = 5^3\)
  • \(15 = 5 * 3\)

125 and 15 has 5 in common, so \(\gcd(125, 15) = 5\)

2| are 840 and 945 coprime ?

Solution

We start by calculate \(\gcd(840, 945)\), the decomposition in prime factor of 840 and 945 are:

  • \(840 = 2 \cdot 420 = 2 \cdot 2 \cdot 210 = 2^2 \cdot 2 \cdot 105 = 2^3 \cdot 5 \cdot 21 =2^3 \cdot 5 \cdot 7 \cdot 3 = 2^3 \cdot 3 \cdot 5 \cdot 7\)
  • \(945 = 5 \cdot 189=5 \cdot 3 \cdot 63 = 5 \cdot 3 \cdot 3 \cdot 21 = 5 \cdot 3^2 \cdot 3 \cdot 7=3^3 \cdot 5 \cdot 7\)

840 and 945 have \(3, 5, 7\) in common, \(\gcd(840, 945) = 3 \cdot 5 \cdot 7 = 105\) so 840 and 945 are not coprime

3| are 840 and 121 coprime ?

Solution

We start by calculate \(\gcd(840, 121)\), the decomposition in prime factor of 840 and 121 are:

  • \(840 = 2 \cdot 420 = 2 \cdot 2 \cdot 210 = 2^2 \cdot 2 \cdot 105 = 2^3 \cdot 5 \cdot 21 =2^3 \cdot 5 \cdot 7 \cdot 3 = 2^3 \cdot 3 \cdot 5 \cdot 7\)
  • \(121 = 11\cdot11 = 11^2\)

840 and 121 don't have common factors, \(\gcd(840, 121) = 1\) so 840 and 121 are coprime.

Euclidean Algorithm

The Euclid's algorithm is an efficient method for computing the GCD of two integers.

The main idea of Euclid's algorithm is : $$ \gcd(a,b) = \gcd(b, a \bmod b) $$ The algorithm repeatedly replaces the larger number with the remainder of dividing the larger by the smaller, until one number becomes zero.

The algorithm is based on this key property :

Lemma: If \(a = bq + r\), then \(\gcd(a, b) = \gcd(b, r)\)

Proof sketch: - Any common divisor of \(a\) and \(b\) must also divide \(r = a - bq\) - Any common divisor of \(b\) and \(r\) must also divide \(a = bq + r\) - Therefore, the sets of common divisors are identical, so their GCD is the same

Step-by-Step Example

Let's compute \(\gcd(48, 21)\):

Step \(a\) \(b\) Remainder \(r\) (\(a \bmod b\)) Calculation
1 48 21 6 \(48 = 21 \cdot 2 + 6\)
2 21 6 3 \(21 = 6 \cdot 3 + 3\)
3 6 3 0 \(6 = 3 \cdot 2 + 0\)
4 3 0 0 Answer

When \(b = 0\), we stop. The GCD is \(a=3\), so \(\gcd(48, 21) = 3\).

Another Example

Let's compute \(\gcd(924, 630)\)

\[ \begin{aligned} 924 &= 630 \cdot 1 + 294\\ 630 &= 294 \cdot 2 + 42\\ 294 &= 42 \cdot 7 + 0 \end{aligned} \]

So \(\gcd(924, 630) = 42\)

Time Complexity

The Euclidean algorithm is really efficient. The time complexity is \(O(\log(\min(a, b)))\), where \(a\) and \(b\) are the two integers of which you are finding the Greatest Common Divisor.

For small numbers, finding the GCD via prime factorization works well. However, for large numbers (like in RSA), prime factorization becomes computationally infeasible. This is why we use the Euclidean Algorithm, which is efficient even for huge numbers.

Python Implementation

def gcd(a: int, b: int) -> int:
    """
    Compute the Greatest Common Divisor of a and b
    using the Euclidean Algorithm. If all arguments
    are zero, then the returned value is 0.

    Args:
        a (int): First integer
        b (int): Second integer

    Returns:
        int: The GCD of a and b (always positive)
    """
    # Absolute function
    a, b = abs(a), abs(b)
    while b != 0:
        a, b = b, a % b
    return a

The algorithm can also be written recursively:

def gcd(a: int, b: int) -> int:
    """
    Compute the Greatest Common Divisor of a and b
    using the Euclidean Algorithm. If all arguments
    are zero, then the returned value is 0.

    Args:
        a (int): First integer
        b (int): Second integer

    Returns:
        int: The GCD of a and b (always positive)
    """
    if b == 0:
        return abs(a)
    return gcd(b, a % b)

Python also provides a built-in function in the math module:

import math


math.gcd(39, 3) # returns 3

However, understanding the algorithm is crucial for the Extended Euclidean algorithm, which we'll need for RSA key generation.

Exercices

  • Compute \(\gcd(987, 462)\) by hand using the Euclidean Algorithm.
Solution

The Euclidean Algorithm:

\[ \begin{aligned} 987 &= 462 \cdot 2 + 63\\ 462 &= 63 \cdot 7 + 21\\ 63 &= 21 \cdot 3 + 0 \end{aligned} \]

So, \(\gcd(987, 462) = 21\)

Extended Euclidean Algorithm

The Extended Euclidean algorithm is an extension to the Euclidean algorithm, and computes, in addition the Greatest Common Divisor of integers \(a\) and \(b\), but also finds integers \(x\) and \(y\) such that: $$ ax + by = \gcd(a,b) $$ This equation is know as Bézout's Identity.

The Extended Euclidean Algorithm works by performing the Regular Euclidean Algorithm in the forward phase, then working backward to express the GCD as a linear combination of \(a\) and \(b\).

Step-by-Step Examples

Let's find \(x\) and \(y\) such that \(48x + 18y = \gcd(48, 18)\).

Forward Phase (Regular Euclidean Algorithm):

Step \(a\) \(b\) Quotient \(q\) Remainder \(r\) Calculation
1 48 18 2 12 \(48 = 18 \cdot 2 + 12\)
2 18 12 1 6 \(18 = 12 \cdot 1 + 6\)
3 12 6 2 0 \(12 = 6 \cdot 2 + 0\)

So \(\gcd(48, 18) = 6\)

Backward Phase (Finding coefficients): Now we work backwards to express 6 as a combination of 48 and 18:

From the penultimate equation:

\[ \begin{aligned} 18 = 12 \cdot 1 + 6 \leftrightarrow 6 &= 18 - 12\\ &= 18 - (48 - 18 \cdot 2)\\ &= 18 - 48 + 18 \cdot 2 \\ &= 18 \cdot 3 + 48 \cdot (-1)\\ &= 48 \cdot (-1) + 18 \cdot 3 \end{aligned} \]

So \(x = -1\), \(y = 3\)

Another example

Let's find \(x\) and \(y\) such that \(240x + 46y = \gcd(240, 46)\) Forward Phase:

\[ \begin{aligned} 240 &= 46 \cdot 5 + 10 \\ 46 &= 10 \cdot 4 + 6 \\ 10 &= 6 \cdot 1 + 4 \\ 6 &= 4 \cdot 1 + 2 \\ 4 &= 2 \cdot 2 + 0 \\ \end{aligned} \]

Backward Phase: From the penultimate equation:

\[ \begin{aligned} 6 = 4 \cdot 1 + 2 \leftrightarrow 2 &= 6 - 4\\ &= (46 -10 \cdot 4) - (10 - 6)\\ &= (46 - 10 \cdot 4) - (10 - (46 - 10 \cdot 4))\\ &= 46 - 10 \cdot 4 - 10 + 46 - 10 \cdot 4 \\ &= 2 \cdot 46 - 10 \cdot 9 \\ &= 2 \cdot 46 - (240 - 46 \cdot 5 ) \cdot 9 \\ &= 2 \cdot 46 - 240 \cdot 9 + 46 \cdot 45 \\ &= 240 \cdot (-9) + 46 \cdot 47 \end{aligned} \]

so \(x = -9\) and \(y=47\).

Python implementation

One easy way to implement the Extended Euclidean algorithm is recursively:

def extended_euclidean(a: int, b: int) -> tuple[int, int, int]:
    """
    Computes the GCD of two integers a and b, as well as the coefficients x and y
    of Bézout's identity: a * x + b * y = gcd(a, b).

    Args:
        a (int): The first integer.
        b (int): The second integer.

    Returns:
        tuple[int, int, int]: A tuple containing:
            - gcd (int): the greatest common divisor of a and b,
            - x (int): the coefficient of a in Bézout's identity,
            - y (int): the coefficient of b in Bézout's identity.
    """
    if b == 0:
        return a, 1, 0
    else:
        gcd, x, y = extended_euclidean(b, a % b)
        x, y = y, x - (a // b) * y
        return gcd, x, y

it also possible to implement it in a iterative way:

def extended_euclidean(a: int, b: int) -> tuple[int, int, int]:
    """
    Computes the GCD of two integers a and b, as well as the coefficients x and y
    of Bézout's identity: a * x + b * y = gcd(a, b).

    Args:
        a (int): The first integer.
        b (int): The second integer.

    Returns:
        tuple[int, int, int]: A tuple containing:
            - gcd (int): the greatest common divisor of a and b,
            - x (int): the coefficient of a in Bézout's identity,
            - y (int): the coefficient of b in Bézout's identity.
    """
    x0, x1, y0, y1 = 1, 0, 0, 1
    while b:
        q, a, b = a // b, b, a % b
        x0, x1 = x1, x0 - q * x1
        y0, y1 = y1, y0 - q * y1

    return a, x0, y0

Exercices

1| Find \(x\) and \(y\) such that \(120x + 45y = \gcd(120, 45)\)

Solution

Let's find \(x\) and \(y\) such that \(120x + 45y = \gcd(120, 45)\)

Forward Phase:

\[ \begin{aligned} 120 &= 45 \cdot 2 + 30 \\ 45 &= 30 \cdot 1 + 15 \\ 30 &= 15 \cdot 2 + 0 \end{aligned} \]

Backward Phase:

\[ \begin{aligned} 15 &= 45 - 30 \\ &= 45 - (120 - 45 \cdot 2) \\ &= -120 + 45 \cdot 3 \end{aligned} \]

So \(x = -1\) and \(y = 3\).

2| Find \(x\) and \(y\) such that \(21x + 14y = gcd(21, 14)\)

Solution

Let's find \(x\) and \(y\) such that \(21x + 14y = \gcd(21, 14)\)

Forward Phase:

\[ \begin{aligned} 21 &= 14 \cdot 1 + 7 \\ 14 &= 7 \cdot 2 + 0 \end{aligned} \]

Backward Phase:

\[ \begin{aligned} 7 &= 21 - 14 \\ &= 21 \cdot 1 + 14 \cdot (-1) \end{aligned} \]

So \(x = 1\) and \(y = -1\).

Modular Inverse

The Modular Inverse of \(a\) modulo \(n\) is an integer \(x\) such that: $$ a \cdot x \equiv 1 \pmod{n} $$ We write: $$ x \equiv a^{-1} \pmod{n} $$

Example:

\(3 \cdot 5 = 15 \equiv 1 \pmod{7}\), So \(3^{-1} \equiv 5 \pmod{7}\)

Existence and Uniqueness

Existence: The modular inverse exists if and only if \(\gcd(a, n) = 1\) - If \(\gcd(a, n) \neq 1\), then \(a^{-1}\pmod{n}\) doesn't exist

Uniqueness: When the inverse exists, it is unique modulo \(n\) - This means there is exactly one value \(x\) in the set \(\{1, 2, \dots, n-1\}\) such that \(a \cdot x \equiv 1 \pmod{n}\) - Any other solution is congruent to this value modulo \(n\)

Why not 0? Note that \(0\) is excluded because \(a \cdot 0 = 0 \not\equiv 1 \pmod{n}\) for any \(a\).

Formally: $$ \exists! x \in {1, 2, \dots, n-1} \text{ such that } ax \equiv 1 \pmod{n} $$

Computing Modular Inverses

There are several methods to compute modular inverses:

Brute Force

For small moduli, we can try all values in \(\left\{1, \dots, n-1\right\}\) until we find one that satisfies \(a \cdot x \equiv 1 \pmod{n}\).

Example

Find \(7^{-1} \pmod{11}\) We test each value systematically:

\(x\) \(7 \cdot x\) \(7 \cdot x \bmod 11\) Is it \(\equiv 1\)?
1 7 7 No
2 14 3 No
3 21 10 No
4 28 6 No
5 35 2 No
6 42 9 No
7 49 5 No
8 56 1 Yes

Therefore, \(7^{-1} \equiv 8 \pmod{11}\)

Verification: \(7 \cdot 8 = 56 = 11 \cdot 5 + 1 \equiv 1 \pmod{11}\)

Python Implementation
def modular_inverse_brute_force(a: int, n: int) -> int:
    """
    Compute the modular inverse of a modulo n using brute force.
    Only practical for small values of n.

    Args:
        a (int): The integer whose inverse is sought
        n (int): The modulus

    Returns:
        int: The modular inverse of a modulo n

    Raises:
        ValueError: If the inverse doesn't exist (gcd(a,n) ≠ 1)
    """
    a = a % n  # Normalize a to be in range [0, n-1]

    # Try all possible values from 1 to n-1
    for x in range(1, n):
        if (a * x) % n == 1:
            return x

    # If we reach here, no inverse was found
    raise ValueError(f"Modular inverse doesn't exist: gcd({a}, {n}) ≠ 1")

Extended Euclidean Algorithm

The most efficient method is using the Extended Euclidean Algorithm (see Extended Euclidean Algorithm).

The Extended Euclidean algorithm finds integers \(x\) and \(y\) such that: $$ ax + ny = \gcd(a, n) $$If \(\gcd(a, n) = 1\), then: $$ ax + ny = 1 \leftrightarrow ax \equiv 1 \pmod{n} $$

So \(x\) is the modular inverse of \(a\) modulo \(n\)!

Python Implementation
def modular_inverse(a: int, n: int) -> int:
    """
    Compute the modular inverse of a modulo n using Extended Euclidean Algorithm.

    Args:
        a (int): The integer whose inverse is sought
        n (int): The modulus

    Returns:
        int: The modular inverse of a modulo n

    Raises:
        ValueError: If gcd(a,n) ≠ 1 (inverse doesn't exist)
    """
    gcd, x, y = extended_euclidean(a, n)

    if gcd != 1:
        raise ValueError(f"Modular inverse doesn't exist: gcd({a}, {n}) = {gcd} ≠ 1")

    return x % n  # Ensure positive result

Python provides an easy way to compute modular inverses using the Euclidean Algorithm:

# To compute the modular inverse of a mod n
pow(a, -1, n)

Examples

1 | Find \(3^{-1} \pmod{7}\) We need \(3x \equiv 1 \pmod{7}\)

Testing values:

\[ \begin{aligned} 3 \cdot 1 = 3 &\not\equiv 1 \pmod{7} \\ 3 \cdot 2 = 6 &\not\equiv 1 \pmod{7}\\ \vdots\\\ 3 \cdot 5 = 15 &\equiv 1 \pmod{7} \end{aligned} \]

So, \(3^{-1} \equiv 5 \pmod{7}\) This is the unique solution in \(\{1, 2, 3, 4, 5, 6\}\).

Note

\(3 \times 12 = 36 \equiv 1 \pmod{7}\) is also true, but \(12 \equiv 5 \pmod{7}\), so it's the same solution.

2| Find \(7^{-1} \pmod{26}\) We check that 7 is coprime with 26: $$ \gcd(26, 7) = 1 $$

We need to find \(x\) such that \(7x \equiv 1 \pmod{26}\). \(x\) is necesseraly congru to one of the integers of \(\left\{0, 1,2, \dots, 25\right\} \pmod{26}\).

\[ \begin{aligned} 7 \cdot 1 = 7 &\not\equiv 1 \pmod{26}\\ 7 \cdot 2 = 14 &\not\equiv 1 \pmod{26}\\ \vdots\\\ 7 \cdot 15 = 105 &\equiv 1 \pmod{26}\\ \end{aligned} \]

So, \(7^{-1} \equiv 15 \pmod{26}\) This is the unique solution in \(\{1, 2, \dots, 25\}\).

Note

\(119 \equiv 1 \pmod{26}\) is also true, but \(119 \equiv 15 \pmod{26}\), so it's the same solution.

3| Does \(3^{-1} \pmod{12}\) exists ? We check that 3 is coprime with 12: $$ \gcd(3, 12) = 3 $$ Since \(\gcd(3, 12) = 3 \neq 1\), the modular inverse does not exist. There is no integer \(x\) such that \(3x \equiv 1 \pmod{12}\).

← Previous Next →