First commit
This commit is contained in:
commit
50f7b1159e
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
__pycache__/
|
||||||
|
build/**
|
||||||
|
Cryptotools.egg-info/**
|
||||||
|
dist/**
|
||||||
|
**.swp
|
||||||
6
Cryptotools/Cryptotools.egg-info/PKG-INFO
Normal file
6
Cryptotools/Cryptotools.egg-info/PKG-INFO
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: Cryptotools
|
||||||
|
Version: 1.0
|
||||||
|
Summary: Cryptography library
|
||||||
|
Author: Geoffrey Bucchino
|
||||||
|
Author-email: contact@bucchino.org
|
||||||
13
Cryptotools/Cryptotools.egg-info/SOURCES.txt
Normal file
13
Cryptotools/Cryptotools.egg-info/SOURCES.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
README.md
|
||||||
|
setup.py
|
||||||
|
Cryptotools/Cryptotools.egg-info/PKG-INFO
|
||||||
|
Cryptotools/Cryptotools.egg-info/SOURCES.txt
|
||||||
|
Cryptotools/Cryptotools.egg-info/dependency_links.txt
|
||||||
|
Cryptotools/Cryptotools.egg-info/top_level.txt
|
||||||
|
Cryptotools/Numbers/__init__.py
|
||||||
|
Cryptotools/Numbers/carmi.py
|
||||||
|
Cryptotools/Numbers/numbers.py
|
||||||
|
Cryptotools/Numbers/primeNumber.py
|
||||||
|
tests/test_carmi.py
|
||||||
|
tests/test_numbers.py
|
||||||
|
tests/test_phi.py
|
||||||
1
Cryptotools/Cryptotools.egg-info/dependency_links.txt
Normal file
1
Cryptotools/Cryptotools.egg-info/dependency_links.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
1
Cryptotools/Cryptotools.egg-info/top_level.txt
Normal file
1
Cryptotools/Cryptotools.egg-info/top_level.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Numbers
|
||||||
174
Cryptotools/Encryptions/RSA.py
Normal file
174
Cryptotools/Encryptions/RSA.py
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.coprime import phi
|
||||||
|
from Cryptotools.Numbers.carmi import carmichael_lambda
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
from Cryptotools.Numbers.primeNumber import getPrimeNumber
|
||||||
|
from sys import getsizeof
|
||||||
|
|
||||||
|
class RSAKey:
|
||||||
|
"""
|
||||||
|
This class store the RSA key with the modulus associated
|
||||||
|
The key is a tuple of the key and the modulus n
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
key: It's the exponent key, can be public or private
|
||||||
|
modulus: It's the public modulus
|
||||||
|
length: It's the key length
|
||||||
|
"""
|
||||||
|
def __init__(self, key, modulus, length):
|
||||||
|
"""
|
||||||
|
Contain the RSA Key. An object of RSAKey can be a public key or a private key
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key (Integer): it's the exponent of the key
|
||||||
|
modulus (Integer): it's the public modulus of the key
|
||||||
|
length (Integer): length of the key
|
||||||
|
"""
|
||||||
|
|
||||||
|
self._key = key
|
||||||
|
self._modulus = modulus
|
||||||
|
self._length = length
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key(self):
|
||||||
|
return self._key
|
||||||
|
|
||||||
|
@property
|
||||||
|
def modulus(self):
|
||||||
|
return self._modulus
|
||||||
|
|
||||||
|
@property
|
||||||
|
def length(self):
|
||||||
|
return self.length
|
||||||
|
|
||||||
|
class RSA:
|
||||||
|
"""
|
||||||
|
This class generate public key based on RSA algorithm
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
p: it's the prime number for generating the modulus
|
||||||
|
q: it's the second prime number for the modulus
|
||||||
|
public: Object of the RSAKey which is the public key
|
||||||
|
private: Object of the RSAKey for the private key
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
Build a RSA Key
|
||||||
|
"""
|
||||||
|
self._p = None
|
||||||
|
self._q = None
|
||||||
|
self._public = None
|
||||||
|
self._private = None
|
||||||
|
|
||||||
|
def generateKeys(self, size=512):
|
||||||
|
"""
|
||||||
|
This function generate both public and private keys
|
||||||
|
Args:
|
||||||
|
size: It's the size of the key and must be multiple of 64
|
||||||
|
"""
|
||||||
|
# p and q must be coprime
|
||||||
|
self._p = getPrimeNumber(size)
|
||||||
|
self._q = getPrimeNumber(size)
|
||||||
|
|
||||||
|
# compute n = pq
|
||||||
|
n = self._p * self._q
|
||||||
|
|
||||||
|
phin = (self._p - 1) * (self._q - 1)
|
||||||
|
|
||||||
|
# e must be coprime with phi(n)
|
||||||
|
# According to the FIPS 186-5, the public key exponent must be odd
|
||||||
|
# and the minimum size is 65536 (Cf. Section 5.4 PKCS #1)
|
||||||
|
# https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
|
||||||
|
e = 65535 # Works
|
||||||
|
for i in range(2, phin - 1):
|
||||||
|
if gcd(phin, e) == 1:
|
||||||
|
break
|
||||||
|
e += 1
|
||||||
|
# print(gcd(phin, e))
|
||||||
|
self._public = RSAKey(e, n, getsizeof(e))
|
||||||
|
|
||||||
|
# d is the reverse modulo of phi(n)
|
||||||
|
# d = self._inverseModular(e, phin)
|
||||||
|
d = pow(e, -1, phin) # Works in python 3.8
|
||||||
|
self._private = RSAKey(d, n, getsizeof(d))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def e(self):
|
||||||
|
return self._public.key
|
||||||
|
|
||||||
|
@property
|
||||||
|
def d(self):
|
||||||
|
return self._private.key
|
||||||
|
|
||||||
|
@property
|
||||||
|
def n(self):
|
||||||
|
return self._public.modulus
|
||||||
|
|
||||||
|
@property
|
||||||
|
def p(self):
|
||||||
|
return self._p
|
||||||
|
|
||||||
|
@property
|
||||||
|
def q(self):
|
||||||
|
return self._q
|
||||||
|
|
||||||
|
def encrypt(self, data) -> list:
|
||||||
|
"""
|
||||||
|
This function return a list of data encrypted with the public key
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (str): it's the plaintext which need to be encrypted
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
return a list of the data encrypted, each entries contains the value encoded
|
||||||
|
"""
|
||||||
|
dataEncoded = self._str2bin(data)
|
||||||
|
return list(
|
||||||
|
pow(int(x), self._public.key, self._public.modulus)
|
||||||
|
for x in dataEncoded
|
||||||
|
)
|
||||||
|
|
||||||
|
def decrypt(self, data) -> list:
|
||||||
|
"""
|
||||||
|
This function return a list decrypted with the private key
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data (str): It's the encrypted data which need to be decrypted
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the list of data uncrypted into plaintext
|
||||||
|
"""
|
||||||
|
decrypted = list()
|
||||||
|
for x in data:
|
||||||
|
d = pow(x, self._private.key, self._private.modulus)
|
||||||
|
decrypted.append(chr(d))
|
||||||
|
return ''.join(decrypted)
|
||||||
|
|
||||||
|
def _str2bin(self, data) -> list:
|
||||||
|
"""
|
||||||
|
This function convert a string into the unicode value
|
||||||
|
|
||||||
|
Args:
|
||||||
|
data: the string which need to be converted
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of unicode values of data
|
||||||
|
"""
|
||||||
|
return list(ord(x) for x in data)
|
||||||
|
|
||||||
|
def _inverseModular(self, a, n):
|
||||||
|
"""
|
||||||
|
This function compute the modular inverse for finding d, the decryption key
|
||||||
|
|
||||||
|
Args:
|
||||||
|
a (Integer): the base of the exponent
|
||||||
|
n (Integer): the modulus
|
||||||
|
"""
|
||||||
|
for b in range(1, n):
|
||||||
|
#if pow(a, b, n) == 1:
|
||||||
|
if (a * b) % n == 1:
|
||||||
|
inv = b
|
||||||
|
break
|
||||||
|
return inv
|
||||||
1
Cryptotools/Encryptions/__init__.py
Normal file
1
Cryptotools/Encryptions/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
1
Cryptotools/Groups/__init__.py
Normal file
1
Cryptotools/Groups/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
91
Cryptotools/Groups/cyclic.py
Normal file
91
Cryptotools/Groups/cyclic.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.group import Group
|
||||||
|
|
||||||
|
|
||||||
|
class Cyclic(Group):
|
||||||
|
"""
|
||||||
|
This object contain a list of the Group for a cyclic group. This class find all generator of the group.
|
||||||
|
This class is inherited from Group object
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
G (list): list of all elements in the group
|
||||||
|
n (Integer): it's the value where the group has been generated
|
||||||
|
operation (Function): it's the operation generating the group
|
||||||
|
generators (list): contain all generators of the group
|
||||||
|
generatorChecked (boolean): Check if generators has been found
|
||||||
|
"""
|
||||||
|
def __init__(self, G:list, n, ope):
|
||||||
|
super().__init__(n, G, ope) # Call the Group's constructor
|
||||||
|
self._G = G
|
||||||
|
self._n = n
|
||||||
|
self._operation = ope
|
||||||
|
self._generators = list()
|
||||||
|
self._generatorChecked = False
|
||||||
|
|
||||||
|
def generator(self):
|
||||||
|
"""
|
||||||
|
This function find all generators in the group G
|
||||||
|
"""
|
||||||
|
|
||||||
|
index = 1
|
||||||
|
G = sorted(self._g)
|
||||||
|
for g in range(2, self._n):
|
||||||
|
z = list()
|
||||||
|
for entry in range(1, self._n):
|
||||||
|
res = self._operation(g, index, self._n)
|
||||||
|
if res not in z:
|
||||||
|
z.append(res)
|
||||||
|
index = index + 1
|
||||||
|
|
||||||
|
# We check if that match with G
|
||||||
|
# If yes, we find a generator
|
||||||
|
if sorted(z) == G:
|
||||||
|
self._generators.append(g)
|
||||||
|
self._generatorChecked = True
|
||||||
|
|
||||||
|
def getPrimitiveRoot(self):
|
||||||
|
"""
|
||||||
|
This function return the primitive root modulo of n
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the primitive root of the group. None if no primitive has been found
|
||||||
|
"""
|
||||||
|
|
||||||
|
index = 1
|
||||||
|
G = sorted(self._g)
|
||||||
|
for g in range(2, self._n):
|
||||||
|
z = list()
|
||||||
|
for entry in range(1, self._n):
|
||||||
|
res = self._operation(g, index, self._n)
|
||||||
|
if res not in z:
|
||||||
|
z.append(res)
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
# If the group is the same has G, we found a generator
|
||||||
|
if sorted(z) == G:
|
||||||
|
return g
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getGenerators(self) -> list:
|
||||||
|
"""
|
||||||
|
This function return all generators of that group
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the list of generators found. The function generators() must be called before to call this function
|
||||||
|
"""
|
||||||
|
if not self._generatorChecked:
|
||||||
|
self.generator()
|
||||||
|
self._generatorChecked = True
|
||||||
|
return self._generators
|
||||||
|
|
||||||
|
def isCyclic(self) -> bool:
|
||||||
|
"""
|
||||||
|
Check if the group is a cyclic group, means we have at least one generator
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
REturn a boolean, False if the group is not Cyclic otherwise return True
|
||||||
|
"""
|
||||||
|
if len(self.getGenerators()) == 0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
227
Cryptotools/Groups/galois.py
Normal file
227
Cryptotools/Groups/galois.py
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.group import Group
|
||||||
|
|
||||||
|
|
||||||
|
class Galois:
|
||||||
|
"""
|
||||||
|
This class contain the Galois Field (Finite Field)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
q (Integer): it's the number of the GF
|
||||||
|
operation (Function): Function for generating the group
|
||||||
|
identityAdd (Integer): it's the identity element in the GF(n) for the addition operation
|
||||||
|
identityMul (Integer): it's the identity element in the GF(n) for the multiplicative operation
|
||||||
|
"""
|
||||||
|
def __init__(self, q, operation):
|
||||||
|
self._q = q
|
||||||
|
self._operation = operation
|
||||||
|
self._identityAdd = 0
|
||||||
|
self._identityMul = 1
|
||||||
|
self._F = [x for x in range(q)]
|
||||||
|
self._add = [[0 for x in range(q)] for y in range(q)]
|
||||||
|
|
||||||
|
# TODO: May do we do a deep copy between all groups ?
|
||||||
|
self._div = [[0 for x in range(q)] for y in range(q)]
|
||||||
|
self._mul = [[0 for x in range(q)] for y in range(q)]
|
||||||
|
self._sub = [[0 for x in range(q)] for y in range(q)]
|
||||||
|
self._primitiveRoot = list()
|
||||||
|
|
||||||
|
def primitiveRoot(self):
|
||||||
|
"""
|
||||||
|
In this function, we going to find the primitive root modulo n of the galois field
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the list of primitive root of the GF(q)
|
||||||
|
"""
|
||||||
|
for x in range(2, self._q):
|
||||||
|
z = list()
|
||||||
|
for entry in range(1, self._q):
|
||||||
|
res = self._operation(x, entry, self._q)
|
||||||
|
if res not in z:
|
||||||
|
z.append(res)
|
||||||
|
|
||||||
|
if self.isPrimitiveRoot(z, self._q - 1):
|
||||||
|
if x not in self._primitiveRoot: # It's dirty, need to find why we have duplicate entry
|
||||||
|
self._primitiveRoot.append(x)
|
||||||
|
return z
|
||||||
|
|
||||||
|
def getPrimitiveRoot(self):
|
||||||
|
"""
|
||||||
|
Return the list of primitives root
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the primitive root
|
||||||
|
"""
|
||||||
|
return self._primitiveRoot
|
||||||
|
|
||||||
|
def isPrimitiveRoot(self, z, length):
|
||||||
|
"""
|
||||||
|
Check if z is a primitive root
|
||||||
|
|
||||||
|
Args:
|
||||||
|
z (list): check if z is a primitive root
|
||||||
|
length (Integer): Length of the GF(q)
|
||||||
|
"""
|
||||||
|
if len(z) == length:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def add(self):
|
||||||
|
"""
|
||||||
|
This function do the operation + on the Galois Field
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of the group with the addition operation
|
||||||
|
"""
|
||||||
|
for x in range(0, self._q):
|
||||||
|
for y in range(0, self._q):
|
||||||
|
self._add[x][y] = (x + y) % self._q
|
||||||
|
return self._add
|
||||||
|
|
||||||
|
def _inverseModular(self, a, n):
|
||||||
|
"""
|
||||||
|
This function find the reverse modular of a by n
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the reverse modular
|
||||||
|
"""
|
||||||
|
for b in range(1, n):
|
||||||
|
if (a * b) % n == 1:
|
||||||
|
inv = b
|
||||||
|
break
|
||||||
|
return inv
|
||||||
|
|
||||||
|
def div(self):
|
||||||
|
"""
|
||||||
|
This function do the operation / on the Galois Field
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of the group with the division operation
|
||||||
|
"""
|
||||||
|
for x in range(1, self._q):
|
||||||
|
for y in range(1, self._q):
|
||||||
|
inv = self._inverseModular(y, self._q)
|
||||||
|
|
||||||
|
self._div[x][y] = (x * inv) % self._q
|
||||||
|
return self._div
|
||||||
|
|
||||||
|
def mul(self):
|
||||||
|
"""
|
||||||
|
This function do the operation * on the Galois Field
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of the group with the multiplication operation
|
||||||
|
"""
|
||||||
|
for x in range(0, self._q):
|
||||||
|
for y in range(0, self._q):
|
||||||
|
self._mul[x][y] = (x * y) % self._q
|
||||||
|
return self._mul
|
||||||
|
|
||||||
|
def sub(self):
|
||||||
|
"""
|
||||||
|
This function do the operation - on the Galois Field
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of the group with the subtraction operation
|
||||||
|
"""
|
||||||
|
for x in range(0, self._q):
|
||||||
|
for y in range(0, self._q):
|
||||||
|
self._sub[x][y] = (x - y) % self._q
|
||||||
|
return self._sub
|
||||||
|
|
||||||
|
def check_closure_law(self, arithmetic):
|
||||||
|
"""
|
||||||
|
This function check the closure law.
|
||||||
|
By definition, every element in the GF is an abelian group, which respect the closure law: for a and b belongs to G, a + b belongs to G, the operation is a binary operation
|
||||||
|
|
||||||
|
Args:
|
||||||
|
Arithmetics (str): contain the operation to be made, must be '+', '*', '/' or /-'
|
||||||
|
"""
|
||||||
|
if arithmetic not in ['+', '*', '/', '-']:
|
||||||
|
raise Exception("The arithmetic need to be '+', '*', '/' or '-'")
|
||||||
|
|
||||||
|
if arithmetic == '+':
|
||||||
|
G = self._add
|
||||||
|
elif arithmetic == '*':
|
||||||
|
G = self._mul
|
||||||
|
elif arithmetic == '/':
|
||||||
|
G = self._div
|
||||||
|
else:
|
||||||
|
G = self._sub
|
||||||
|
|
||||||
|
start = 0
|
||||||
|
"""
|
||||||
|
In case of multiplicative, we bypass the first line, because all elements are zero, otherwise the test fail
|
||||||
|
"""
|
||||||
|
if arithmetic == '*' or arithmetic == '/':
|
||||||
|
start = 1
|
||||||
|
|
||||||
|
isClosure = True
|
||||||
|
for x in range(start, self._q):
|
||||||
|
gr = Group(self._q, G[x], self._operation)
|
||||||
|
if not gr.closure():
|
||||||
|
isClosure = False
|
||||||
|
del gr
|
||||||
|
|
||||||
|
if isClosure:
|
||||||
|
print(f"The group {arithmetic} respect closure law")
|
||||||
|
else:
|
||||||
|
print(f"The group {arithmetic} does not respect closure law")
|
||||||
|
|
||||||
|
def check_identity_add(self):
|
||||||
|
"""
|
||||||
|
This function check the identity element and must satisfy this condition: $a + 0 = a$ for each element in the GF(n)
|
||||||
|
In Group Theory, an identity element is an element in the group which do not change the value every element in the group
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
for x in self._F:
|
||||||
|
if not self._identityAdd + x == x:
|
||||||
|
raise Exception(
|
||||||
|
f"The identity element {self._identityAdd} "\
|
||||||
|
"do not satisfy $a + element = a$"
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_identity_mul(self):
|
||||||
|
"""
|
||||||
|
This function check the identity element and must satisfy this condition: $a * 1 = a$ for each element in the GF(n)
|
||||||
|
In Group Theory, an identity element is an element in the group which do not change the value every element in the group
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
for x in self._F:
|
||||||
|
if not self._identityMul * x == x:
|
||||||
|
raise Exception(
|
||||||
|
f"The identity element {self._identityAdd} "\
|
||||||
|
"do not satisfy $a * element = a$"
|
||||||
|
)
|
||||||
|
|
||||||
|
def printMatrice(self, m):
|
||||||
|
"""
|
||||||
|
This function print the GF(m)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
m (list): Matrix of the GF
|
||||||
|
"""
|
||||||
|
header = str()
|
||||||
|
header = " "
|
||||||
|
for x in range(0, self._q):
|
||||||
|
header += f"{x} "
|
||||||
|
|
||||||
|
header += "\n--|" + "-" * (len(header)- 3) +"\n"
|
||||||
|
|
||||||
|
s = str()
|
||||||
|
|
||||||
|
for x in range(0, self._q):
|
||||||
|
s += f"{x} | "
|
||||||
|
for y in range(0, self._q):
|
||||||
|
s += f"{m[x][y]} "
|
||||||
|
s += "\n"
|
||||||
|
|
||||||
|
s = header + s
|
||||||
|
print(s)
|
||||||
124
Cryptotools/Groups/group.py
Normal file
124
Cryptotools/Groups/group.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
class Group:
|
||||||
|
"""
|
||||||
|
This class generate a group self._g based on the operation (here denoted +)
|
||||||
|
with the function ope: (a ** b) % n
|
||||||
|
|
||||||
|
In group theory, any group has an identity element (e), which with the binary operation, do not change the value and must satisfy the condition: $a + e = 0$
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
n (Integer): It's the G_n elements in the Group
|
||||||
|
g (List): The set of the Group
|
||||||
|
operation (Function): Function for generating the Group
|
||||||
|
identity (Integer): The identity of the group.
|
||||||
|
reverse (Dict): For each elements of the Group of n, we have the reverse value
|
||||||
|
"""
|
||||||
|
def __init__(self, n, g, ope):
|
||||||
|
self._n = n
|
||||||
|
self._g = g
|
||||||
|
self._operation = ope
|
||||||
|
self._identity = 0
|
||||||
|
self._reverse = dict()
|
||||||
|
|
||||||
|
def getG(self) -> list():
|
||||||
|
"""
|
||||||
|
This function return the Group
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of all elements in the Group
|
||||||
|
"""
|
||||||
|
return self._g
|
||||||
|
|
||||||
|
def closure(self) -> bool:
|
||||||
|
"""
|
||||||
|
Check the closure law
|
||||||
|
In a group, each element a, b belongs to G, such as a + b belongs to G
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a Boolean if the closure law is respected. True if yes otherwise it's False
|
||||||
|
"""
|
||||||
|
for e1 in self._g:
|
||||||
|
for e2 in self._g:
|
||||||
|
res = self._operation(e1, e2, self._n)
|
||||||
|
if not res in self._g:
|
||||||
|
# raise Exception(f"{res} not in g. g is not a group")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def associative(self) -> bool:
|
||||||
|
"""
|
||||||
|
Check the associative law.
|
||||||
|
In a group, for any a, b and c belongs to G,
|
||||||
|
they must respect this condition: (a + b) + c = a + (a + b)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a boolean if the Associative law is respected. True if yes otherwise it's False
|
||||||
|
"""
|
||||||
|
a = self._g[0]
|
||||||
|
b = self._g[1]
|
||||||
|
c = self._g[2]
|
||||||
|
|
||||||
|
res_ope = self._operation(a, b, self._n)
|
||||||
|
res1 = self._operation(res_ope, c, self._n)
|
||||||
|
|
||||||
|
res_ope = self._operation(b, c, self._n)
|
||||||
|
res2 = self._operation(a, res_ope, self._n)
|
||||||
|
if res1 != res2:
|
||||||
|
# raise Exception(f"{res1} is different from {res2}. g is not a group")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def identity(self) -> bool:
|
||||||
|
"""
|
||||||
|
Check the identity law.
|
||||||
|
In a group, an identity element exist and must be uniq
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a Boolean if the identity elements has been found. True if found otherwise it's False
|
||||||
|
"""
|
||||||
|
for a in self._g:
|
||||||
|
for b in self._g:
|
||||||
|
if not self._operation(a, b, self._n) == b:
|
||||||
|
break
|
||||||
|
|
||||||
|
self._identity = a
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getIdentity(self) -> int:
|
||||||
|
"""
|
||||||
|
Return the identity element. The function identitu() must be called before.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the identity element if it has been found
|
||||||
|
"""
|
||||||
|
return self._identity
|
||||||
|
|
||||||
|
def reverse(self) -> bool:
|
||||||
|
"""
|
||||||
|
Check the inverse law
|
||||||
|
In a group, for each element belongs to G
|
||||||
|
they must have an inverse a ^ (-1) = e (identity)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a Boolean if the all elements ha a reverse element. True if yes otherwise it's False
|
||||||
|
"""
|
||||||
|
reverse = False
|
||||||
|
for a in self._g:
|
||||||
|
for b in self._g:
|
||||||
|
if self._operation(a, b, self._n) == self._identity:
|
||||||
|
self._reverse[a] = b
|
||||||
|
reverse = True
|
||||||
|
break
|
||||||
|
return reverse
|
||||||
|
|
||||||
|
def getReverses(self) -> dict:
|
||||||
|
"""
|
||||||
|
This function return the dictionary of all reverses elements. The key is the element in G and the value is the reverse element
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the reverse dictionary
|
||||||
|
|
||||||
|
"""
|
||||||
|
return self._reverse
|
||||||
1
Cryptotools/Numbers/__init__.py
Normal file
1
Cryptotools/Numbers/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
BIN
Cryptotools/Numbers/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
Cryptotools/Numbers/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
Cryptotools/Numbers/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
Cryptotools/Numbers/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
Cryptotools/Numbers/__pycache__/carmi.cpython-310.pyc
Normal file
BIN
Cryptotools/Numbers/__pycache__/carmi.cpython-310.pyc
Normal file
Binary file not shown.
BIN
Cryptotools/Numbers/__pycache__/carmi.cpython-39.pyc
Normal file
BIN
Cryptotools/Numbers/__pycache__/carmi.cpython-39.pyc
Normal file
Binary file not shown.
177
Cryptotools/Numbers/carmi.py
Normal file
177
Cryptotools/Numbers/carmi.py
Normal file
@ -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
|
||||||
22
Cryptotools/Numbers/coprime.py
Normal file
22
Cryptotools/Numbers/coprime.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
|
||||||
|
|
||||||
|
# https://oeis.org/A000010
|
||||||
|
def phi(n):
|
||||||
|
"""
|
||||||
|
This function count all phi(n)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (integer): it's the phi(n) value
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the phi(n)
|
||||||
|
"""
|
||||||
|
y = 1
|
||||||
|
for i in range(2, n):
|
||||||
|
if gcd(n, i) == 1:
|
||||||
|
y += 1
|
||||||
|
return y
|
||||||
|
|
||||||
56
Cryptotools/Numbers/factorization.py
Normal file
56
Cryptotools/Numbers/factorization.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from random import randint
|
||||||
|
from Cryptotools.Numbers.primeNumber import _millerRabinTest, isPrimeNumber
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
from Cryptotools.lcm import lcm
|
||||||
|
from math import floor, log
|
||||||
|
|
||||||
|
|
||||||
|
def pollard_p_minus_1(n, B=None) -> int:
|
||||||
|
"""
|
||||||
|
This function factorize the number n into factor based on the Pollard's p - 1 algorithm
|
||||||
|
|
||||||
|
The first is to choose B, which is a positive integer and B < n
|
||||||
|
In the second step, we need to define $M=\prod _{primes~q\leq B}q^{\lfloor \log_{q}{B}\rfloor }$
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): The number n to factorize
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the factorize of the number n or None
|
||||||
|
"""
|
||||||
|
|
||||||
|
if B is None:
|
||||||
|
B = randint(1, n - 1)
|
||||||
|
# B = randint(1, n - 1)
|
||||||
|
|
||||||
|
#### We define M
|
||||||
|
# Select all prime numbers 1 < B
|
||||||
|
q = list()
|
||||||
|
for x in range(2, B):
|
||||||
|
# with the _millerRabinTest, the program crash, because the randint() is empty
|
||||||
|
# because, both min value and max value are 2
|
||||||
|
# if _millerRabinTest(x):
|
||||||
|
if isPrimeNumber(x):
|
||||||
|
q.append(x)
|
||||||
|
|
||||||
|
M = 1
|
||||||
|
for prime in q:
|
||||||
|
e = floor(log(B, prime))
|
||||||
|
# print(prime, e)
|
||||||
|
M *= pow(prime, e)
|
||||||
|
|
||||||
|
# We choose a and coprime with n
|
||||||
|
a = 2
|
||||||
|
while True:
|
||||||
|
if gcd(a, n) == 1:
|
||||||
|
break
|
||||||
|
a += 1
|
||||||
|
|
||||||
|
# We can compute g = gcd((a ** M) - 1, n)
|
||||||
|
g = gcd(pow(a, M, n) - 1, n)
|
||||||
|
if g > 1:
|
||||||
|
return g
|
||||||
|
|
||||||
|
return None
|
||||||
19
Cryptotools/Numbers/numbers.py
Normal file
19
Cryptotools/Numbers/numbers.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
|
||||||
|
def fibonacci(n) -> list:
|
||||||
|
"""
|
||||||
|
This function generate the list of Fibonacci
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (integer): it's maximum value of Fibonacci sequence
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of n element in the Fibonacci sequence
|
||||||
|
"""
|
||||||
|
fibo = [0, 1]
|
||||||
|
fibo.append(fibo[0] + fibo[1])
|
||||||
|
for i in range(2, n):
|
||||||
|
fibo.append(fibo[i - 1] + fibo[i])
|
||||||
|
return fibo
|
||||||
|
|
||||||
288
Cryptotools/Numbers/primeNumber.py
Normal file
288
Cryptotools/Numbers/primeNumber.py
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from random import randint, seed, getrandbits
|
||||||
|
from math import log2
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
|
||||||
|
|
||||||
|
def isPrimeNumber(p):
|
||||||
|
"""
|
||||||
|
Check if the number p is a prime number or not. The function iterate until p is achieve.
|
||||||
|
|
||||||
|
This function is not the efficient way to determine if p is prime or a composite.
|
||||||
|
|
||||||
|
To identify if p is prime or not, the function check the result of the Euclidean Division has a remainder. If yes, it's means it's not a prime number
|
||||||
|
|
||||||
|
Args:
|
||||||
|
p (Integer): number if possible prime or not
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a boolean if the number p is a prime number or not. True if yes
|
||||||
|
"""
|
||||||
|
for i in range(2, p):
|
||||||
|
if p % i == 0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
# https://people.csail.mit.edu/rivest/Rsapaper.pdf
|
||||||
|
# https://arxiv.org/pdf/1912.11546
|
||||||
|
# https://link.springer.com/content/pdf/10.1007/3-540-44499-8_27.pdf
|
||||||
|
# https://link.springer.com/article/10.1007/BF00202269
|
||||||
|
# https://www.geeksforgeeks.org/dsa/how-to-generate-large-prime-numbers-for-rsa-algorithm/
|
||||||
|
# https://crypto.stackexchange.com/questions/20548/generation-of-strong-primes
|
||||||
|
# https://crypto.stackexchange.com/questions/71/how-can-i-generate-large-prime-numbers-for-rsa
|
||||||
|
|
||||||
|
def getPrimeNumber(n, safe=True):
|
||||||
|
"""
|
||||||
|
This function generate a large prime number
|
||||||
|
based on "A method for Obtaining Digital Signatures
|
||||||
|
and Public-Key Cryptosystems"
|
||||||
|
Section B. How to Find Large Prime Numbers
|
||||||
|
https://dl.acm.org/doi/pdf/10.1145/359340.359342
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): The size of the prime number. Must be a multiple of 64
|
||||||
|
safe (Boolean): When generating the prime number, the function must find a safe prime number, based on the Germain primes (2p + 1 is also a prime number)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the prime number
|
||||||
|
"""
|
||||||
|
if n % 64 != 0:
|
||||||
|
print("Must be multiple of 64")
|
||||||
|
return
|
||||||
|
# from sys import getsizeof
|
||||||
|
upper = getrandbits(n)
|
||||||
|
lower = upper >> 7
|
||||||
|
r = randint(lower, upper)
|
||||||
|
|
||||||
|
while r % 2 == 0:
|
||||||
|
r += 1
|
||||||
|
|
||||||
|
# Now, we are going to compute r as prime number
|
||||||
|
i = 100
|
||||||
|
while 1:
|
||||||
|
# Check if it's a prime number
|
||||||
|
if _millerRabinTest(r):
|
||||||
|
break
|
||||||
|
|
||||||
|
# TODO: it's dirty, need to change that
|
||||||
|
# i = int(log2(r))
|
||||||
|
# i *= randint(2, 50)
|
||||||
|
|
||||||
|
r += i
|
||||||
|
# print(f"{i} {r}")
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
|
||||||
|
# print(_fermatLittleTheorem(r))
|
||||||
|
# print(getsizeof(r))
|
||||||
|
return r
|
||||||
|
|
||||||
|
def getSmallPrimeNumber(n) -> int:
|
||||||
|
"""
|
||||||
|
This function is deprecated
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): Get the small prime number until n
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return the first prime number found
|
||||||
|
"""
|
||||||
|
is_prime = True
|
||||||
|
|
||||||
|
while True:
|
||||||
|
for i in range(2, n):
|
||||||
|
# If n is divisible by i, it's not a prime, we break the loop
|
||||||
|
if n % i == 0:
|
||||||
|
is_prime = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if is_prime:
|
||||||
|
break
|
||||||
|
is_prime = True
|
||||||
|
n = n + 1
|
||||||
|
|
||||||
|
p = n
|
||||||
|
return p
|
||||||
|
|
||||||
|
def get_prime_numbers(n) -> list:
|
||||||
|
"""
|
||||||
|
This function get all prime number of the n
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): find all prime number until n is achieves
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of prime numbers
|
||||||
|
"""
|
||||||
|
l = list()
|
||||||
|
for i in range(2, n):
|
||||||
|
if n % i == 0:
|
||||||
|
l.append(i)
|
||||||
|
return l
|
||||||
|
|
||||||
|
def get_n_prime_numbers(n) -> list:
|
||||||
|
"""
|
||||||
|
This function return a list of n prime numbers
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): the range, must be an integer
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of n prime numbers
|
||||||
|
"""
|
||||||
|
l = list()
|
||||||
|
|
||||||
|
count = 2
|
||||||
|
index = 0
|
||||||
|
while index < n:
|
||||||
|
is_prime = True
|
||||||
|
for x in range(2, count):
|
||||||
|
if count % x == 0:
|
||||||
|
is_prime = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if is_prime:
|
||||||
|
l.append(count)
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
return l
|
||||||
|
|
||||||
|
def are_coprime(p1, p2):
|
||||||
|
"""
|
||||||
|
This function check if p1 and p2 are coprime
|
||||||
|
|
||||||
|
Args:
|
||||||
|
p1 (list): list of prime numbers of the first number
|
||||||
|
p2 (list): list of prime number of the second number
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a boolean result
|
||||||
|
"""
|
||||||
|
r = True
|
||||||
|
for entry in p1:
|
||||||
|
if entry in p2:
|
||||||
|
r = False
|
||||||
|
break
|
||||||
|
return r
|
||||||
|
|
||||||
|
def sieveOfEratosthenes(n) -> list:
|
||||||
|
"""
|
||||||
|
This function build a list of prime number based on the Sieve of Erastosthenes
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): Interate until n is achives
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a list of all prime numbers to n
|
||||||
|
"""
|
||||||
|
if n < 1:
|
||||||
|
return list()
|
||||||
|
|
||||||
|
eratost = dict()
|
||||||
|
for i in range(2, n):
|
||||||
|
eratost[i] = True
|
||||||
|
|
||||||
|
for i in range(2, n):
|
||||||
|
if eratost[i]:
|
||||||
|
for j in range(i*i, n, i):
|
||||||
|
eratost[j] = False
|
||||||
|
|
||||||
|
sieve = list()
|
||||||
|
for i in range(2, n):
|
||||||
|
if eratost[i]:
|
||||||
|
sieve.append(i)
|
||||||
|
|
||||||
|
return sieve
|
||||||
|
|
||||||
|
def _fermatLittleTheorem(n) -> bool:
|
||||||
|
"""
|
||||||
|
The Fermat's little theorem. if n is a prime number, any number from 0 to n- 1 is a multiple of n
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): Check if n is prime or not
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return True if the number a is a multiple of n, otherwise it's False
|
||||||
|
"""
|
||||||
|
a = randint(1, n - 1)
|
||||||
|
# We compute a ** (n - 1) % n
|
||||||
|
if pow(a, n - 1, n) == 1:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _millerRabinTest(n) -> bool:
|
||||||
|
"""
|
||||||
|
This function execute a Miller Rabin test
|
||||||
|
For the algorithm, it's based on the pseudo-algo provided by this document:
|
||||||
|
* https://www.cs.cornell.edu/courses/cs4820/2010sp/handouts/MillerRabin.pdf
|
||||||
|
The Mille-Rabin test is an efficient way to determine if n is prime or not
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): Check if n is a prime number
|
||||||
|
Returns:
|
||||||
|
Return a boolean. True for a prime otherwise, it's a composite number
|
||||||
|
|
||||||
|
"""
|
||||||
|
if n < 2 or (n > 2 and n % 2 == 0): # If n is even, it's a composite
|
||||||
|
return False
|
||||||
|
|
||||||
|
k = 0
|
||||||
|
q = n - 1
|
||||||
|
#while (q & 1) == 0:
|
||||||
|
# k += 1
|
||||||
|
# q >>= 1
|
||||||
|
while q % 2 == 0:
|
||||||
|
k += 1
|
||||||
|
q //= 2
|
||||||
|
|
||||||
|
# We choose a: a < n - 1
|
||||||
|
for _ in range(40):
|
||||||
|
a = randint(2, n - 1)
|
||||||
|
# We compute a ** q % n
|
||||||
|
x = pow(a, q, n)
|
||||||
|
|
||||||
|
# If it's a composite number
|
||||||
|
if x == 1 or x == n - 1:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for _ in range(k):
|
||||||
|
z = pow(x, 2, n)
|
||||||
|
if z == 1 or z == n - 1:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def sophieGermainPrime(p) -> bool:
|
||||||
|
"""
|
||||||
|
Check if the number p is a safe prime number: 2p + 1 is also a prime
|
||||||
|
|
||||||
|
Args:
|
||||||
|
p (Integer): Possible prime number
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return True if p is a safe prime number, otherwise it's False
|
||||||
|
"""
|
||||||
|
pp = 2 * p + 1
|
||||||
|
return _millerRabinTest(pp)
|
||||||
|
|
||||||
|
def isSafePrime(n) -> bool:
|
||||||
|
"""
|
||||||
|
This function has not been implemented yet, but check if the number n is a safe prime number. This function will test different properties of the possible prime number n
|
||||||
|
|
||||||
|
Args:
|
||||||
|
n (Integer): the prime number to check
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Return a Boolean if the prime number n is safe or not. True if yes, otherwise it's False
|
||||||
|
"""
|
||||||
|
if n.bit_length() >= 256:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Do Sophie Germain's test
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
1
Cryptotools/Utils/__init__.py
Normal file
1
Cryptotools/Utils/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
9
Cryptotools/Utils/number.py
Normal file
9
Cryptotools/Utils/number.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
COMPOSITE = 0
|
||||||
|
PRIME = 1
|
||||||
|
|
||||||
|
class Number:
|
||||||
|
def __init__(self):
|
||||||
|
self._int = int()
|
||||||
|
self._kind = COMPOSITE
|
||||||
34
Cryptotools/Utils/utils.py
Normal file
34
Cryptotools/Utils/utils.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
def gcd(a, b):
|
||||||
|
"""
|
||||||
|
This function calculate the GCD (Greatest Common Divisor of the number a of b
|
||||||
|
Args:
|
||||||
|
a (Integer): the number a
|
||||||
|
b (integer): the number b
|
||||||
|
|
||||||
|
Return:
|
||||||
|
the GCD
|
||||||
|
"""
|
||||||
|
|
||||||
|
if b == 0:
|
||||||
|
return a
|
||||||
|
return gcd(b, a%b)
|
||||||
|
|
||||||
|
def egcd(a, b):
|
||||||
|
"""
|
||||||
|
This function compute the Extended Euclidean algorithm
|
||||||
|
https://user.eng.umd.edu/~danadach/Cryptography_20/ExtEuclAlg.pdf
|
||||||
|
https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
|
||||||
|
|
||||||
|
Args:
|
||||||
|
a (Integer): the number a
|
||||||
|
b (Integer): the number b
|
||||||
|
"""
|
||||||
|
if a == 0:
|
||||||
|
return b, 0, 1
|
||||||
|
gcd, x1, y1 = egcd(b % a, a)
|
||||||
|
x = y1 - (b // a) * x1
|
||||||
|
y = x1
|
||||||
|
return gcd, x, y
|
||||||
|
|
||||||
3
Cryptotools/__init__.py
Normal file
3
Cryptotools/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
__all__ = ["Numbers", "Groups"]
|
||||||
33
Cryptotools/lcm.py
Normal file
33
Cryptotools/lcm.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.primeNumber import gcd
|
||||||
|
|
||||||
|
def compute_multiple(a):
|
||||||
|
"""
|
||||||
|
This function compute the 20 first multiples of the number a
|
||||||
|
|
||||||
|
Args:
|
||||||
|
a (Integer): the number
|
||||||
|
|
||||||
|
Return:
|
||||||
|
list of multiple of a
|
||||||
|
"""
|
||||||
|
|
||||||
|
r = list()
|
||||||
|
for i in range(1, 20):
|
||||||
|
r.append(a * i)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def lcm(a, b):
|
||||||
|
"""
|
||||||
|
This function get the LCM (Least Common Multiple) a of b
|
||||||
|
|
||||||
|
Args:
|
||||||
|
a (Integer): the number
|
||||||
|
b (Integer): the number
|
||||||
|
|
||||||
|
Return:
|
||||||
|
the LCM
|
||||||
|
"""
|
||||||
|
return (b // gcd(a, b)) * a
|
||||||
|
|
||||||
31
README.md
Normal file
31
README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Introduction
|
||||||
|
This project contains the module *cryptotools* which can used for cryptography
|
||||||
|
|
||||||
|
# Install the program
|
||||||
|
```
|
||||||
|
$ virtualenv ~/venv/myenv
|
||||||
|
$ source ~/venv/myenv/bin/activate
|
||||||
|
$ python3 setup.py install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
In the directory *examples/*, you have different python files for using the module
|
||||||
|
|
||||||
|
## Unitests
|
||||||
|
### Test phi
|
||||||
|
```
|
||||||
|
$ python3 tests/test_phi.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Fibonacci
|
||||||
|
For testing Fibonacci sequence, I generate a list from OEIS wich contains 40 first numbers of Fibonacci. The `test_numbers.py` test the Fibonacci sequence generated from the functions `fibonacci` in `utils/numbers.py`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ python3 tests/test_numbers.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
# Build the doc
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdocs build
|
||||||
|
```
|
||||||
27
docs/examples-rsa-keys.md
Normal file
27
docs/examples-rsa-keys.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Generating RSA Keys
|
||||||
|
In the following section, we are going to see how to generate RSA Keys and how to encrypt data with these keys.
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Encryptions.RSA import RSA
|
||||||
|
|
||||||
|
|
||||||
|
rsa = RSA()
|
||||||
|
rsa.generateKeys(size=512)
|
||||||
|
|
||||||
|
e = rsa.e
|
||||||
|
d = rsa.d
|
||||||
|
n = rsa.n
|
||||||
|
|
||||||
|
s = "I am encrypted with RSA"
|
||||||
|
print(f"plaintext: {s}")
|
||||||
|
encrypted = rsa.encrypt(s)
|
||||||
|
|
||||||
|
# Encrypt data
|
||||||
|
print(f"ciphertext: {encrypted}")
|
||||||
|
|
||||||
|
# We decrypt
|
||||||
|
plaintext = rsa.decrypt(encrypted)
|
||||||
|
print(f"Plaintext: {plaintext}")
|
||||||
|
```
|
||||||
9
docs/group-theory.md
Normal file
9
docs/group-theory.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Group Theory
|
||||||
|
## Group
|
||||||
|
::: Cryptotools.Groups.group
|
||||||
|
|
||||||
|
## Cyclic group
|
||||||
|
::: Cryptotools.Groups.cyclic
|
||||||
|
|
||||||
|
## Galois Field (Finite Field)
|
||||||
|
::: Cryptotools.Groups.galois
|
||||||
13
docs/index.md
Normal file
13
docs/index.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Welcome to CryptoTools
|
||||||
|
|
||||||
|
* [Introduction](/introduction)
|
||||||
|
* [Installation](/installation)
|
||||||
|
* Low-Level Cryptographic
|
||||||
|
* [Number Theory](/number-theory)
|
||||||
|
* [Group Theory](/group-theory)
|
||||||
|
* Public Keys:
|
||||||
|
* [RSA](/rsa)
|
||||||
|
* Examples:
|
||||||
|
* [Generating RSA keys](/examples-rsa-keys)
|
||||||
|
|
||||||
|
|
||||||
18
docs/installation.md
Normal file
18
docs/installation.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Installation
|
||||||
|
To install the project, you should install from my own Python repository but, you first need to deploy your virtual enviroment.
|
||||||
|
|
||||||
|
## Installation from source
|
||||||
|
You can install from the source. Download the [project](https://gitea.bucchino.org/gbucchino/cryptotools.git) and install it in your virtual environment:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ virtualenv ~/venv/cryptotools
|
||||||
|
$ source ~/venv/cryptotools/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git clone https://gitea.bucchino.org/gbucchino/cryptotools.git
|
||||||
|
$ cd cryptotools
|
||||||
|
$ python3 setup.py install
|
||||||
|
```
|
||||||
|
|
||||||
|
The installation is completed. You can know use Cryptotools package into your project. In the directory `examples` you may find some examples scripts
|
||||||
5
docs/introduction.md
Normal file
5
docs/introduction.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# CryptoTools
|
||||||
|
CryptoTools is a Python package that provides low-level cryptographic primitives for generating strong numbers. With this project, it's possible to generate public key cryptosystems such as RSA.
|
||||||
|
This project has a academic purpose and can not be used in production enviroment yet.
|
||||||
|
|
||||||
|
So far, my cryptographic modules are not compliant with [FIPS 140-3](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-3.pdf) but in the future, that will be.
|
||||||
9
docs/number-theory.md
Normal file
9
docs/number-theory.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Number Theory
|
||||||
|
For generating keys, we need strong prime number, they are the basis. CryptoTools provides functions for generating these numbers.
|
||||||
|
|
||||||
|
## prime numbers
|
||||||
|
::: Cryptotools.Numbers.primeNumber
|
||||||
|
|
||||||
|
## Fibonacci sequence
|
||||||
|
::: Cryptotools.Numbers.numbers
|
||||||
|
|
||||||
3
docs/rsa.md
Normal file
3
docs/rsa.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
CryptoTools provides several functions for generating a RSA Keys
|
||||||
|
|
||||||
|
::: Cryptotools.Encryptions.RSA
|
||||||
32
examples/carmi.py
Normal file
32
examples/carmi.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
|
||||||
|
|
||||||
|
def carmi_first_method(n) -> int:
|
||||||
|
coprimes = list()
|
||||||
|
for i in range(1, n):
|
||||||
|
if gcd(i, n) == 1:
|
||||||
|
coprimes.append(i)
|
||||||
|
print(coprimes)
|
||||||
|
smallest = list()
|
||||||
|
for m in range(1, n):
|
||||||
|
l = 0
|
||||||
|
for a in coprimes:
|
||||||
|
if a ** m % n == 1:
|
||||||
|
l += 1
|
||||||
|
if l == len(coprimes):
|
||||||
|
smallest.append(m)
|
||||||
|
|
||||||
|
#print(smallest)
|
||||||
|
return min(smallest)
|
||||||
|
|
||||||
|
print(f"lambda(12) = {carmi_first_method(12)}")
|
||||||
|
print(f"lambda(19) = {carmi_first_method(19)}")
|
||||||
|
#print(f"lambda(28) = {carmi_first_method(28)}")
|
||||||
|
#print(f"lambda(32) = {carmi_first_method(32)}")
|
||||||
|
#print(f"lambda(33) = {carmi_first_method(33)}")
|
||||||
|
#print(f"lambda(35) = {carmi_first_method(35)}")
|
||||||
|
#print(f"lambda(36) = {carmi_first_method(36)}")
|
||||||
|
#print(f"lambda(135) = {carmi_first_method(135)}")
|
||||||
|
#print(f"lambda(1200) = {carmi_first_method(1200)}")
|
||||||
23
examples/coprime.py
Normal file
23
examples/coprime.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.coprime import phi
|
||||||
|
from Cryptotools.lcm import lcm
|
||||||
|
from Cryptotools.Numbers.carmi import carmi_numbers, is_carmichael, carmichael_lambda
|
||||||
|
|
||||||
|
print(f"phi(19) = {phi(19)}")
|
||||||
|
|
||||||
|
print("Carmichael's number")
|
||||||
|
l = carmi_numbers(561)
|
||||||
|
print(is_carmichael(561, l))
|
||||||
|
|
||||||
|
# Test Carmichael lambda
|
||||||
|
print("Carmichael")
|
||||||
|
print(f"12 {carmichael_lambda(12)}")
|
||||||
|
print(f"19 {carmichael_lambda(19)}")
|
||||||
|
print(f"28 {carmichael_lambda(28)}")
|
||||||
|
print(f"32 {carmichael_lambda(32)}")
|
||||||
|
print(f"33 {carmichael_lambda(33)}")
|
||||||
|
print(f"35 {carmichael_lambda(35)}")
|
||||||
|
print(f"36 {carmichael_lambda(36)}")
|
||||||
|
print(f"135 {carmichael_lambda(135)}")
|
||||||
|
print(f"1200 {carmichael_lambda(1200)}")
|
||||||
41
examples/cyclic.py
Normal file
41
examples/cyclic.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.cyclic import Cyclic
|
||||||
|
from Cryptotools.Numbers.primeNumber import isPrimeNumber
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
n = 19
|
||||||
|
g = list()
|
||||||
|
for i in range(1, n):
|
||||||
|
g.append(i)
|
||||||
|
|
||||||
|
print(f"n = {n}")
|
||||||
|
print(f"G = {g}")
|
||||||
|
|
||||||
|
cyclic = Cyclic(g, n, operation)
|
||||||
|
order = len(g) # Length of the group
|
||||||
|
print(f"len: {order}")
|
||||||
|
print(f"prime: {isPrimeNumber(order)}")
|
||||||
|
|
||||||
|
cyclic.generator()
|
||||||
|
|
||||||
|
print(f"All generators: {cyclic.getGenerators()}")
|
||||||
|
print(f"Is cyclic: {cyclic.isCyclic()}")
|
||||||
|
|
||||||
|
# Check if the abelian group is respected
|
||||||
|
print(f"It is an abelian group: {cyclic.closure()}\n")
|
||||||
|
|
||||||
|
|
||||||
|
e = choice(cyclic.getGenerators())
|
||||||
|
z = list()
|
||||||
|
for a in range(1, n):
|
||||||
|
res = operation(e, a, n)
|
||||||
|
z.append(res)
|
||||||
|
|
||||||
|
print(z)
|
||||||
|
if z == g:
|
||||||
|
print(f"The group generated with the generator {e} works")
|
||||||
64
examples/cyclic_dlp.py
Normal file
64
examples/cyclic_dlp.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from Cryptotools.Groups.cyclic import Cyclic
|
||||||
|
from Cryptotools.Numbers.primeNumber import getPrimeNumber
|
||||||
|
from random import randint, choice
|
||||||
|
from math import log, log10, log2
|
||||||
|
|
||||||
|
"""
|
||||||
|
Here, we will try to understand why we need to have a generator when we encrypt data for Diffie-Hellman
|
||||||
|
https://crypto.stackexchange.com/questions/25489/why-does-diffie-hellman-need-be-a-cyclic-group
|
||||||
|
"""
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
def getGenerator(gr, p):
|
||||||
|
index = 1
|
||||||
|
for g in range(2, p):
|
||||||
|
z = list()
|
||||||
|
for entry in range(1, p):
|
||||||
|
res = operation(g, index, p)
|
||||||
|
#if res not in z:
|
||||||
|
z.append(res)
|
||||||
|
index = index + 1
|
||||||
|
print(f"{g}: {sorted(z)}")
|
||||||
|
|
||||||
|
def generateGroupByG(gr, p, g):
|
||||||
|
index = 1
|
||||||
|
z = list()
|
||||||
|
for entry in range(1, p):
|
||||||
|
res = operation(g, index, p)
|
||||||
|
#if res not in z:
|
||||||
|
z.append(res)
|
||||||
|
index = index + 1
|
||||||
|
return z
|
||||||
|
|
||||||
|
def computePublicKey(key, p, g):
|
||||||
|
return (g ** key) % p
|
||||||
|
|
||||||
|
|
||||||
|
gr = list()
|
||||||
|
# Public value
|
||||||
|
p = 5
|
||||||
|
g = 0
|
||||||
|
for i in range(1, p):
|
||||||
|
gr.append(i)
|
||||||
|
|
||||||
|
print(f"p = {p}")
|
||||||
|
print(f"G = {gr}")
|
||||||
|
# We try with a generator which is not in list
|
||||||
|
cyclic = Cyclic(gr, p, operation)
|
||||||
|
generators = cyclic.getGenerators()
|
||||||
|
print(f"All generators: {generators}")
|
||||||
|
|
||||||
|
# Generate group with g = 2
|
||||||
|
grWithG = generateGroupByG(gr, p, 2)
|
||||||
|
print(f"Group generated with g = 2: {grWithG}")
|
||||||
|
|
||||||
|
for a in grWithG:
|
||||||
|
# print(f"log2({a}) = {log(a, 2)}") # Same as below
|
||||||
|
print(f"log2({a}) = {log2(a)}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
for a in range(1, len(grWithG) + 1):
|
||||||
|
print(f"log2({a}) = {log2(a)}")
|
||||||
32
examples/cyclic_generator.py
Normal file
32
examples/cyclic_generator.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.cyclic import Cyclic
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
n = 19
|
||||||
|
g = list()
|
||||||
|
for i in range(1, n):
|
||||||
|
g.append(i)
|
||||||
|
|
||||||
|
print(f"n = {n}")
|
||||||
|
print(f"G = {g}")
|
||||||
|
|
||||||
|
cyclic = Cyclic(g, n, operation)
|
||||||
|
|
||||||
|
cyclic.generator()
|
||||||
|
generators = cyclic.getGenerators()
|
||||||
|
print(f"All generators: {generators}")
|
||||||
|
|
||||||
|
e = choice(generators)
|
||||||
|
z = list()
|
||||||
|
for a in range(1, n):
|
||||||
|
res = operation(e, a, n)
|
||||||
|
z.append(res)
|
||||||
|
|
||||||
|
z = sorted(z)
|
||||||
|
if z == g:
|
||||||
|
print(f"Working with the generator {e}")
|
||||||
49
examples/cyclic_subgroup.py
Normal file
49
examples/cyclic_subgroup.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from Cryptotools.Groups.cyclic import Cyclic
|
||||||
|
from Cryptotools.Numbers.primeNumber import getPrimeNumber
|
||||||
|
from random import randint, choice
|
||||||
|
from math import log, log10
|
||||||
|
|
||||||
|
"""
|
||||||
|
Here, we will try to understand why we need to have a generator when we encrypt data for Diffie-Hellman
|
||||||
|
https://crypto.stackexchange.com/questions/25489/why-does-diffie-hellman-need-be-a-cyclic-group
|
||||||
|
"""
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
def getGenerator(gr, p):
|
||||||
|
cyclic = Cyclic(gr, p, operation)
|
||||||
|
generators = cyclic.getGenerators()
|
||||||
|
print(f"All generators: {generators}")
|
||||||
|
cyclic.identity()
|
||||||
|
print(f"Identity: {cyclic.getIdentity()}")
|
||||||
|
|
||||||
|
return generators
|
||||||
|
|
||||||
|
|
||||||
|
gr = list()
|
||||||
|
# Public value
|
||||||
|
p = 13
|
||||||
|
g = 0
|
||||||
|
for i in range(1, p):
|
||||||
|
gr.append(i)
|
||||||
|
|
||||||
|
print(f"p = {p}")
|
||||||
|
print(f"G = {gr}")
|
||||||
|
# We try with a generator which is not in list
|
||||||
|
generators = getGenerator(gr, p)
|
||||||
|
|
||||||
|
g = 3 # In the group
|
||||||
|
#g = # Not in the group
|
||||||
|
#print(f"g = {g}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Try to compute the cyclic subgroup
|
||||||
|
for G in range(p + 1):
|
||||||
|
res = 0
|
||||||
|
for a in range(G):
|
||||||
|
r = operation(G, a, p)
|
||||||
|
res = res + r
|
||||||
|
if res == p:
|
||||||
|
print(f"G = {G}; res = {res}")
|
||||||
73
examples/cyclic_test.py
Normal file
73
examples/cyclic_test.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.cyclic import Cyclic
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
from Cryptotools.Numbers.primeNumber import isPrimeNumber
|
||||||
|
from random import choice
|
||||||
|
|
||||||
|
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
def test1(n):
|
||||||
|
"""
|
||||||
|
We test with n is not prime but the order of the group is a prime number
|
||||||
|
"""
|
||||||
|
g = list()
|
||||||
|
g2 = list()
|
||||||
|
for i in range(1, n):
|
||||||
|
#if gcd(i, n) == 1:
|
||||||
|
g.append(i)
|
||||||
|
|
||||||
|
print(f"n = {n}")
|
||||||
|
print(f"G = {g}")
|
||||||
|
Gsorted = sorted(g)
|
||||||
|
|
||||||
|
cyclic = Cyclic(g, n, operation)
|
||||||
|
order = len(g) # https://en.wikipedia.org/wiki/Order_(group_theory)
|
||||||
|
print(f"len: {order}")
|
||||||
|
print(f"prime: {isPrimeNumber(order)}")
|
||||||
|
g2 = list()
|
||||||
|
for i in range(1, order):
|
||||||
|
if gcd(i, order) == 1:
|
||||||
|
g2.append(i)
|
||||||
|
pass
|
||||||
|
|
||||||
|
print(g2)
|
||||||
|
# Pick a number in the previous list and check if we can generate all number with it
|
||||||
|
item = choice(g2)
|
||||||
|
print()
|
||||||
|
|
||||||
|
# if the order is prime, the group is cyclic ?
|
||||||
|
|
||||||
|
# Check if we have all items
|
||||||
|
g3 = list()
|
||||||
|
for i in range(1, n):
|
||||||
|
res = operation(i, item, n)
|
||||||
|
if gcd(res, item) == 1:
|
||||||
|
g3.append(res)
|
||||||
|
#print(res)
|
||||||
|
pass
|
||||||
|
|
||||||
|
G2sorted = sorted(g2)
|
||||||
|
G3sorted = sorted(g3)
|
||||||
|
print()
|
||||||
|
# print(f"{g} = {cyclic.generator(g)}")
|
||||||
|
gen = cyclic.generator()
|
||||||
|
|
||||||
|
print(f"All generators: {cyclic.getGenerators()}")
|
||||||
|
print(f"Is cyclic: {cyclic.isCyclic()}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
print(G2sorted)
|
||||||
|
print(G3sorted)
|
||||||
|
if G3sorted == Gsorted:
|
||||||
|
print(f"Matching with item {item}") # Always match with item 1
|
||||||
|
|
||||||
|
# Check if the abelian group is respected
|
||||||
|
print(f"It is an abelian group: {cyclic.closure()}\n")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test1(19)
|
||||||
|
test1(12)
|
||||||
74
examples/dh_cyclic.py
Normal file
74
examples/dh_cyclic.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from Cryptotools.Groups.cyclic import Cyclic
|
||||||
|
from Cryptotools.Numbers.primeNumber import getPrimeNumber
|
||||||
|
from random import randint, choice
|
||||||
|
from math import log, log10
|
||||||
|
|
||||||
|
"""
|
||||||
|
Here, we will try to understand why we need to have a generator when we encrypt data for Diffie-Hellman
|
||||||
|
https://crypto.stackexchange.com/questions/25489/why-does-diffie-hellman-need-be-a-cyclic-group
|
||||||
|
"""
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
def getGenerator(gr, p):
|
||||||
|
cyclic = Cyclic(gr, p, operation)
|
||||||
|
generators = cyclic.getGenerators()
|
||||||
|
print(f"All generators: {generators}")
|
||||||
|
|
||||||
|
# Test with a no generator
|
||||||
|
item = 2
|
||||||
|
while item in generators: # we loop until we found an item which is not a generators of the group
|
||||||
|
item = randint(1, p)
|
||||||
|
return item
|
||||||
|
|
||||||
|
def computePublicKey(key, p, g):
|
||||||
|
return (g ** key) % p
|
||||||
|
|
||||||
|
def computeEphemeralKey(public, secret, p):
|
||||||
|
return (public ** secret) % p
|
||||||
|
|
||||||
|
gr = list()
|
||||||
|
# Public value
|
||||||
|
#p = getPrimeNumber(n = 8)
|
||||||
|
#p = 257
|
||||||
|
p = 19
|
||||||
|
g = 0
|
||||||
|
for i in range(1, p):
|
||||||
|
gr.append(i)
|
||||||
|
|
||||||
|
print(f"p = {p}")
|
||||||
|
print(f"G = {gr}")
|
||||||
|
# We try with a generator which is not in list
|
||||||
|
g = getGenerator(gr, p)
|
||||||
|
#g = [3, 5, 6, 7, 10, 12, 14, 19, 20, 24, 27, 28, 33, 37, 38, 39, 40, 41, 43, 45, 47, 48, 51, 53, 54, 55, 56, 63, 65, 66, 69, 71, 74, 75, 76, 77, 78, 80, 82, 83, 85, 86, 87, 90, 91, 93, 94, 96, 97, 101, 102, 103, 105, 106, 107, 108, 109, 110, 112, 115, 119, 125, 126, 127, 130, 131, 132, 138, 142, 145, 147, 148, 149, 150, 151, 152, 154, 155, 156, 160, 161, 163, 164, 166, 167, 170, 171, 172, 174, 175, 177, 179, 180, 181, 182, 183, 186, 188, 191, 192, 194, 201, 202, 203, 204, 206, 209, 210, 212, 214, 216, 217, 218, 219, 220, 224, 229, 230, 233, 237, 238, 243, 245, 247, 250, 251, 252, 254]
|
||||||
|
g = 29 # Not in the group
|
||||||
|
print(f"g = {g}")
|
||||||
|
|
||||||
|
# We can compute with the secret key
|
||||||
|
secretKeyA = 5
|
||||||
|
secretKeyB = 10
|
||||||
|
publicKeyA = computePublicKey(secretKeyA, p, g)
|
||||||
|
publicKeyB = computePublicKey(secretKeyB, p, g)
|
||||||
|
print(f"Public key A: {publicKeyA}")
|
||||||
|
print(f"Public key B: {publicKeyB}")
|
||||||
|
|
||||||
|
# Eve sniff the traffic and knows p, g and publicKeyA and B
|
||||||
|
|
||||||
|
|
||||||
|
# Generator need to be use, because that avoid to Eve to try to find a secret key of Alice or Bob ???
|
||||||
|
# Utiliser un generateur qui genere la tout le groupe, va permettre d'éviter à Eve de trouver la secret key de Alice ou Bob ????
|
||||||
|
# https://eitca.org/cybersecurity/eitc-is-acc-advanced-classical-cryptography/diffie-hellman-cryptosystem/diffie-hellman-key-exchange-and-the-discrete-log-problem/examination-review-diffie-hellman-key-exchange-and-the-discrete-log-problem/what-are-the-roles-of-the-prime-number-p-and-the-generator-alpha-in-the-diffie-hellman-key-exchange-process/
|
||||||
|
# https://www.perplexity.ai/search/why-generator-in-cyclic-group-QRYR6.rxSI218hs_x5CvnQ#0
|
||||||
|
|
||||||
|
# They exchange their public keys
|
||||||
|
ephemeralKeyA = computeEphemeralKey(publicKeyB, secretKeyA, p)
|
||||||
|
ephemeralKeyB = computeEphemeralKey(publicKeyA, secretKeyB, p)
|
||||||
|
print(f"Ephemeral key A: {ephemeralKeyA}")
|
||||||
|
print(f"Ephemeral key B: {ephemeralKeyB}")
|
||||||
|
|
||||||
|
# Test log10
|
||||||
|
#for i in range(1, 1000):
|
||||||
|
# r = log10(i)
|
||||||
|
# if isinstance(r, int):
|
||||||
|
# print(f"{i} = {r}")
|
||||||
116
examples/dh_no_generator.py
Normal file
116
examples/dh_no_generator.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from Cryptotools.Groups.cyclic import Cyclic
|
||||||
|
from Cryptotools.Numbers.primeNumber import getPrimeNumber
|
||||||
|
from random import randint, choice
|
||||||
|
from math import log, log10
|
||||||
|
|
||||||
|
"""
|
||||||
|
Here, we will try to understand why we need to have a generator when we encrypt data for Diffie-Hellman
|
||||||
|
https://crypto.stackexchange.com/questions/25489/why-does-diffie-hellman-need-be-a-cyclic-group
|
||||||
|
"""
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
def getGenerator(gr, p):
|
||||||
|
index = 1
|
||||||
|
for g in range(2, p):
|
||||||
|
z = list()
|
||||||
|
for entry in range(1, p):
|
||||||
|
res = operation(g, index, p)
|
||||||
|
#if res not in z:
|
||||||
|
z.append(res)
|
||||||
|
index = index + 1
|
||||||
|
print(f"{g}: {sorted(z)}")
|
||||||
|
|
||||||
|
def getGenerator2(gr, p, g):
|
||||||
|
index = 1
|
||||||
|
z = list()
|
||||||
|
for entry in range(1, p):
|
||||||
|
res = operation(g, index, p)
|
||||||
|
if res not in z:
|
||||||
|
z.append(res)
|
||||||
|
index = index + 1
|
||||||
|
return z
|
||||||
|
|
||||||
|
|
||||||
|
def computePublicKey(key, p, g):
|
||||||
|
return (g ** key) % p
|
||||||
|
|
||||||
|
def computeEphemeralKey(public, secret, p):
|
||||||
|
return (public ** secret) % p
|
||||||
|
|
||||||
|
gr = list()
|
||||||
|
# Public value
|
||||||
|
p = 43
|
||||||
|
g = 0
|
||||||
|
for i in range(1, p):
|
||||||
|
gr.append(i)
|
||||||
|
|
||||||
|
print(f"p = {p}")
|
||||||
|
print(f"G = {gr}")
|
||||||
|
# We try with a generator which is not in list
|
||||||
|
cyclic = Cyclic(gr, p, operation)
|
||||||
|
generators = cyclic.getGenerators()
|
||||||
|
print(f"All generators: {generators}")
|
||||||
|
|
||||||
|
g = 3 # In the group
|
||||||
|
print(f"g = {g}")
|
||||||
|
|
||||||
|
# We can compute with the secret key
|
||||||
|
secretKeyA = 5
|
||||||
|
secretKeyB = 10
|
||||||
|
publicKeyA = computePublicKey(secretKeyA, p, g)
|
||||||
|
publicKeyB = computePublicKey(secretKeyB, p, g)
|
||||||
|
print(f"Public key A: {publicKeyA}")
|
||||||
|
print(f"Public key B: {publicKeyB}\n")
|
||||||
|
|
||||||
|
# Here, g is in the generator, we need to compute all values until that match with publicKeyA
|
||||||
|
for a in range(1, p):
|
||||||
|
res = operation(g, a, p)
|
||||||
|
if res == publicKeyA:
|
||||||
|
print(f"Brute forced secret key of A: {a}")
|
||||||
|
|
||||||
|
for a in range(1, p):
|
||||||
|
res = operation(g, a, p)
|
||||||
|
if res == publicKeyB:
|
||||||
|
print(f"Brute forced secret key of B: {a}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
#for a in generators:
|
||||||
|
# print(a)
|
||||||
|
#
|
||||||
|
#print()
|
||||||
|
|
||||||
|
# Here, we generate all key withthe same generator
|
||||||
|
keys = list()
|
||||||
|
for a in range(1, p):
|
||||||
|
keys.append(operation(g, a, p))
|
||||||
|
|
||||||
|
print((keys))
|
||||||
|
print(sorted(keys))
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
print(f"Keys with g = 4: {sorted(getGenerator2(gr, p, 4))}")
|
||||||
|
|
||||||
|
# Do the same, but g is not a generator
|
||||||
|
g = 4 # Not in the generator group
|
||||||
|
publicKeyA = computePublicKey(secretKeyA, p, g)
|
||||||
|
publicKeyB = computePublicKey(secretKeyB, p, g)
|
||||||
|
print(f"Public key A: {publicKeyA}")
|
||||||
|
print(f"Public key B: {publicKeyB}")
|
||||||
|
|
||||||
|
keys = list()
|
||||||
|
for a in range(1, p):
|
||||||
|
keys.append(operation(g, a, p))
|
||||||
|
print(keys)
|
||||||
|
|
||||||
|
# Eve sniff the traffic and knows p, g and publicKeyA and B
|
||||||
|
# Eve, knows p and g, because it's public
|
||||||
|
# Eve need to guess the secretKey of A.
|
||||||
|
# For doing that, we iterate all posibility until that match with the publicKeyA
|
||||||
|
|
||||||
|
#for a in range(1, 4):
|
||||||
|
# res = operation(g, a, p)
|
||||||
|
# print(res)
|
||||||
80
examples/fermat_factorization.py
Normal file
80
examples/fermat_factorization.py
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from Cryptotools.Numbers.primeNumber import isPrimeNumber, _millerRabinTest, getPrimeNumber
|
||||||
|
from math import sqrt, isqrt, ceil
|
||||||
|
from sympy import sqrt as sq
|
||||||
|
|
||||||
|
def get_closest_prime(p):
|
||||||
|
q = p + 1
|
||||||
|
l = list()
|
||||||
|
while True:
|
||||||
|
if _millerRabinTest(q):
|
||||||
|
l.append(q)
|
||||||
|
if len(l) == 20:
|
||||||
|
break
|
||||||
|
q += 1
|
||||||
|
return l
|
||||||
|
|
||||||
|
def test():
|
||||||
|
while True:
|
||||||
|
p = getPrimeNumber(64)
|
||||||
|
b = sqrt(p)
|
||||||
|
if b % 2 == 0.0:
|
||||||
|
break
|
||||||
|
print(p)
|
||||||
|
|
||||||
|
#test()
|
||||||
|
#exit(1)
|
||||||
|
p = 7901
|
||||||
|
q = 7817
|
||||||
|
#p = getPrimeNumber(64)
|
||||||
|
#q = get_closest_prime(p)[1]
|
||||||
|
p = 7943202761666983 # Works
|
||||||
|
q = 7943202761667119
|
||||||
|
#p = 314159200000000028138418196395985880850000485810513
|
||||||
|
#q = 314159200000000028138415196395985880850000485810479
|
||||||
|
print(f"p = {p}")
|
||||||
|
print(f"q = {q}")
|
||||||
|
n = p * q
|
||||||
|
print(f"n = {n}")
|
||||||
|
|
||||||
|
a = ceil(sqrt(n))
|
||||||
|
#print(a)
|
||||||
|
#print(sqrt(n))
|
||||||
|
#print(sqrt(n) < n) # True
|
||||||
|
#print(a * a)
|
||||||
|
#print(a * a < n)
|
||||||
|
#print()
|
||||||
|
#a = isqrt(n) + 1
|
||||||
|
iteration = 0
|
||||||
|
while True:
|
||||||
|
# b2 = (a ** 2) - n
|
||||||
|
iteration += 1
|
||||||
|
b2 = pow(a, 2) - n
|
||||||
|
#b2 = ceil(a*a) - n
|
||||||
|
# print(b2)
|
||||||
|
sqb2 = ceil(sqrt(b2))
|
||||||
|
# print(b2, isqrt(pow(b2, 2)))
|
||||||
|
if b2 % 2 == 0.0:
|
||||||
|
#if isqrt(pow(b2, 2)) == b2:
|
||||||
|
b = isqrt(b2)
|
||||||
|
break
|
||||||
|
a = a + 1
|
||||||
|
|
||||||
|
print(f"Iteration: {iteration}")
|
||||||
|
print(f"a = {a}")
|
||||||
|
print(f"b2 = {b2}")
|
||||||
|
print(f"b = {b}")
|
||||||
|
p = int((a + b))
|
||||||
|
q = int((a - b))
|
||||||
|
print(p)
|
||||||
|
print(q)
|
||||||
|
#N = (a + b) * (a - b)
|
||||||
|
N = p * q
|
||||||
|
print(_millerRabinTest(p))
|
||||||
|
print(_millerRabinTest(q))
|
||||||
|
print(f"N = {N}")
|
||||||
|
print(n == N)
|
||||||
|
print()
|
||||||
|
|
||||||
5
examples/fibonacci.py
Normal file
5
examples/fibonacci.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.numbers import fibonacci
|
||||||
|
|
||||||
|
print(fibonacci(40))
|
||||||
36
examples/galois.py
Normal file
36
examples/galois.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.galois import Galois
|
||||||
|
import matplotlib.pyplot as plt # pip install numpy==1.26.4
|
||||||
|
|
||||||
|
|
||||||
|
def operation(a, b, n):
|
||||||
|
return (a ** b) % n
|
||||||
|
|
||||||
|
q = 13
|
||||||
|
g = Galois(q, operation)
|
||||||
|
add = g.add()
|
||||||
|
div = g.div()
|
||||||
|
mul = g.mul()
|
||||||
|
sub = g.sub()
|
||||||
|
g.check_closure_law('+')
|
||||||
|
g.check_closure_law('*')
|
||||||
|
g.check_closure_law('-')
|
||||||
|
g.check_closure_law('/')
|
||||||
|
|
||||||
|
print("Addition")
|
||||||
|
g.printMatrice(add)
|
||||||
|
print("Division")
|
||||||
|
g.printMatrice(div)
|
||||||
|
print("Multiplication")
|
||||||
|
g.printMatrice(mul)
|
||||||
|
print("Substraction")
|
||||||
|
g.printMatrice(sub)
|
||||||
|
|
||||||
|
|
||||||
|
print("Primitives root")
|
||||||
|
print(g.primitiveRoot(), end="\n\n")
|
||||||
|
|
||||||
|
#print("Identity elements")
|
||||||
|
g.check_identity_add()
|
||||||
|
g.check_identity_mul()
|
||||||
55
examples/group.py
Normal file
55
examples/group.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.group import Group
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
n = 18
|
||||||
|
def operation(e1, e2, n) -> int:
|
||||||
|
return e1 * e2 % n
|
||||||
|
|
||||||
|
# Generate the group G
|
||||||
|
g = list()
|
||||||
|
for i in range(1, n):
|
||||||
|
#if gcd(i, n) == 1:
|
||||||
|
g.append(i)
|
||||||
|
|
||||||
|
G = Group(n = n, g = g, ope=operation)
|
||||||
|
print(f"n = {n}")
|
||||||
|
print(f"G = {G.getG()}")
|
||||||
|
|
||||||
|
if G.closure() is False:
|
||||||
|
print("The closure law is not respected. It's not an abelian (commutative) group")
|
||||||
|
else:
|
||||||
|
print("It is a closure group")
|
||||||
|
|
||||||
|
if G.associative() is False:
|
||||||
|
print("The associative law is not respected. It's not a group")
|
||||||
|
else:
|
||||||
|
print("It is an associative group")
|
||||||
|
|
||||||
|
if G.identity() is False:
|
||||||
|
print("The group hasn't an identity element")
|
||||||
|
else:
|
||||||
|
print(f"Identity: {G.getIdentity()}")
|
||||||
|
|
||||||
|
if G.reverse() is False:
|
||||||
|
print(f"The group hasn't a reverse")
|
||||||
|
else:
|
||||||
|
print(f"Reverses: {G.getReverses()}")
|
||||||
|
|
||||||
|
#reverses = G.getReverses()
|
||||||
|
#plt.rcParams["figure.figsize"] = [7.00, 3.50]
|
||||||
|
#plt.rcParams["figure.autolayout"] = True
|
||||||
|
#for key, value in reverses.items():
|
||||||
|
# x = key
|
||||||
|
# y = value
|
||||||
|
# plt.plot(x, y, marker="o", markersize=2, markeredgecolor="blue")
|
||||||
|
# #plt.Circle((0, n), 0.2, color='r')
|
||||||
|
#
|
||||||
|
#plt.xlim(0, n)
|
||||||
|
#plt.ylim(0, n)
|
||||||
|
#plt.grid()
|
||||||
|
#plt.show()
|
||||||
|
|
||||||
6
examples/main.py
Normal file
6
examples/main.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from utils.primeNumber import primeNumber
|
||||||
|
|
||||||
|
print(primeNumber(19))
|
||||||
|
print(primeNumber(20))
|
||||||
25
examples/plotlib.py
Normal file
25
examples/plotlib.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.primeNumber import get_n_prime_numbers
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
#import numpy as np
|
||||||
|
|
||||||
|
# Get list of n prime numbers
|
||||||
|
n = 100
|
||||||
|
primes = get_n_prime_numbers(n)
|
||||||
|
print(primes)
|
||||||
|
|
||||||
|
# With matplotlib, show into a graphics and try to explain that
|
||||||
|
plt.rcParams["figure.figsize"] = [7.00, 3.50]
|
||||||
|
plt.rcParams["figure.autolayout"] = True
|
||||||
|
for i in range(0, n):
|
||||||
|
x = primes[i]
|
||||||
|
y = primes[i]
|
||||||
|
plt.plot(x, y, marker="o", markersize=2, markeredgecolor="blue")
|
||||||
|
|
||||||
|
|
||||||
|
plt.xlim(0, n)
|
||||||
|
plt.ylim(0, n)
|
||||||
|
plt.grid()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
53
examples/pollard.py
Normal file
53
examples/pollard.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.factorization import pollard_p_minus_1
|
||||||
|
from Cryptotools.Numbers.primeNumber import _millerRabinTest, getPrimeNumber
|
||||||
|
from sympy.ntheory.factor_ import pollard_pm1
|
||||||
|
from sympy import factorint
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def pollard(n):
|
||||||
|
p = pollard_p_minus_1(n, B=10)
|
||||||
|
if p is not None:
|
||||||
|
print(p, n / p)
|
||||||
|
print(pollard_pm1(n, B=10))
|
||||||
|
print()
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def safePrime(p):
|
||||||
|
nP = 2 * p + 1
|
||||||
|
return _millerRabinTest(nP)
|
||||||
|
|
||||||
|
#pollard(299)
|
||||||
|
#pollard(257 * 1009)
|
||||||
|
#pollard(1684) # Doesn't works
|
||||||
|
|
||||||
|
# Test for RSA
|
||||||
|
#p = 281
|
||||||
|
while True:
|
||||||
|
while True:
|
||||||
|
p = getPrimeNumber(64)
|
||||||
|
if ((p - 1) / 2520) % 2 == 0.0:
|
||||||
|
#print(p)
|
||||||
|
break
|
||||||
|
#p = 322506219347091343
|
||||||
|
#q = 13953581789873249851
|
||||||
|
# n = p * q
|
||||||
|
while True:
|
||||||
|
q = getPrimeNumber(64)
|
||||||
|
if int(((q - 1) / 2520) % 2) == 1:
|
||||||
|
#print(q)
|
||||||
|
break
|
||||||
|
|
||||||
|
#q = 223
|
||||||
|
n = p * q
|
||||||
|
##print(n)
|
||||||
|
#print(pollard(n))
|
||||||
|
#break
|
||||||
|
if pollard(n): # We can factorize n
|
||||||
|
break
|
||||||
|
|
||||||
|
print(safePrime(p))
|
||||||
|
#print(safePrime(q))
|
||||||
8
examples/prime.py
Normal file
8
examples/prime.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.primeNumber import getPrimeNumber, sophieGermainPrime
|
||||||
|
|
||||||
|
p = getPrimeNumber(512)
|
||||||
|
print(p)
|
||||||
|
if sophieGermainPrime(p):
|
||||||
|
print("It's a safe prime")
|
||||||
17
examples/pseudoprimes.py
Normal file
17
examples/pseudoprimes.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.primeNumber import _millerRabinTest, _fermatLittleTheorem
|
||||||
|
from Cryptotools.Numbers.carmi import carmi_numbers, is_carmi_number, generate_carmi_numbers
|
||||||
|
|
||||||
|
print(_fermatLittleTheorem(1729))
|
||||||
|
print(_fermatLittleTheorem(1105))
|
||||||
|
print(_fermatLittleTheorem(6601))
|
||||||
|
print(_millerRabinTest(1729))
|
||||||
|
|
||||||
|
print(f"1729: {is_carmi_number(1729)}")
|
||||||
|
print(f"1105: {is_carmi_number(1105)}")
|
||||||
|
print(f"110: {is_carmi_number(110)}")
|
||||||
|
print(f"2465: {is_carmi_number(2465)}")
|
||||||
|
print(f"6601: {is_carmi_number(6601)}")
|
||||||
|
#print(carmi_numbers(1729))
|
||||||
|
print(generate_carmi_numbers(10))
|
||||||
22
examples/rsa.py
Normal file
22
examples/rsa.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Encryptions.RSA import RSA
|
||||||
|
|
||||||
|
|
||||||
|
rsa = RSA()
|
||||||
|
rsa.generateKeys(size=512)
|
||||||
|
|
||||||
|
e = rsa.e
|
||||||
|
d = rsa.d
|
||||||
|
n = rsa.n
|
||||||
|
|
||||||
|
s = "I am encrypted with RSA"
|
||||||
|
print(f"plaintext: {s}")
|
||||||
|
encrypted = rsa.encrypt(s)
|
||||||
|
|
||||||
|
# Encrypt data
|
||||||
|
# print(f"ciphertext: {encrypted}")
|
||||||
|
|
||||||
|
# We decrypt
|
||||||
|
plaintext = rsa.decrypt(encrypted)
|
||||||
|
print(f"Plaintext: {plaintext}")
|
||||||
52
examples/rsa_problem.py
Normal file
52
examples/rsa_problem.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.coprime import phi
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
|
||||||
|
def generate_keys():
|
||||||
|
p = 7853
|
||||||
|
q = 7919
|
||||||
|
n = p * q
|
||||||
|
e = 65536 # It's public value, must be coprime with phi n
|
||||||
|
|
||||||
|
print(n)
|
||||||
|
#phin = phi(n)
|
||||||
|
phin = (p - 1) * (q - 1)
|
||||||
|
print(phin)
|
||||||
|
|
||||||
|
for _ in range(2, phin):
|
||||||
|
if gcd(phin, e) == 1:
|
||||||
|
break
|
||||||
|
e += 1
|
||||||
|
|
||||||
|
print(e)
|
||||||
|
plaintext = 'A'
|
||||||
|
ciphertext = pow(ord(plaintext), e, n)
|
||||||
|
print(f"Ciphertext: {ciphertext}")
|
||||||
|
|
||||||
|
# Now, we can test
|
||||||
|
|
||||||
|
# To resolve that formula: C = x ** e mod n
|
||||||
|
# Where C is the ciphertext, and C, e and n are known (public values)
|
||||||
|
# First, we need to find the reverse modular of phi(n) or carmi(n)
|
||||||
|
# z = e -1 mod phi(n)
|
||||||
|
# After that, we have our decryption key, we can resolve x
|
||||||
|
# x = C ** z mod n
|
||||||
|
# The RSA Problem is to decrypt with the public-key
|
||||||
|
# We just need to find the decryption key with the public-key and the modulus
|
||||||
|
|
||||||
|
# First, we need to find phi(n)
|
||||||
|
# phin = phi(n) # I computed here, result = 62172136
|
||||||
|
|
||||||
|
n = 62187907
|
||||||
|
phin = 62172136
|
||||||
|
e = 65537
|
||||||
|
ciphertext = 38605768
|
||||||
|
# print(phin)
|
||||||
|
|
||||||
|
# Find the reverse modular
|
||||||
|
d = pow(e, -1, phin)
|
||||||
|
# print(d)
|
||||||
|
plaintext = pow(ciphertext, d, n)
|
||||||
|
print(chr(plaintext))
|
||||||
|
|
||||||
6
examples/sieveOfEratosthenes.py
Normal file
6
examples/sieveOfEratosthenes.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.primeNumber import sieveOfEratosthenes
|
||||||
|
|
||||||
|
print(sieveOfEratosthenes(100))
|
||||||
|
print()
|
||||||
15
examples/test_gcd.py
Normal file
15
examples/test_gcd.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
from Cryptotools.Utils.utils import gcd
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(1, 30):
|
||||||
|
if 30 % i == 0:
|
||||||
|
print(i)
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
for i in range(1, 40):
|
||||||
|
if 40 % i == 0:
|
||||||
|
print(i)
|
||||||
|
|
||||||
|
print(gcd(30, 40))
|
||||||
17
mkdocs.yml
Normal file
17
mkdocs.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
site_name: CryptoTools documentation
|
||||||
|
theme:
|
||||||
|
name: "readthedocs"
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
- mkdocstrings
|
||||||
|
|
||||||
|
nav:
|
||||||
|
- Introduction: introduction.md
|
||||||
|
- Installation: installation.md
|
||||||
|
- Low-level cryptographic:
|
||||||
|
- Number theory: number-theory.md
|
||||||
|
- Group theory: group-theory.md
|
||||||
|
- Public Keys:
|
||||||
|
- RSA: rsa.md
|
||||||
|
- Examples:
|
||||||
|
- Generating RSA Keys: examples-rsa-keys.md
|
||||||
16
pyproject.toml
Normal file
16
pyproject.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[project]
|
||||||
|
name = "Cryptotools"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = ""
|
||||||
|
authors = [
|
||||||
|
{name = "gbucchino",email = "gbucchino@fortinet-us.com"}
|
||||||
|
]
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.10"
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
sympy
|
||||||
|
mkdocs
|
||||||
|
mkdocstrings[python]
|
||||||
|
mkdocs-readthedocs
|
||||||
|
mkdocs-material
|
||||||
22
setup.py
Normal file
22
setup.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
|
||||||
|
_version = "1.0"
|
||||||
|
_project_name = "Cryptotools"
|
||||||
|
|
||||||
|
_packages = [
|
||||||
|
"Numbers",
|
||||||
|
"Groups",
|
||||||
|
"Utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name=_project_name,
|
||||||
|
version=_version,
|
||||||
|
description="Cryptography library",
|
||||||
|
author="Geoffrey Bucchino",
|
||||||
|
author_email="contact@bucchino.org",
|
||||||
|
packages=find_packages(),
|
||||||
|
#packages=_packages,
|
||||||
|
#package_dir={"": "Cryptotools"}
|
||||||
|
)
|
||||||
29
sieves_base.py
Normal file
29
sieves_base.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Numbers.primeNumber import isPrimeNumber
|
||||||
|
|
||||||
|
def get_bases(n):
|
||||||
|
# Generate the n first prime numbers
|
||||||
|
bases = list()
|
||||||
|
i = 2
|
||||||
|
while (len(bases) < n):
|
||||||
|
if isPrimeNumber(i):
|
||||||
|
bases.append(i)
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
return bases
|
||||||
|
|
||||||
|
bases = get_bases(1000)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print("(")
|
||||||
|
index = 0
|
||||||
|
for i in range(0, len(bases)):
|
||||||
|
if index == 10:
|
||||||
|
index = 0
|
||||||
|
print(f"\n", end="")
|
||||||
|
else:
|
||||||
|
print(f"{bases[i]}", end=",")
|
||||||
|
index = index + 1
|
||||||
|
print(")")
|
||||||
122
site/404.html
Normal file
122
site/404.html
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="writer-html5" lang="en" >
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="shortcut icon" href="/img/favicon.ico" />
|
||||||
|
<title>CryptoTools documentation</title>
|
||||||
|
<link rel="stylesheet" href="/css/theme.css" />
|
||||||
|
<link rel="stylesheet" href="/css/theme_extra.css" />
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css" />
|
||||||
|
<link href="/assets/_mkdocstrings.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="/js/html5shiv.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
||||||
|
<script>hljs.highlightAll();</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="wy-body-for-nav" role="document">
|
||||||
|
|
||||||
|
<div class="wy-grid-for-nav">
|
||||||
|
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
|
||||||
|
<div class="wy-side-scroll">
|
||||||
|
<div class="wy-side-nav-search">
|
||||||
|
<a href="/." class="icon icon-home"> CryptoTools documentation
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="/introduction/">Introduction</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="/installation/">Installation</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Low-level cryptographic</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="/number-theory/">Number theory</a>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="/group-theory/">Group theory</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Public Keys</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="/rsa/">RSA</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Examples</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="/examples-rsa-keys/">Generating RSA Keys</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||||
|
<nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu">
|
||||||
|
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||||
|
<a href="/.">CryptoTools documentation</a>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
<div class="wy-nav-content">
|
||||||
|
<div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation">
|
||||||
|
<ul class="wy-breadcrumbs">
|
||||||
|
<li><a href="/." class="icon icon-home" aria-label="Docs"></a></li>
|
||||||
|
<li class="wy-breadcrumbs-aside">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||||
|
<div class="section" itemprop="articleBody">
|
||||||
|
|
||||||
|
|
||||||
|
<h1 id="404-page-not-found">404</h1>
|
||||||
|
|
||||||
|
<p><strong>Page not found</strong></p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div><footer>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div role="contentinfo">
|
||||||
|
<!-- Copyright etc -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst-versions" role="note" aria-label="Versions">
|
||||||
|
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<script src="/js/jquery-3.6.0.min.js"></script>
|
||||||
|
<script>var base_url = "/";</script>
|
||||||
|
<script src="/js/theme_extra.js"></script>
|
||||||
|
<script src="/js/theme.js"></script>
|
||||||
|
<script>
|
||||||
|
jQuery(function () {
|
||||||
|
SphinxRtdTheme.Navigation.enable(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
57
site/assets/_mkdocstrings.css
Normal file
57
site/assets/_mkdocstrings.css
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
/* Avoid breaking parameters name, etc. in table cells. */
|
||||||
|
.doc-contents td code {
|
||||||
|
word-break: normal !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No line break before first paragraph of descriptions. */
|
||||||
|
.doc-md-description,
|
||||||
|
.doc-md-description>p:first-child {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Avoid breaking code headings. */
|
||||||
|
.doc-heading code {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Improve rendering of parameters, returns and exceptions. */
|
||||||
|
.doc-contents .field-name {
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other curious-spacing fixes. */
|
||||||
|
.doc-contents .field-name,
|
||||||
|
.doc-contents .field-body {
|
||||||
|
border: none !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-contents p {
|
||||||
|
margin: 1em 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-contents .field-list {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-contents pre {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-contents .wy-table-responsive {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-contents td.code {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-contents td.linenos {
|
||||||
|
padding: 0 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-children,
|
||||||
|
footer {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
BIN
site/css/fonts/Roboto-Slab-Bold.woff
Normal file
BIN
site/css/fonts/Roboto-Slab-Bold.woff
Normal file
Binary file not shown.
BIN
site/css/fonts/Roboto-Slab-Bold.woff2
Normal file
BIN
site/css/fonts/Roboto-Slab-Bold.woff2
Normal file
Binary file not shown.
BIN
site/css/fonts/Roboto-Slab-Regular.woff
Normal file
BIN
site/css/fonts/Roboto-Slab-Regular.woff
Normal file
Binary file not shown.
BIN
site/css/fonts/Roboto-Slab-Regular.woff2
Normal file
BIN
site/css/fonts/Roboto-Slab-Regular.woff2
Normal file
Binary file not shown.
BIN
site/css/fonts/fontawesome-webfont.eot
Normal file
BIN
site/css/fonts/fontawesome-webfont.eot
Normal file
Binary file not shown.
2671
site/css/fonts/fontawesome-webfont.svg
Normal file
2671
site/css/fonts/fontawesome-webfont.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 434 KiB |
BIN
site/css/fonts/fontawesome-webfont.ttf
Normal file
BIN
site/css/fonts/fontawesome-webfont.ttf
Normal file
Binary file not shown.
BIN
site/css/fonts/fontawesome-webfont.woff
Normal file
BIN
site/css/fonts/fontawesome-webfont.woff
Normal file
Binary file not shown.
BIN
site/css/fonts/fontawesome-webfont.woff2
Normal file
BIN
site/css/fonts/fontawesome-webfont.woff2
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-bold-italic.woff
Normal file
BIN
site/css/fonts/lato-bold-italic.woff
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-bold-italic.woff2
Normal file
BIN
site/css/fonts/lato-bold-italic.woff2
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-bold.woff
Normal file
BIN
site/css/fonts/lato-bold.woff
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-bold.woff2
Normal file
BIN
site/css/fonts/lato-bold.woff2
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-normal-italic.woff
Normal file
BIN
site/css/fonts/lato-normal-italic.woff
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-normal-italic.woff2
Normal file
BIN
site/css/fonts/lato-normal-italic.woff2
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-normal.woff
Normal file
BIN
site/css/fonts/lato-normal.woff
Normal file
Binary file not shown.
BIN
site/css/fonts/lato-normal.woff2
Normal file
BIN
site/css/fonts/lato-normal.woff2
Normal file
Binary file not shown.
13
site/css/theme.css
Normal file
13
site/css/theme.css
Normal file
File diff suppressed because one or more lines are too long
197
site/css/theme_extra.css
Normal file
197
site/css/theme_extra.css
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Wrap inline code samples otherwise they shoot of the side and
|
||||||
|
* can't be read at all.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/313
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/233
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/834
|
||||||
|
*/
|
||||||
|
.rst-content code {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
padding: 2px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make code blocks display as blocks and give them the appropriate
|
||||||
|
* font size and padding.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/855
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/834
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/233
|
||||||
|
*/
|
||||||
|
.rst-content pre code {
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
display: block;
|
||||||
|
padding: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix code colors
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/2027
|
||||||
|
*/
|
||||||
|
.rst-content code {
|
||||||
|
color: #E74C3C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rst-content pre code {
|
||||||
|
color: #000;
|
||||||
|
background: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix link colors when the link text is inline code.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/718
|
||||||
|
*/
|
||||||
|
a code {
|
||||||
|
color: #2980B9;
|
||||||
|
}
|
||||||
|
a:hover code {
|
||||||
|
color: #3091d1;
|
||||||
|
}
|
||||||
|
a:visited code {
|
||||||
|
color: #9B59B6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The CSS classes from highlight.js seem to clash with the
|
||||||
|
* ReadTheDocs theme causing some code to be incorrectly made
|
||||||
|
* bold and italic.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/411
|
||||||
|
*/
|
||||||
|
pre .cs, pre .c {
|
||||||
|
font-weight: inherit;
|
||||||
|
font-style: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix some issues with the theme and non-highlighted code
|
||||||
|
* samples. Without and highlighting styles attached the
|
||||||
|
* formatting is broken.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/319
|
||||||
|
*/
|
||||||
|
.rst-content .no-highlight {
|
||||||
|
display: block;
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Additions specific to the search functionality provided by MkDocs
|
||||||
|
*/
|
||||||
|
|
||||||
|
.search-results {
|
||||||
|
margin-top: 23px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results article {
|
||||||
|
border-top: 1px solid #E1E4E5;
|
||||||
|
padding-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results article:first-child {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .search-query {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 50px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-color: #D1D4D5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Improve inline code blocks within admonitions.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/656
|
||||||
|
*/
|
||||||
|
.rst-content .admonition code {
|
||||||
|
color: #404040;
|
||||||
|
border: 1px solid #c7c9cb;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||||
|
background: #f8fbfd;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Account for wide tables which go off the side.
|
||||||
|
* Override borders to avoid weirdness on narrow tables.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/834
|
||||||
|
* https://github.com/mkdocs/mkdocs/pull/1034
|
||||||
|
*/
|
||||||
|
.rst-content .section .docutils {
|
||||||
|
width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
display: block;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
border: 1px solid #e1e4e5 !important;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Without the following amendments, the navigation in the theme will be
|
||||||
|
* slightly cut off. This is due to the fact that the .wy-nav-side has a
|
||||||
|
* padding-bottom of 2em, which must not necessarily align with the font-size of
|
||||||
|
* 90 % on the .rst-current-version container, combined with the padding of 12px
|
||||||
|
* above and below. These amendments fix this in two steps: First, make sure the
|
||||||
|
* .rst-current-version container has a fixed height of 40px, achieved using
|
||||||
|
* line-height, and then applying a padding-bottom of 40px to this container. In
|
||||||
|
* a second step, the items within that container are re-aligned using flexbox.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/2012
|
||||||
|
*/
|
||||||
|
.wy-nav-side {
|
||||||
|
padding-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For section-index only */
|
||||||
|
.wy-menu-vertical .current-section p {
|
||||||
|
background-color: #e3e3e3;
|
||||||
|
color: #404040;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The second step of above amendment: Here we make sure the items are aligned
|
||||||
|
* correctly within the .rst-current-version container. Using flexbox, we
|
||||||
|
* achieve it in such a way that it will look like the following:
|
||||||
|
*
|
||||||
|
* [No repo_name]
|
||||||
|
* Next >> // On the first page
|
||||||
|
* << Previous Next >> // On all subsequent pages
|
||||||
|
*
|
||||||
|
* [With repo_name]
|
||||||
|
* <repo_name> Next >> // On the first page
|
||||||
|
* <repo_name> << Previous Next >> // On all subsequent pages
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/2012
|
||||||
|
*/
|
||||||
|
.rst-versions .rst-current-version {
|
||||||
|
padding: 0 12px;
|
||||||
|
display: flex;
|
||||||
|
font-size: initial;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Please note that this amendment also involves removing certain inline-styles
|
||||||
|
* from the file ./mkdocs/themes/readthedocs/versions.html.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/2012
|
||||||
|
*/
|
||||||
|
.rst-current-version span {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
158
site/examples-rsa-keys/index.html
Normal file
158
site/examples-rsa-keys/index.html
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="writer-html5" lang="en" >
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="shortcut icon" href="../img/favicon.ico" />
|
||||||
|
<title>Generating RSA Keys - CryptoTools documentation</title>
|
||||||
|
<link rel="stylesheet" href="../css/theme.css" />
|
||||||
|
<link rel="stylesheet" href="../css/theme_extra.css" />
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css" />
|
||||||
|
<link href="../assets/_mkdocstrings.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Current page data
|
||||||
|
var mkdocs_page_name = "Generating RSA Keys";
|
||||||
|
var mkdocs_page_input_path = "examples-rsa-keys.md";
|
||||||
|
var mkdocs_page_url = null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="../js/html5shiv.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
||||||
|
<script>hljs.highlightAll();</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="wy-body-for-nav" role="document">
|
||||||
|
|
||||||
|
<div class="wy-grid-for-nav">
|
||||||
|
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
|
||||||
|
<div class="wy-side-scroll">
|
||||||
|
<div class="wy-side-nav-search">
|
||||||
|
<a href=".." class="icon icon-home"> CryptoTools documentation
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../introduction/">Introduction</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../installation/">Installation</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Low-level cryptographic</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../number-theory/">Number theory</a>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../group-theory/">Group theory</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Public Keys</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../rsa/">RSA</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Examples</span></p>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1 current"><a class="reference internal current" href="#">Generating RSA Keys</a>
|
||||||
|
<ul class="current">
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||||
|
<nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu">
|
||||||
|
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||||
|
<a href="..">CryptoTools documentation</a>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
<div class="wy-nav-content">
|
||||||
|
<div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation">
|
||||||
|
<ul class="wy-breadcrumbs">
|
||||||
|
<li><a href=".." class="icon icon-home" aria-label="Docs"></a></li>
|
||||||
|
<li class="breadcrumb-item">Examples</li>
|
||||||
|
<li class="breadcrumb-item active">Generating RSA Keys</li>
|
||||||
|
<li class="wy-breadcrumbs-aside">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||||
|
<div class="section" itemprop="articleBody">
|
||||||
|
|
||||||
|
<h1 id="generating-rsa-keys">Generating RSA Keys</h1>
|
||||||
|
<p>In the following section, we are going to see how to generate RSA Keys and how to encrypt data with these keys.</p>
|
||||||
|
<pre><code>#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Encryptions.RSA import RSA
|
||||||
|
|
||||||
|
|
||||||
|
rsa = RSA()
|
||||||
|
rsa.generateKeys(size=512)
|
||||||
|
|
||||||
|
e = rsa.e
|
||||||
|
d = rsa.d
|
||||||
|
n = rsa.n
|
||||||
|
|
||||||
|
s = "I am encrypted with RSA"
|
||||||
|
print(f"plaintext: {s}")
|
||||||
|
encrypted = rsa.encrypt(s)
|
||||||
|
|
||||||
|
# Encrypt data
|
||||||
|
print(f"ciphertext: {encrypted}")
|
||||||
|
|
||||||
|
# We decrypt
|
||||||
|
plaintext = rsa.decrypt(encrypted)
|
||||||
|
print(f"Plaintext: {plaintext}")
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div><footer>
|
||||||
|
<div class="rst-footer-buttons" role="navigation" aria-label="Footer Navigation">
|
||||||
|
<a href="../rsa/" class="btn btn-neutral float-left" title="RSA"><span class="icon icon-circle-arrow-left"></span> Previous</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div role="contentinfo">
|
||||||
|
<!-- Copyright etc -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst-versions" role="note" aria-label="Versions">
|
||||||
|
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||||
|
|
||||||
|
|
||||||
|
<span><a href="../rsa/" style="color: #fcfcfc">« Previous</a></span>
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<script src="../js/jquery-3.6.0.min.js"></script>
|
||||||
|
<script>var base_url = "..";</script>
|
||||||
|
<script src="../js/theme_extra.js"></script>
|
||||||
|
<script src="../js/theme.js"></script>
|
||||||
|
<script>
|
||||||
|
jQuery(function () {
|
||||||
|
SphinxRtdTheme.Navigation.enable(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
3059
site/group-theory/index.html
Normal file
3059
site/group-theory/index.html
Normal file
File diff suppressed because it is too large
Load Diff
BIN
site/img/favicon.ico
Normal file
BIN
site/img/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
148
site/index.html
Normal file
148
site/index.html
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="writer-html5" lang="en" >
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="description" content="None" />
|
||||||
|
<link rel="shortcut icon" href="img/favicon.ico" />
|
||||||
|
<title>CryptoTools documentation</title>
|
||||||
|
<link rel="stylesheet" href="css/theme.css" />
|
||||||
|
<link rel="stylesheet" href="css/theme_extra.css" />
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css" />
|
||||||
|
<link href="assets/_mkdocstrings.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Current page data
|
||||||
|
var mkdocs_page_name = "Welcome to CryptoTools";
|
||||||
|
var mkdocs_page_input_path = "index.md";
|
||||||
|
var mkdocs_page_url = null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="js/html5shiv.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
||||||
|
<script>hljs.highlightAll();</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="wy-body-for-nav" role="document">
|
||||||
|
|
||||||
|
<div class="wy-grid-for-nav">
|
||||||
|
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
|
||||||
|
<div class="wy-side-scroll">
|
||||||
|
<div class="wy-side-nav-search">
|
||||||
|
<a href="." class="icon icon-home"> CryptoTools documentation
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="introduction/">Introduction</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="installation/">Installation</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Low-level cryptographic</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="number-theory/">Number theory</a>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="group-theory/">Group theory</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Public Keys</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="rsa/">RSA</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Examples</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="examples-rsa-keys/">Generating RSA Keys</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||||
|
<nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu">
|
||||||
|
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||||
|
<a href=".">CryptoTools documentation</a>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
<div class="wy-nav-content">
|
||||||
|
<div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation">
|
||||||
|
<ul class="wy-breadcrumbs">
|
||||||
|
<li><a href="." class="icon icon-home" aria-label="Docs"></a></li>
|
||||||
|
<li class="breadcrumb-item active">Welcome to CryptoTools</li>
|
||||||
|
<li class="wy-breadcrumbs-aside">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||||
|
<div class="section" itemprop="articleBody">
|
||||||
|
|
||||||
|
<h1 id="welcome-to-cryptotools">Welcome to CryptoTools</h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/introduction">Introduction</a></li>
|
||||||
|
<li><a href="/installation">Installation</a></li>
|
||||||
|
<li>Low-Level Cryptographic<ul>
|
||||||
|
<li><a href="/number-theory">Number Theory</a></li>
|
||||||
|
<li><a href="/group-theory">Group Theory</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Public Keys:<ul>
|
||||||
|
<li><a href="/rsa">RSA</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Examples:<ul>
|
||||||
|
<li><a href="/examples-rsa-keys">Generating RSA keys</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div><footer>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div role="contentinfo">
|
||||||
|
<!-- Copyright etc -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst-versions" role="note" aria-label="Versions">
|
||||||
|
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<script src="js/jquery-3.6.0.min.js"></script>
|
||||||
|
<script>var base_url = ".";</script>
|
||||||
|
<script src="js/theme_extra.js"></script>
|
||||||
|
<script src="js/theme.js"></script>
|
||||||
|
<script>
|
||||||
|
jQuery(function () {
|
||||||
|
SphinxRtdTheme.Navigation.enable(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
MkDocs version : 1.6.1
|
||||||
|
Build Date UTC : 2026-01-06 07:48:31.465035+00:00
|
||||||
|
-->
|
||||||
149
site/installation/index.html
Normal file
149
site/installation/index.html
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="writer-html5" lang="en" >
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="shortcut icon" href="../img/favicon.ico" />
|
||||||
|
<title>Installation - CryptoTools documentation</title>
|
||||||
|
<link rel="stylesheet" href="../css/theme.css" />
|
||||||
|
<link rel="stylesheet" href="../css/theme_extra.css" />
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css" />
|
||||||
|
<link href="../assets/_mkdocstrings.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Current page data
|
||||||
|
var mkdocs_page_name = "Installation";
|
||||||
|
var mkdocs_page_input_path = "installation.md";
|
||||||
|
var mkdocs_page_url = null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="../js/html5shiv.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
||||||
|
<script>hljs.highlightAll();</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="wy-body-for-nav" role="document">
|
||||||
|
|
||||||
|
<div class="wy-grid-for-nav">
|
||||||
|
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
|
||||||
|
<div class="wy-side-scroll">
|
||||||
|
<div class="wy-side-nav-search">
|
||||||
|
<a href=".." class="icon icon-home"> CryptoTools documentation
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../introduction/">Introduction</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1 current"><a class="reference internal current" href="#">Installation</a>
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l2"><a class="reference internal" href="#installation-from-source">Installation from source</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Low-level cryptographic</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../number-theory/">Number theory</a>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../group-theory/">Group theory</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Public Keys</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../rsa/">RSA</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Examples</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../examples-rsa-keys/">Generating RSA Keys</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||||
|
<nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu">
|
||||||
|
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||||
|
<a href="..">CryptoTools documentation</a>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
<div class="wy-nav-content">
|
||||||
|
<div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation">
|
||||||
|
<ul class="wy-breadcrumbs">
|
||||||
|
<li><a href=".." class="icon icon-home" aria-label="Docs"></a></li>
|
||||||
|
<li class="breadcrumb-item active">Installation</li>
|
||||||
|
<li class="wy-breadcrumbs-aside">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||||
|
<div class="section" itemprop="articleBody">
|
||||||
|
|
||||||
|
<h1 id="installation">Installation</h1>
|
||||||
|
<p>To install the project, you should install from my own Python repository but, you first need to deploy your virtual enviroment.</p>
|
||||||
|
<h2 id="installation-from-source">Installation from source</h2>
|
||||||
|
<p>You can install from the source. Download the <a href="https://gitea.bucchino.org/gbucchino/cryptotools.git">project</a> and install it in your virtual environment:</p>
|
||||||
|
<pre><code>$ virtualenv ~/venv/cryptotools
|
||||||
|
$ source ~/venv/cryptotools/bin/activate
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>$ git clone https://gitea.bucchino.org/gbucchino/cryptotools.git
|
||||||
|
$ cd cryptotools
|
||||||
|
$ python3 setup.py install
|
||||||
|
</code></pre>
|
||||||
|
<p>The installation is completed. You can know use Cryptotools package into your project. In the directory <code>examples</code> you may find some examples scripts</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div><footer>
|
||||||
|
<div class="rst-footer-buttons" role="navigation" aria-label="Footer Navigation">
|
||||||
|
<a href="../introduction/" class="btn btn-neutral float-left" title="Introduction"><span class="icon icon-circle-arrow-left"></span> Previous</a>
|
||||||
|
<a href="../number-theory/" class="btn btn-neutral float-right" title="Number theory">Next <span class="icon icon-circle-arrow-right"></span></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div role="contentinfo">
|
||||||
|
<!-- Copyright etc -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst-versions" role="note" aria-label="Versions">
|
||||||
|
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||||
|
|
||||||
|
|
||||||
|
<span><a href="../introduction/" style="color: #fcfcfc">« Previous</a></span>
|
||||||
|
|
||||||
|
|
||||||
|
<span><a href="../number-theory/" style="color: #fcfcfc">Next »</a></span>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<script src="../js/jquery-3.6.0.min.js"></script>
|
||||||
|
<script>var base_url = "..";</script>
|
||||||
|
<script src="../js/theme_extra.js"></script>
|
||||||
|
<script src="../js/theme.js"></script>
|
||||||
|
<script>
|
||||||
|
jQuery(function () {
|
||||||
|
SphinxRtdTheme.Navigation.enable(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
136
site/introduction/index.html
Normal file
136
site/introduction/index.html
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="writer-html5" lang="en" >
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<link rel="shortcut icon" href="../img/favicon.ico" />
|
||||||
|
<title>Introduction - CryptoTools documentation</title>
|
||||||
|
<link rel="stylesheet" href="../css/theme.css" />
|
||||||
|
<link rel="stylesheet" href="../css/theme_extra.css" />
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css" />
|
||||||
|
<link href="../assets/_mkdocstrings.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Current page data
|
||||||
|
var mkdocs_page_name = "Introduction";
|
||||||
|
var mkdocs_page_input_path = "introduction.md";
|
||||||
|
var mkdocs_page_url = null;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="../js/html5shiv.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
|
||||||
|
<script>hljs.highlightAll();</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="wy-body-for-nav" role="document">
|
||||||
|
|
||||||
|
<div class="wy-grid-for-nav">
|
||||||
|
<nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
|
||||||
|
<div class="wy-side-scroll">
|
||||||
|
<div class="wy-side-nav-search">
|
||||||
|
<a href=".." class="icon icon-home"> CryptoTools documentation
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
|
||||||
|
<ul class="current">
|
||||||
|
<li class="toctree-l1 current"><a class="reference internal current" href="#">Introduction</a>
|
||||||
|
<ul class="current">
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../installation/">Installation</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Low-level cryptographic</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../number-theory/">Number theory</a>
|
||||||
|
</li>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../group-theory/">Group theory</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Public Keys</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../rsa/">RSA</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p class="caption"><span class="caption-text">Examples</span></p>
|
||||||
|
<ul>
|
||||||
|
<li class="toctree-l1"><a class="reference internal" href="../examples-rsa-keys/">Generating RSA Keys</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||||
|
<nav class="wy-nav-top" role="navigation" aria-label="Mobile navigation menu">
|
||||||
|
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||||
|
<a href="..">CryptoTools documentation</a>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
<div class="wy-nav-content">
|
||||||
|
<div class="rst-content"><div role="navigation" aria-label="breadcrumbs navigation">
|
||||||
|
<ul class="wy-breadcrumbs">
|
||||||
|
<li><a href=".." class="icon icon-home" aria-label="Docs"></a></li>
|
||||||
|
<li class="breadcrumb-item active">Introduction</li>
|
||||||
|
<li class="wy-breadcrumbs-aside">
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||||
|
<div class="section" itemprop="articleBody">
|
||||||
|
|
||||||
|
<h1 id="cryptotools">CryptoTools</h1>
|
||||||
|
<p>CryptoTools is a Python package that provides low-level cryptographic primitives for generating strong numbers. With this project, it's possible to generate public key cryptosystems such as RSA.
|
||||||
|
This project has a academic purpose and can not be used in production enviroment yet.</p>
|
||||||
|
<p>So far, my cryptographic modules are not compliant with <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.140-3.pdf">FIPS 140-3</a> but in the future, that will be.</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div><footer>
|
||||||
|
<div class="rst-footer-buttons" role="navigation" aria-label="Footer Navigation">
|
||||||
|
<a href="../installation/" class="btn btn-neutral float-right" title="Installation">Next <span class="icon icon-circle-arrow-right"></span></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div role="contentinfo">
|
||||||
|
<!-- Copyright etc -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="rst-versions" role="note" aria-label="Versions">
|
||||||
|
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<span><a href="../installation/" style="color: #fcfcfc">Next »</a></span>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<script src="../js/jquery-3.6.0.min.js"></script>
|
||||||
|
<script>var base_url = "..";</script>
|
||||||
|
<script src="../js/theme_extra.js"></script>
|
||||||
|
<script src="../js/theme.js"></script>
|
||||||
|
<script>
|
||||||
|
jQuery(function () {
|
||||||
|
SphinxRtdTheme.Navigation.enable(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4
site/js/html5shiv.min.js
vendored
Normal file
4
site/js/html5shiv.min.js
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||||
|
*/
|
||||||
|
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);
|
||||||
2
site/js/jquery-3.6.0.min.js
vendored
Normal file
2
site/js/jquery-3.6.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
site/js/theme.js
Normal file
2
site/js/theme.js
Normal file
File diff suppressed because one or more lines are too long
8
site/js/theme_extra.js
Normal file
8
site/js/theme_extra.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Assign 'docutils' class to tables so styling and
|
||||||
|
* JavaScript behavior is applied.
|
||||||
|
*
|
||||||
|
* https://github.com/mkdocs/mkdocs/issues/2028
|
||||||
|
*/
|
||||||
|
|
||||||
|
$('div.rst-content table').addClass('docutils');
|
||||||
1380
site/number-theory/index.html
Normal file
1380
site/number-theory/index.html
Normal file
File diff suppressed because it is too large
Load Diff
BIN
site/objects.inv
Normal file
BIN
site/objects.inv
Normal file
Binary file not shown.
1086
site/rsa/index.html
Normal file
1086
site/rsa/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3
site/sitemap.xml
Normal file
3
site/sitemap.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
</urlset>
|
||||||
BIN
site/sitemap.xml.gz
Normal file
BIN
site/sitemap.xml.gz
Normal file
Binary file not shown.
1
tests/carmi_function_oeis
Normal file
1
tests/carmi_function_oeis
Normal file
@ -0,0 +1 @@
|
|||||||
|
1, 1, 2, 2, 4, 2, 6, 2, 6, 4, 10, 2, 12, 6, 4, 4, 16, 6, 18, 4, 6, 10, 22, 2, 20, 12, 18, 6, 28, 4, 30, 8, 10, 16, 12, 6, 36, 18, 12, 4, 40, 6, 42, 10, 12, 22, 46, 4, 42, 20, 16, 12, 52, 18, 20, 6, 18, 28, 58, 4, 60, 30, 6, 16, 12, 10, 66, 16, 22, 12, 70, 6, 72, 36, 20, 18, 30, 12, 78, 4, 54
|
||||||
1
tests/carmi_numbers_oeis
Normal file
1
tests/carmi_numbers_oeis
Normal file
@ -0,0 +1 @@
|
|||||||
|
561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841, 29341, 41041, 46657, 52633, 62745, 63973, 75361, 101101, 115921, 126217, 162401, 172081, 188461, 252601, 278545, 294409, 314821, 334153, 340561, 399001, 410041, 449065, 488881, 512461, 530881, 552721
|
||||||
8
tests/execute_tests.py
Executable file
8
tests/execute_tests.py
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
source /home/geoffrey/venv/forensic/bin/activate;
|
||||||
|
for test in `ls tests/test_*.py`; do
|
||||||
|
echo $test;
|
||||||
|
python3 $test -v;
|
||||||
|
done
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user