First commit
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from Cryptotools.Numbers.primeNumber import gcd, isPrimeNumber
|
||||
from Cryptotools.lcm import lcm
|
||||
from Cryptotools.Numbers.coprime import phi
|
||||
from Cryptotools.Utils.utils import gcd
|
||||
from sympy import factorint
|
||||
from functools import reduce
|
||||
|
||||
|
||||
def carmichael_lambda(n: int) -> int:
|
||||
"""
|
||||
This function is a carmichael lambda for identifying the smallest integer m
|
||||
and saisfy this condition: a ** m congrue 1 modulo n
|
||||
This function is relatively closed with the euler's totient (phi of n)
|
||||
|
||||
Args:
|
||||
n (Integer): found the smallest integer of n
|
||||
|
||||
Returns:
|
||||
REturn the smallest integer of n
|
||||
"""
|
||||
|
||||
# First, factorizing n number
|
||||
# factorint return a list of prime factors of n
|
||||
# Base on that theorem:
|
||||
# https://en.wikipedia.org/wiki/Fundamental_theorem_of_arithmetic
|
||||
factorsN = factorint(n)
|
||||
|
||||
"""
|
||||
The result of the factorint, we have the following:
|
||||
n = p ** e1, p ** e2, ..., p ** ek
|
||||
"""
|
||||
|
||||
factors = list()
|
||||
|
||||
for p, e in factorsN.items():
|
||||
# Base on the theorem of arithmetic, p is always prime
|
||||
if isPrimeNumber(p):
|
||||
if p == 2 and e >= 3:
|
||||
factors.append(phi(pow(p, e)) // 2)
|
||||
elif p >= 2 and e > 0:
|
||||
factors.append(phi(pow(p, e)))
|
||||
elif p > 2:
|
||||
factors.append(phi(pow(p, e)))
|
||||
|
||||
# Now, we can compute lcm
|
||||
result = reduce(lcm, factors)
|
||||
|
||||
return result
|
||||
|
||||
def carmichael_lambda2(n):
|
||||
"""
|
||||
Deprecated function
|
||||
"""
|
||||
# Get all coprimes with n
|
||||
coprimes = list()
|
||||
for a in range(1, n):
|
||||
if gcd(a, n) == 1:
|
||||
coprimes.append(a)
|
||||
|
||||
# Need to find the smallest value
|
||||
"""
|
||||
Need to find the smallest value m. Must to satisfy this condition:
|
||||
a ** m congrus 1 mod n
|
||||
"""
|
||||
for m in range(1, n):
|
||||
print(f"{m} {a ** m % n}")
|
||||
|
||||
print(coprimes)
|
||||
|
||||
def carmi_numbers(n):
|
||||
"""
|
||||
This function get all GCD of the number if these number are prime or not
|
||||
|
||||
Args:
|
||||
n (Integer): Iterate to n elements
|
||||
|
||||
Returns:
|
||||
Return a list of prime numbers
|
||||
"""
|
||||
# https://kconrad.math.uconn.edu/blurbs/ugradnumthy/carmichaelkorselt.pdf
|
||||
primes = list()
|
||||
for i in range(2, n - 1):
|
||||
if gcd(n, i) == i:
|
||||
if isPrimeNumber(i):
|
||||
primes.append(i)
|
||||
|
||||
return primes
|
||||
|
||||
def is_carmichael(n, primes):
|
||||
"""
|
||||
This function check if the n number is a carmichael number. The arguments primes at least 3 prime numbers
|
||||
As it's said in the Carmichael theorem, a carmichael number has three factors and they are all primes: https://en.wikipedia.org/wiki/Carmichael_number
|
||||
With the Korselt's criterion, to check if the number is a carmichael number p - 1 / n - 1.
|
||||
|
||||
Args:
|
||||
n (Integer): the carmichael number
|
||||
primes (list): list of prime numbers
|
||||
|
||||
Returns:
|
||||
Boolean of the carmichael's number result
|
||||
"""
|
||||
r = True
|
||||
n = n - 1
|
||||
|
||||
if len(primes) < 3:
|
||||
return False
|
||||
|
||||
# Korselt's criterion
|
||||
for p in primes:
|
||||
p = p - 1
|
||||
if n % p != 0:
|
||||
r = False
|
||||
break
|
||||
return r
|
||||
|
||||
def is_carmi_number(n) -> bool:
|
||||
"""
|
||||
This function check if the number n is a carmichael number (pseudoprime)
|
||||
|
||||
Args:
|
||||
n (Integer): Iterate to n elements
|
||||
|
||||
Returns:
|
||||
Return a Boolean if n is a carmichael number or not. True if yes
|
||||
"""
|
||||
j = 0
|
||||
for i in range(n):
|
||||
if i ** n % n == i:
|
||||
j += 1
|
||||
if j == n:
|
||||
return True
|
||||
return False
|
||||
|
||||
def generate_carmi_numbers(nbr) -> list:
|
||||
"""
|
||||
This function generate carmichael numbers, they are called pseudoprimes
|
||||
For instance: a = 545, n = 561
|
||||
gcd(a, n) = 1
|
||||
pow(a, n - 1) % n = 1
|
||||
|
||||
Args:
|
||||
nbr (Integer): Find all pseudoprimes until nbr is achieves
|
||||
|
||||
Returns:
|
||||
Return the list of pseudoprimes
|
||||
"""
|
||||
carmi = list()
|
||||
|
||||
count = 0
|
||||
n = 2
|
||||
while count < nbr:
|
||||
# First, we need to find a, coprime with n
|
||||
for a in range(1, n):
|
||||
# We check if n is coprime with a
|
||||
# All integers must be coprime with n, a belong to n
|
||||
if gcd(a, n) == 1:
|
||||
# Check if is a carmichael number
|
||||
# Fermat's little theorem, a ** (n - 1) % n, must be congruent to 1
|
||||
if pow(a, (n - 1)) % n == 1:
|
||||
#if (a ** (n - 1)) % n == 1:
|
||||
#print(f"{gcd(a, n)} {a} {n}")
|
||||
if n not in carmi:
|
||||
count += 1
|
||||
carmi.append(n)
|
||||
else:
|
||||
print(f"{gcd(a, n)} {a} {n}")
|
||||
|
||||
break
|
||||
n += 1
|
||||
print(carmi)
|
||||
#for cop in range(2, n):
|
||||
# if gcd(cop, n) == 1:
|
||||
# coprimes.append(cop)
|
||||
|
||||
return carmi
|
||||
Reference in New Issue
Block a user