Exercise 2.9.4 (Modular square roots)

With the aid of a pocket calculator, use RESSOL to find solutions of the following congruences:

( a ) x 2 10 ( mod 13 ) ; ( b ) x 2 5 ( mod 19 ) ; ( c ) x 2 3 ( mod 11 ) ; ( d ) x 2 7 ( mod 29 ) .

Answers

Proof.

(a)
Here p = 13 and a = 10 . Note that p 1 = 12 = 2 2 3 = 2 k m , where k = 2 , m = 3 . Starting from ( a m + 1 2 ) 2 = a a m , we obtain r 2 an ( mod p ) , (1)

where r = a m + 1 2 = 1 0 2 9 ( mod 13 ) , and n = a m = 1000 1 ( mod 13 ) .

We choose a generator quadratic non residue z . Since 2 6 ( 2 13 ) = 1 ( mod 13 ) , we take z = 2 .

(Then z ¯ is a generator of ( 13 ) , and c ¯ = z ¯ m = 2 ¯ 3 = 8 ¯ is a generator of the subgroup of elements whose order is a power of 2 .)

The order of c m = 8 is 2 k = 2 2 . The order of n 1 ( mod 13 ) is 2 .

(Since n 2 = n 2 k 1 a p 1 2 = 1 , we verify anew that a is a quadratic residue.)

Therefore n and c 2 have the same order 2 1 . Multiplying (1) by c 2 , we obtain

( rc ) 2 a ( n c 2 ) ( mod p ) ,

that is r 1 2 a n 1 ( mod p ) , where r 1 = rc 7 ( mod 13 ) , and n 1 = n c 2 must have order 2 k 1 , with k 1 < 1 . Indeed, n 1 = 8 2 1 ( mod 13 ) .

Therefore 7 2 10 ( mod 13 ) , and 7 is a square root of 10 modulo 13 . The other root is 7 6 ( mod 13 ) .

Verification: 7 2 = 49 = 3 × 13 + 10 .

(b)
Similarly, for the equation x 2 5 ( mod 19 ) , we obtain z = 3 , c = 1 , and n 1 , r 9 ( mod 19 ) . Since n = 1 , there is no loop, and the roots of 5 modulo 19 are ± 9 .
(c)
With z = 6 , c = 10 , we obtain n = 1 , r = 5 . No loop : ± 5 are the roots of 3 modulo 11 .

Note: in the cases (b) and (c), we have p 3 ( mod 4 ) , thus the roots are given by ± a p + 1 4 .

(d)
With z = 8 , c = 17 , we obtain n = 1 , r = 23 , thus 6 , 23 are the roots of 7 modulo 29 .

A Python code to implement the RESSOL algorithm is

from random import randint

def legendre(a, p):
    resu = pow(a, (p - 1) // 2, p)
    if resu > p//2:
        resu -= p
    return resu

def ressol(a, p):
    assert legendre(a, p) == 1, "not a square (mod p)"

    m = p - 1
    s = 0
    while m % 2 == 0:
        m //= 2
        s += 1

    found = False
    while not found:
        xi = randint(2, p - 2)
        if -1 == legendre(xi, p):
            found = True

    c = pow(xi, m , p)                      # o(c) = 2^s
    r = pow(a, (m+1) // 2, p)
    n = pow(a, m, p)
    while n!=1:
        i = 0
        npower = n
        while npower != 1:
            npower = (npower * npower) % p
            i = i + 1
                                            # o(n) = 2^i
        b = pow(c, 2 ** (s-i-1), p)         # o(b^2) = 2^i = o(n)
        r = (r * b) % p
        n = (n * b * b) % p
    return(r)

if __name__ == ’__main__’:
    print(ressol(43,97))

User profile picture
2024-05-18 09:25
Comments