Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
sage-code
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Multivariate Quadric-polynomial Public Key Cryptography
sage-code
Commits
19c99c04
Commit
19c99c04
authored
7 years ago
by
Maximilian Stauss
Browse files
Options
Downloads
Patches
Plain Diff
add UOV
parent
70ad68ff
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
classes/UnbalancedOilAndVinegar.py
+141
-0
141 additions, 0 deletions
classes/UnbalancedOilAndVinegar.py
with
141 additions
and
0 deletions
classes/UnbalancedOilAndVinegar.py
0 → 100644
+
141
−
0
View file @
19c99c04
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
UnbalancedOilAndVinegar
(
SignatureScheme
):
"""
Unalanced Oil and Vinegar Implementation
"""
def
__init__
(
self
,
finite_field
,
ring
,
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
.
P
)
sig
=
[]
"""
Linearisierung
"""
# x[1] bis x[n-m] werden zufällig aus F gewählt
# Diese bilden den ersten Teil der Lösung
for
i
in
xrange
(
0
,
vinegar_len
):
x
[
i
]
=
random_value
(
F
)
sig
.
append
(
x
[
i
])
# Durch einsetzen der belegten Variablen wird P linearisiert
for
i
in
xrange
(
0
,
len
(
P
)):
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
for
x
in
A
.
solve_right
(
b
):
sig
.
append
(
x
)
# Die Lösung von "P(sig) = msg" wird zurückgegeben
return
vector
(
F
,
sig
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment