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

usable UOV

parent bfc72f45
Branches
No related tags found
No related merge requests found
.DS_Store
*.pyc
#!/usr/bin/sage
# -*- coding: utf-8 -*-
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
# Endlicher Körper mit 5 Elementen:
finite_field = GF(5, 'a')
m = 2 # Zwei Gleichungen
n = 3 # Drei Variablen
"""TEST UOV"""
# Initialize simple UOV
UOV = UnbalancedOilAndVinegar(finite_field, n, m, keyfile="./keys/bsp_uov2.priv")
private_key = UOV.private_key
public_key = UOV.public_key
# use a random vector
msg = vector(finite_field, [1, 4])
# generate Signature
sig = UOV.sign(msg)
# verify signature is valid
print("msg =", msg)
print("sig =", sig)
print("UOV.verify(msg, sig):", UOV.verify(msg, sig))
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function
from sage.all import *
from .helpers.AffineTransformation import AffineTransformation
from .helpers.PrivateKey import PrivateKey
from .helpers.PrivateKey import PublicKey
from .helpers.EncryptionScheme import EncryptionScheme
class MatsumotoImaiA(EncryptionScheme):
"""Matsumoto Imai Scheme A Implementation"""
def phi(self, polynomail_a):
return polynomail_a.list()
def phi_inv(self, vector_a):
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(n)
def generate_keys(self, n):
k = self.finite_field
(a,) = k.gens()
ring = PolynomialRing(k, 'x')
(x,) = ring.gens()
q = len(k)
# alle Kandidaten für theta werden gesucht
thetas = []
qn = q**n - 1
for theta in xrange(1, n - 1):
qd = q**theta + 1
(common_divider, t, _) = xgcd(qd, qn)
if common_divider == 1:
thetas.append((theta, t))
# ein zufälliges Theta wird ausgewählt
print(len(thetas))
(self.theta, self.theta_invers) = thetas[int(random() * len(thetas))]
S = AffineTransformation(
random_invertible_matrix(k, n), random_vector(k, n))
T = AffineTransformation(
random_invertible_matrix(k, n), random_vector(k, n))
# der Erweiterungskörper wird gebaut
gx = ring.irreducible_element(n)
multivariate_ring = PolynomialRing(k, 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_invers(Sx)
'''Now the MAGIC happens'''
post_F = pre_F * pre_F**(4**theta)
Pr = S.inverse(vector(post_F.list()))
SPTx = T(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))
X = X**self.theta_invers
return vector(self.phi(X))
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function
from sage.all import *
import copy as cp
......@@ -12,7 +15,7 @@ from .helpers.SignatureScheme import SignatureScheme
class UnbalancedOilAndVinegar(SignatureScheme):
"""Unalanced Oil and Vinegar Implementation"""
def __init__(self, finite_field, ring, n, m, keyfile=None):
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
......@@ -98,7 +101,7 @@ class UnbalancedOilAndVinegar(SignatureScheme):
F = self.finite_field
# wichtig ist, dass private_key.Pr `UOV`-Gestalt hat
Pr = cp.copy(self.private_key.P)
Pr = cp.copy(self.private_key.Pr)
sig = []
......@@ -109,8 +112,10 @@ class UnbalancedOilAndVinegar(SignatureScheme):
x[i] = random_value(F)
sig.append(x[i])
print("random_values =", sig )
# Durch einsetzen der belegten Variablen wird P linearisiert
for i in xrange(0, len(P)):
for i in xrange(0, len(Pr)):
Pr[i] = Pr[i](x)
# Die gelösten Variablen werden entfernt
......@@ -134,8 +139,9 @@ class UnbalancedOilAndVinegar(SignatureScheme):
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 "P(sig) = msg" wird zurückgegeben
# Die Lösung von "Pr(sig) = msg" wird zurückgegeben
return vector(F, sig)
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
from sage.all import *
......@@ -16,20 +19,20 @@ class AffineTransformation():
self.M = M # invertierbare Matrix
self.y = y # Vektor
def __call__(self, vector):
def __call__(self, v):
"""Anwenden der Transformation auf den gegebenen Vektor"""
# Sollte `vector` eine Liste sein -> Typecast
# Sollte `v` eine Liste sein -> Typecast
if not isinstance(vector, sage.structure.element.Vector):
vector = vector(vector)
v = vector(v)
return (self.M * vector) + self.y
return (self.M * v) + self.y
def inverse(self, vector):
def inverse(self, v):
"""Anwenden der inversen Transformation auf den gegebenen Vektor"""
# Sollte `vector` eine Liste sein -> Typecast
# Sollte `v` eine Liste sein -> Typecast
if not isinstance(vector, sage.structure.element.Vector):
vector = vector(vector)
v = vector(v)
return self.M.inverse() * (vector - self.y)
return self.M.inverse() * (v - self.y)
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from sage.all import *
from .SignatureScheme import SignatureScheme
......
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
class PolynomialSystem(object):
def __init__(self, P):
self.P = P
def __repr__(self):
return self.P
def __call__(self, variables):
ret = []
for p in self.P:
ret.append(p(variables))
return ret
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
from sage.all import vector
import cPickle as pickle
......@@ -9,7 +12,7 @@ class PrivateKey(object):
def __init__(self, S, Pr, T, path=None):
# wird ein Schlüssel als Dateipfad übergeben, so wird dieser geladen
if path is not None:
(self.S, self.P, self.T) = self.load(path)
(S, Pr, T) = self.load(path)
self.S = S # Affine Transformation
self.Pr = Pr # Polynomsystem
......@@ -17,7 +20,7 @@ class PrivateKey(object):
def generate_public_key(self):
# in `x` sind die Variablen x1,...,xn
x = vector(self.P[0].parent().gens())
x = vector(self.Pr[0].parent().gens())
# angewendet auf die Verschlüsselung ergibt
# dies das öffentliche Polynom
......@@ -29,15 +32,17 @@ class PrivateKey(object):
# Die Verschlüsselung wurde angepasst um nicht von
# dem PublicKey abzuhängen sondern von (S,Pr,T)
sx = list(self.S(vector(message)))
spx = self.Pr(list(sx))
return self.T(spx)
spx = []
for p in self.Pr:
spx.append(p(sx))
return self.T(vector(spx))
""" Es folgt eine sehr einfache Möglichkeit den Schlüssel zu
speichern und entsprechend auch wieder zu laden """
def save(self, path="./keys/uov.priv"):
def save(self, path="./keys/key.priv"):
with open(path, 'wb') as output:
pickle.dump((self.S, self.P, self.T),
pickle.dump((self.S, self.Pr, self.T),
output, pickle.HIGHEST_PROTOCOL)
def load(self, path):
......
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, print_function
from sage.all import vector
import cPickle as pickle
......@@ -20,16 +24,21 @@ class PublicKey(object):
def encrypt(self, msg):
# der Vektor `msg` muss als Liste an Sage übergeben werden
# Sage kann dann eigenständig das Polynomsystem ausrechen
return self.P(list(msg))
msg = list(msg)
solution = []
for p in self.P:
solution.append(p(msg))
return vector(solution)
def verify(self, msg, signature):
def verify(self, msg, sig):
# Vergleiche gegebene Singatur mit generierter Signatur
return signature == self.encrypt(msg)
return msg == self.encrypt(sig)
""" Es folgt eine sehr einfache Möglichkeit den Schlüssel zu
speichern und entsprechend auch wieder zu laden """
def save(self, path="./keys/uov.pub"):
def save(self, path="./keys/key.pub"):
with open(path, 'wb') as output:
pickle.dump(self.P, output, pickle.HIGHEST_PROTOCOL)
......
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from sage.all import *
......@@ -22,7 +25,7 @@ class SignatureScheme(object):
'''Platzhalter für alle Signatur- und Verschlüsselungsverfahren'''
raise NotImplementedError
def verify(self, signature, msg):
def verify(self, msg, sig):
# da SignatureScheme nicht direkt von PublicKey erbt wird
# die Verifikation extra zur Verfügung gestellt
return self.public_key.verify(signature, msg)
return self.public_key.verify(msg, sig)
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from sage.all import random_matrix, random_vector, random
......
File added
File added
test.py 0 → 100644
from __future__ import absolute_import, division, print_function
from sys import exit
from sage.all import *
from classes.helpers.AffineTransformation import *
k = GF(4, 'a') # hat modulus x^2 + x + 1
(a,) = k.gens()
n = 3
ring = PolynomialRing(k, 'x')
(x,) = ring.gens()
gx = x**3 + x + 1
K = ring.quotient_ring(gx, 'X')
q = len(k)
thetas = []
qn = q**n - 1
print("qn =", qn)
for theta in xrange(1, n):
qd = q**theta + 1
print("qd =", qd)
(common_divider, t, _) = xgcd(qd, qn)
if common_divider == 1:
thetas.append((theta, t))
thetas
#!/usr/bin/sage
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function
from sys import exit
from sage.all import *
from classes.UnbalancedOilAndVinegar import UnbalancedOilAndVinegar
# Variables that may be set by CLI
q = 5 # Number of elements in F
m = 4 # length of message
n = 6 # length of signature
# Computed Variables
if n <= m:
exit(1)
oil = n - m # number of oil variables
vinegar = m # number of vinegar variables
# Finite field with q elements
finite_field = GF(q, 'a')
# Multivariate Polynomial Ring over
# `finite_field` with `n` variables
ring = PolynomialRing(finite_field, 'x', n)
"""TEST UOV"""
# Initialize simple UOV
UOV = UnbalancedOilAndVinegar(finite_field, n, m)
# use a random vector
msg = random_vector(finite_field, m)
# generate Signature
sig = UOV.sign(msg)
# verify signature is valid
print("msg =", msg)
print("sig =", sig)
print("UOV.verify(msg, sig):", UOV.verify(msg, sig))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment