initial commit

main
marius 2023-05-31 17:12:13 +02:00
parent 20a4478f77
commit f377305f49
4 changed files with 516 additions and 0 deletions

184
.gitignore vendored Normal file
View File

@ -0,0 +1,184 @@
# Created by .ignore support plugin (hsz.mobi)
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# IPython Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
### VirtualEnv template
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# idea folder, uncomment if you don't need it
.idea

262
lib/gcd_tables.py Normal file
View File

@ -0,0 +1,262 @@
'''
Source: extendedeuclideanalgorithm.com
Modified to generate CSV tables
for iterative calculation of the modular inverse
'''
import math
# Warning: can't handle b=0. See extendedeuclideanalgorithm.com/code for a version that can
def gcd_iterative(a, b):
""" Calculating the greatest common divisor
using the Euclidean Algorithm (non-recursive)
(Source: extendedeuclideanalgorithm.com/code)
"""
# Set default values for the quotient and the remainder
q = 0
r = 1
'''
In each iteration of the loop below, we
calculate the new quotient, remainder, a and b.
r decreases, so we stop when r = 0
'''
while (r > 0):
# The calculations
q = math.floor(a / b)
r = a - q * b
# The values for the next iteration
a = b
b = r if (r > 0) else b
return abs(b)
# Can handle b=0
def gcd_iterative_2(a, b):
""" Calculating the greatest common divisor
using the Euclidean Algorithm (non-recursive)
(Source: extendedeuclideanalgorithm.com/code)
"""
# Set default values for the quotient and the remainder
q = 0
r = 1
'''
In each iteration of the loop below, we
calculate the new quotient, remainder, a and b.
r decreases, so we stop when r = 0
'''
while (b > 0):
# The calculations
q = math.floor(a / b)
r = a - q * b
# The values for the next iteration
a = b
b = r
return abs(a)
def gcd(a, b):
""" Calculating the greatest common divisor
using the Euclidean Algorithm (recursive)
(Source: extendedeuclideanalgorithm.com/code)
"""
if (b == 0):
return abs(a)
q = math.floor(a / b)
r = a - q * b
return abs(b) if (r == 0) else gcd(b, r)
# Warning: this version can't handle b=0. See extendedeuclideanalgorithm.com/code for a version that can.
def xgcd_iterative(a, b):
""" Calculates the gcd and Bezout coefficients,
using the Extended Euclidean Algorithm (non-recursive).
(Source: extendedeuclideanalgorithm.com/code)
"""
# Set default values for the quotient, remainder,
# s-variables and t-variables
q = 0
r = 1
s1 = 1
s2 = 0
s3 = 1
t1 = 0
t2 = 1
t3 = 0
'''
In each iteration of the loop below, we
calculate the new quotient, remainder, a, b,
and the new s-variables and t-variables.
r decreases, so we stop when r = 0
'''
while (r > 0):
# The calculations
q = math.floor(a / b)
r = a - q * b
s3 = s1 - q * s2
t3 = t1 - q * t2
'''
The values for the next iteration,
(but only if there is a next iteration)
'''
if (r > 0):
a = b
b = r
s1 = s2
s2 = s3
t1 = t2
t2 = t3
return abs(b), s2, t2
# Can handle b=0
def xgcd_iterative_2(a, b):
""" Calculates the gcd and Bezout coefficients,
using the Extended Euclidean Algorithm (non-recursive).
(Source: extendedeuclideanalgorithm.com/code)
"""
# Set default values for the quotient, remainder,
# s-variables and t-variables
q = 0
r = 1
s1 = 1
s2 = 0
s3 = 1
t1 = 0
t2 = 1
t3 = 0
'''
In each iteration of the loop below, we
calculate the new quotient, remainder, a, b,
and the new s-variables and t-variables.
r decreases, so we stop when r = 0
'''
# CSV output
print("i, n, b, q, r, t1, t2, t3")
i = 1
while (b > 0):
# The calculations
q = math.floor(a / b)
r = a - q * b
s3 = s1 - q * s2
t3 = t1 - q * t2
# CSV output
print("{}, {}, {}, {}, {}, {}, {}, {}".format(i, a, b, q, r, t1, t2, t3))
i += 1
'''
The values for the next iteration,
(but only if there is a next iteration)
'''
a = b
b = r
s1 = s2
s2 = s3
t1 = t2
t2 = t3
return abs(a), s1, t1
def xgcd(a, b, s1=1, s2=0, t1=0, t2=1):
""" Calculates the gcd and Bezout coefficients,
using the Extended Euclidean Algorithm (recursive).
(Source: extendedeuclideanalgorithm.com/code)
"""
if (b == 0):
return abs(a), 1, 0
q = math.floor(a / b)
r = a - q * b
s3 = s1 - q * s2
t3 = t1 - q * t2
# if r==0, then b will be the gcd and s2, t2 the Bezout coefficients
return (abs(b), s2, t2) if (r == 0) else xgcd(b, r, s2, s3, t2, t3)
def multinv(b, n):
"""
Calculates the multiplicative inverse of a number b mod n,
using the Extended Euclidean Algorithm. If b does not have a
multiplicative inverse mod n, then throw an exception.
(Source: extendedeuclideanalgorithm.com/code)
"""
# Get the gcd and the second Bezout coefficient (t)
# from the Extended Euclidean Algorithm. (We don't need s)
my_gcd, _, t = xgcd(n, b)
# It only has a multiplicative inverse if the gcd is 1
if (my_gcd == 1):
return t % n
else:
raise ValueError('{} has no multiplicative inverse modulo {}'.format(b, n))
def make_eea_table(a : int, b : int):
'''
Euclidean algorithm:
see the output of gcd(a, b)
'''
print('Euclidean Algorithm:')
print('The gcd of', a, 'and', b, 'is', gcd(a, b))
# -------------------------------------------------------------
'''
Extended Euclidean Algorithm:
see the output of xgcd(a,b) and Bezout coefficients
And verify that they are correct
'''
my_gcd, s, t = xgcd(a, b)
verification = abs(s * a + t * b)
print('Extended Euclidean Algorithm:')
print('The gcd of', a, 'and', b, 'is', my_gcd)
print('And the Bezout coefficients: s=', s, ' and t=', t, '.', sep='')
print('And', s, '*', a, '+', t, '*', b, '=', verification)
if (my_gcd == verification):
print('So as we expect, s*a+t*b is equal to the gcd we found.')
else:
print('Something went wrong')
# ------------------------------------------------------------
b = b
n = a
'''
Multiplicative Inverse:
Try to compute the multiplicative inverse of b mod n.
If that succeeds, verify that it's correct.
If it doesn't succeed, show the error raised by the function.
'''
print('Multiplicative inverse:')
try:
# inverse = multinv(b, n);
inverse = xgcd_iterative_2(b, n)
except ValueError as error:
print(error)

10
make_eea_takes.py Normal file
View File

@ -0,0 +1,10 @@
from lib.gcd_tables import *
def check():
make_eea_table(7, 143)
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
check()

60
shanks_baby_giant_step.py Normal file
View File

@ -0,0 +1,60 @@
from math import ceil, sqrt
def bsgs(p, g, h):
##Berechne d in h = g^d mod p
N = ceil(sqrt(p - 1)) # phi(p) is p-1 if p is prime
# Baby step: compute a look-up table of g^i values for i = 0, 1, ..., N
lookup_table = {pow(g, i, p): i for i in range(N)}
# Precompute via Fermat's Little Theorem
c = pow(g, N * (p - 2), p)
# Giant step: Search for an equivalence in the lookup_table
for j in range(N):
y = (h * pow(c, j, p)) % p
if y in lookup_table:
return j * N + lookup_table[y]
# Solution not found
return None
def main():
p = 27893
g = 3729
alpha = 11819
beta = 1531
# Find the discrete logarithm a such that g^a = alpha mod p
a = bsgs(p, g, alpha)
print(f"a = {a}")
# Validate the result
if a is None:
print("No solution found for a")
else:
# Recompute the shared secret key: K = beta^a mod p
K = pow(beta, a, p)
print(f"Shared secret key K = {K}")
# Find the discrete logarithm b such that g^b = beta mod p
b = bsgs(p, g, beta)
print(f"b = {b}")
# Validate the result
if b is None:
print("No solution found for b")
else:
# Recompute the shared secret key: K = alpha^b mod p
K2 = pow(alpha, b, p)
if K2 == K:
print("b is correct")
else:
print("b is not correct")
if __name__ == '__main__':
main()