Skip to content
Snippets Groups Projects
Commit 34136ed4 authored by Maximilian Stauss's avatar Maximilian Stauss
Browse files

Beispiele angepasst

parent 84c77dec
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
from sage.all import *
from classes.MatsumotoImaiAExample import MatsumotoImaiAExample
# Endlicher Körper mit 5 Elementen:
finite_field = GF(2**2, 'a')
(a,) = finite_field.gens()
n = 3 # Drei Variablen
"""TEST MIA"""
# MIA mit den Schlüsseln initialisieren
# MatsumotoImaiAExample setzt die sonst zufälligen Werte
# wie in den Beispielen und printed mehr
MIA = MatsumotoImaiAExample(finite_field, n)
# Schlüssel im sage CLI nutzbar machen
private_key = MIA.private_key
public_key = MIA.public_key
# Schlüssel ausgeben
print("Privater Schlüssel:")
print("S:\n{}x + {}".format(private_key.S.M, private_key.S.y))
print("Pr:\n{}".format(private_key.Pr))
print("S:\n{}x + {}".format(private_key.T.M, private_key.T.y))
print("\nÖffentlicher Schlüssel:")
print("P:\n{}".format(public_key.P))
# Die Nachricht soll (1, a, a^2) sein
msg = vector(finite_field, [1, a, a**2])
print("\n\nmsg =", msg)
# Nachricht verschlüsseln
enc = public_key.encrypt(msg)
print("public_key.encrypt(msg): enc =", enc)
# Verifizieren, dass enc auch entschlüsselt wird
print("MIA.decryt(enc):", MIA.decrypt(enc))
# Signatur erstellen
msg = vector(finite_field, [a, 1, 1])
print("\nmsg =", msg)
sig = MIA.sign(msg)
print("sig =", sig)
# Signatur verifizieren
print("public_key.verify(msg, sig):", public_key.verify(msg, sig))
......@@ -4,9 +4,7 @@
from __future__ import absolute_import, division, print_function
from sage.all import *
from classes.helpers.PublicKey import PublicKey
from classes.helpers.PrivateKey import PrivateKey
from classes.UnbalancedOilAndVinegar import UnbalancedOilAndVinegar
from classes.UnbalancedOilAndVinegarExample import *
# Endlicher Körper mit 5 Elementen:
finite_field = GF(5, 'a')
......@@ -16,18 +14,32 @@ n = 3 # Drei Variablen
"""TEST UOV"""
# Initialize simple UOV
UOV = UnbalancedOilAndVinegar(finite_field, n, m, keyfile="./keys/bsp_uov2.priv")
# UOV mit den Schlüsseln initialisieren
# UnbalancedOilAndVinegarExample setzt die sonst zufälligen Werte
# wie in den Beispielen und printed mehr
UOV = UnbalancedOilAndVinegarExample(
finite_field, n, m, keyfile="./keys/bsp_uov.priv")
# Schlüssel im sage CLI nutzbar machen
private_key = UOV.private_key
public_key = UOV.public_key
# use a random vector
# Schlüssel ausgeben
print("Privater Schlüssel:")
print("S:\n{}x + {}".format(private_key.S.M, private_key.S.y))
print("Pr:\n{}".format(private_key.Pr))
print("S:\n{}x + {}".format(private_key.T.M, private_key.T.y))
print("\nÖffentlicher Schlüssel:")
print("P:\n{}".format(public_key.P))
# Die Nachricht soll (1, 4) sein
msg = vector(finite_field, [1, 4])
print("\n\nmsg =", msg)
# generate Signature
# Signatur erstellen
sig = UOV.sign(msg)
# verify signature is valid
print("msg =", msg)
print("sig =", sig)
print("UOV.verify(msg, sig):", UOV.verify(msg, sig))
# Signatur verifizieren
print("public_key.verify(msg, sig):", public_key.verify(msg, sig))
from __future__ import absolute_import, division, print_function
from sage.all import *
class AffineTransformation():
def __init__(self, M, y):
"""
Eine affine Transformation wird mit einer invertierbaren
Matrix und einem beliebigen Vektor initialisiert
"""
# Abbruchbedingung für nicht invertierbare Matrizen
if not M.is_invertible():
exit(1)
self.M = M # invertierbare Matrix
self.y = y # Vektor
def __call__(self, vector):
"""Anwenden der Transformation auf den gegebenen Vektor"""
# Sollte `vector` eine Liste sein -> Typecast
if not isinstance(vector, sage.structure.element.Vector):
vector = vector(vector)
return (self.M * vector) + self.y
def inverse(self, vector):
"""Anwenden der inversen Transformation auf den gegebenen Vektor"""
# Sollte `vector` eine Liste sein -> Typecast
if not isinstance(vector, sage.structure.element.Vector):
vector = vector(vector)
return self.M.inverse() * (vector - self.y)
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function
from sage.all import *
import copy as cp
from .helpers.sage_extensions import random_value, random_invertible_matrix
from .helpers.AffineTransformation import AffineTransformation
from .helpers.PrivateKey import PrivateKey
from .helpers.PrivateKey import PublicKey
from .helpers.EncryptionScheme import EncryptionScheme
class MatsumotoImaiAExample(EncryptionScheme):
"""Matsumoto Imai Scheme A implementation"""
def phi(self, polynomail_a):
return polynomail_a.list()
def phi_inv(self, vector_a): # -> b::Polynomial
return self.extension_field(vector_a)
def __init__(self, finite_field, n, keyfile=None):
self.finite_field = finite_field
self.n = n
# generate or load private & public key
if keyfile is not None:
self.private_key = PrivateKey(None, None, None, keyfile)
self.public_key = self.private_key.generate_public_key()
else:
# self.generate_keys()
self.generate_example_keys()
def generate_example_keys(self):
k = self.finite_field
(a,) = k.gens()
n = 3
ring = PolynomialRing(k, 'x')
(x,) = ring.gens()
gx = x**3 + x + 1
(self.theta, self.theta_invers) = (2, 26)
ML1 = matrix(k, [[a**2, a, a], [a, 1, 0], [1, 0, 1]])
yL1 = vector(k, [0, 1, a])
T = AffineTransformation(ML1, yL1)
ML2 = matrix(k, [[1, 0, a], [0, 1, a], [1, a, 0]])
yL2 = vector(k, [a, a**2, a**2])
S = AffineTransformation(ML2, yL2)
multivariate_ring = PolynomialRing(k, 'x1, x2, x3', n)
extension_field = PolynomialRing(
multivariate_ring, 't').quotient_ring(gx, 'T')
self.extension_field = extension_field
multi_vars = multivariate_ring.gens()
Sx = list(S(vector(multi_vars)))
pre_F = self.phi_inv(Sx) # <- phi_invers
# Now the MAGIC happens
# post_F = self.F(pre_F)
post_F = extension_field("1 + (a + 1)*x1 + (a)*x2 + x3 + x1*x2 + (a)*x1*x3 + (a + 1)*x2*x3 + ((a) + (a)*x1 + x2 + (a + 1)*x3 + x1^2 + (a + 1)*x1*x2 + x2^2 + x2*x3)*T + ((a + 1) + (a + 1)*x1 + (a)*x2 + (a)*x3 + x1^2 + x1*x2 + (a)*x1*x3 + (a + 1)*x2^2 + (a)*x2*x3 + (a + 1)*x3^2)*T^2")
SPTx = T(vector(post_F.list()))
Pr = T.inverse(vector(post_F.list()))
self.private_key = PrivateKey(S, Pr, T)
self.public_key = PublicKey(SPTx)
def invert_MQ(self, msg):
X = self.phi_inv(list(msg))
return vector(self.phi(X**self.theta_invers))
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function
from sage.all import *
import copy as cp
from .helpers.sage_extensions import random_value, random_invertible_matrix
from .helpers.AffineTransformation import AffineTransformation
from .helpers.PrivateKey import PrivateKey
from .helpers.SignatureScheme import SignatureScheme
class UnbalancedOilAndVinegarExample(SignatureScheme):
"""Unalanced Oil and Vinegar Implementation"""
def __init__(self, finite_field, n, m, keyfile=None):
"""
UOV wird mit dem Grundkörper `F`, Länge der Nachrichten `n`
und Länge der Signatur `m` initialisiert
Der Pfad zum privaten Schlüssel ist optional
"""
# speichere die initialen Werte
self.finite_field = finite_field
self.ring = PolynomialRing(finite_field, 'x', n)
self.n = n # Anzahl der Variablen
self.m = m # Anzahl der Gleichungen
# wird ein privater Schlüssel als Dateipfad übergeben, so wird dieser
# geladen ansonsten werden mit `generate_keys` die Schlüssel erstellt
if keyfile is not None:
self.private_key = PrivateKey(None, None, None, keyfile)
self.public_key = self.private_key.generate_public_key()
else:
self.generate_keys(finite_field, n, m)
def generate_keys(self, F, n, m):
"""
erstelle Privaten und öffentlichen Schlüssel aus gegebenem endlichen
Körper `F`, Anzahl der Variablen `n` und Anzahl der Gleichungen `m`
"""
# oil and vinegar variables:
v = n - m
oil = m
# Zwei affine Abbildungen (T ist Identität)
# - S ist (n x n) und T ist (m x m)
S = AffineTransformation(
random_invertible_matrix(F, n), random_vector(F, n))
T = AffineTransformation(matrix.identity(F, m), vector(F, m))
# Generiere geheimes Polynom `Pr`
# - P ist (n x m)
alpha = []
beta = []
gamma = []
Pr = []
# x[0] .. x[n-1] als Variablen benutzbar machen
x = vector(self.ring.gens())
# für jedes Polynom Pr[i]
for i in xrange(0, oil):
# Zufällige Matrix Representation jedes Polynoms
# - Alpha (Wert) ist der Konstante Anteil
# - Beta (Vektor) ist der lineare Anteil
# - Gamma (Matrix) ist der gemischte und quadratische Anteil
alpha.append(random_value(F))
beta.append(random_vector(F, n))
gamma.append(random_matrix(F, n - m, n))
'''Baue Polynom folgender Form'''
# poly = ((gamma[i] * x) * x) + (beta * x) + alpha[i]
# Konstanter Anteil
poly = alpha[i]
# Essigvariablen:
for j in xrange(0, v):
for k in xrange(0, n):
poly += gamma[i][j, k] * x[j] * x[k]
# Essig- & Ölvariablen
for k in xrange(0, n):
poly += beta[i][k] * x[k]
Pr.append(poly)
# erstelle den geheimen und öffentlichen Schlüssel
self.private_key = PrivateKey(S, Pr, T)
self.public_key = self.private_key.generate_public_key()
def invert_MQ(self, msg):
vinegar_len = self.n - self.m
x = list(self.ring.gens())
F = self.finite_field
# wichtig ist, dass private_key.Pr `UOV`-Gestalt hat
Pr = cp.copy(self.private_key.Pr)
sig = []
""" Linearisierung """
# x[1] bis x[n-m] werden zufällig aus F gewählt
# Diese bilden den ersten Teil der Lösung
if vinegar_len == 1:
x[0] = 3
sig.append(x[0])
else:
for i in xrange(0, vinegar_len):
x[i] = random_value(F)
sig.append(x[i])
print("Zufällig belegte Werte", x)
# Durch einsetzen der belegten Variablen wird P linearisiert
for i in xrange(0, len(Pr)):
Pr[i] = Pr[i](x)
# Die gelösten Variablen werden entfernt
x = x[vinegar_len:]
""" Gleichungssystem lösen """
# Um mit sagemath das lineare Gleichungssystem zu loesen
# wird diese Form angestrebt: A*x - b = 0
A = matrix(F, len(x)) # Koeffizenten Matrix
b = vector(F, len(x))
# A[i] ist die Liste der Koeffizienten der neuen Monome von Pr[i]
# b[i] ist der konstante Anteil von Pr[i]
for i in xrange(0, len(x)):
for j in xrange(0, len(x)):
A[i, j] = Pr[i].monomial_coefficient(x[j])
b[i] = Pr[i].constant_coefficient()
# Die Nachricht muss von den Konstanten abgezogen werden
b = msg - b
# sagemath bietet eine einfache Methode die Lösung des GS zu finden
# sollte keine Lösung gefunden werden können muss die
for x in A.solve_right(b):
sig.append(x)
# Die Lösung von "Pr(sig) = msg" wird zurückgegeben
return vector(F, sig)
No preview for this file type
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment