From 34136ed494f920cf38794af62cfd004b4eb99265 Mon Sep 17 00:00:00 2001
From: Maximilian Stauss <max.stauss@gmail.com>
Date: Tue, 5 Sep 2017 16:17:59 +0200
Subject: [PATCH] Beispiele angepasst

---
 bsp_MIA.py                                |  54 ++++++++
 bsp_UOV.py                                |  34 +++--
 classes/AffineTransformation.py           |  35 +++++
 classes/MatsumotoImaiAExample.py          |  79 +++++++++++
 classes/UnbalancedOilAndVinegarExample.py | 151 ++++++++++++++++++++++
 keys/bsp_uov.priv                         | Bin 2023 -> 2030 bytes
 keys/bsp_uov2.priv                        | Bin 2030 -> 0 bytes
 keys/bsp_uov_old.priv                     | Bin 0 -> 2023 bytes
 8 files changed, 342 insertions(+), 11 deletions(-)
 create mode 100644 bsp_MIA.py
 create mode 100644 classes/AffineTransformation.py
 create mode 100644 classes/MatsumotoImaiAExample.py
 create mode 100644 classes/UnbalancedOilAndVinegarExample.py
 delete mode 100644 keys/bsp_uov2.priv
 create mode 100644 keys/bsp_uov_old.priv

diff --git a/bsp_MIA.py b/bsp_MIA.py
new file mode 100644
index 0000000..ae6eed2
--- /dev/null
+++ b/bsp_MIA.py
@@ -0,0 +1,54 @@
+#!/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))
diff --git a/bsp_UOV.py b/bsp_UOV.py
index 4d9b5d2..cd28c51 100644
--- a/bsp_UOV.py
+++ b/bsp_UOV.py
@@ -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))
diff --git a/classes/AffineTransformation.py b/classes/AffineTransformation.py
new file mode 100644
index 0000000..ca63c10
--- /dev/null
+++ b/classes/AffineTransformation.py
@@ -0,0 +1,35 @@
+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)
diff --git a/classes/MatsumotoImaiAExample.py b/classes/MatsumotoImaiAExample.py
new file mode 100644
index 0000000..228e825
--- /dev/null
+++ b/classes/MatsumotoImaiAExample.py
@@ -0,0 +1,79 @@
+#!/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))
diff --git a/classes/UnbalancedOilAndVinegarExample.py b/classes/UnbalancedOilAndVinegarExample.py
new file mode 100644
index 0000000..a3d38a9
--- /dev/null
+++ b/classes/UnbalancedOilAndVinegarExample.py
@@ -0,0 +1,151 @@
+#!/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)
diff --git a/keys/bsp_uov.priv b/keys/bsp_uov.priv
index b58b64b7dff26ab5dfef0d56e179a060c63bb4f9..9888565e6ce5c97005eb2b57c3a08dfa7b77ac05 100644
GIT binary patch
delta 1039
zcmaFP|BinHCnKjfyEm&hV|yXbWNt=fC*Dv-)7GFuzEH-B)<S;2P?p^Ml)OTLP^RkI
z489EBP)5VnphCfpl0u={l0xC2LJ@D~PQQ{u(b|$iv7kcn*g}cP1&rFBk|3o9twDuS
zAO^@p=?szfphB4pxQuKDL`V)IWYQW`C=V4<NcCp+X6+~mDpZ{Ogi(o6X)-&LJ)`nu
zcP0ZymB|%M>cOfS86w`y-prk$tZ6x!c_oEvCAIB^>OqAXowbFUq0A|%C52iLgFz0~
zh8nC>?9JE_%E`jW$il+F%*4>{%~cXqs9Ty8Tc|hr0;|MiE@pd1{mB<u#V2zy8&00Y
zEF@u&Ari_|VNhro%2Z)kXcWp+VN__`UT6YVbeUPK-c+-((5$x5TqBe>zBn^4y)-AW
zD89I)sL&#mDW#y$GL$2}JT)^tqolad$}f~XJ~y$XD6^u_+AowfJ})shwa_M%GbJ^>
zD77pnwW82AlrKIvF*&g`C$Z89Y>ZtfyL(V-nNMm(p?#<b!iwDdqSU0Ee5>T_;z9>+
zhEVqSoYcJZl8iz}Z{|?0_}s+w+(fVePNAGiP~(*fokQ8<<5TjJ<KqimHZNk4U=(u=
zWsgtF$p;zZrdgWQ9#rUFTj(+Q0;^uVXKkUEH-k50u{U#DP@y*@JV6oV0}W5#49{Ay
zoL>frS?KT0;LQY49RLvt^k#(V4}$17ZVf67hUyQ=@T@Hi^=5)83CjSBglm9o^{!{~
zW-J98ACci(+7?t8nW3NIURxNY0n!!?QUkFo24XTOremQd$AOf@L(E}>8Iu4u9&BPF
z#Cb^w2PcCi3sVpdu1|%SYt$N4m<BaB9b|3>!o`^oU0D#D;115tNC!DMCsiYZF~2ak
zwlGg4l(8~{MI(b%BZDJ@6O??JKp7{$wxqBisIV}$ut)=8TQS(SoS?!Ih!`l$O2J}5
zg=MMUOpwe`9?IyOp`?+aoS~8d&JaxAOr06voKO)|SlL-ySd{_I1Rw*dp$61|GXV<|
PBQrB3{nwTzwd(-@%*8^w

delta 1031
zcmaFI|D1mVCnHk^=VT#9Whb6cM$^`yLf%luiq=9tzfhLk{FJ;x{!pgs+6>+do=`@^
z)}TUxj*>#b+LA({ph979=1#woLXp~%LeZc?vDiZK$>ogNo)RFX#;rkxk{|}iM5zqn
z_Mk%P46qEy5Sa{!kSs(9q*x9rB%kWd?9JLy5>%)#`8A^wqvB*fCVNJu$$m@*jLMVi
znbbp6G%|#}nZ21iLs`>uGV@9bRZD8y3)O-O)jMkoHA0zFQcDUo5e92P4c0F9X6y*%
zWMpAsVqjuqWNP>3DhVpoDNTwk)YX_A$m}t>f|-}8P;YV|bCiUBhHxlTg+ZY~C{u-D
zp<yUfg;AkVd!g~<KxXmDx0uE1O*9(|O=}CyG(vgfi!<}mOLG#7;)_d)3e7{AQVI$!
zLOJ5gQ!~>uN{S0D{X*H}a}!I7GAjzL{6bmd^AdAY3#~&rQ&Q85Qp<8uD++Bw`QmdE
zlM_pG5-W|s#@L3ky9cF~`J`49+J%ZBtjNtTN=?eiw@S_~F0}V%2xX7YNzF?y$tZO2
zW)9_w&rM9vO#~a@7|N*xHD0OEDU>}vJ|#anKEBX-^GX&8Msb%=_V}cne2_7&nx#qY
zL4|I$h3=qm5TE>>Rjl5lw$Rg?!JDzzo4GBh&<hfrCapn*-q7Im$?&KJ%lT%2n1z1c
z4Bku-)&3BX0B=T^{y>O+P&@}g^#^Bo)E0(#Gr^REW`IS)G(fg`*E4xDmV%8B&+sX2
z3o4Ar(93YEEsWFvX^R4>f!GxdF&UJoVxT6+f|SHT%wdEX6Av~XY+?e$d5H)ICxImk
zlfB^%u1|rOYt$N4m<lyF4P<UQ!o?X7U6~M@;115pNCP=IJ5?itF~2aUwlG&Cl(8~{
zMI(b%BZDJ@6O?+HK=~%GwxlpWsIVZmuuubHn?Y+(VG-E2oS?#Dgjfk!EU2(F)td>D
zH_Ad8eKQm_GL$luGr;+Q$(yM&1Dp}cg9<A;YYQtgpm_ikG*wUos=;}Hg^_`Q5t96C
IN|W040Qc5EhyVZp

diff --git a/keys/bsp_uov2.priv b/keys/bsp_uov2.priv
deleted file mode 100644
index 9888565e6ce5c97005eb2b57c3a08dfa7b77ac05..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2030
zcmZo*(nwCuNh~f-E!N9O%_&GND%NvMOUukl4Jk^@D^ANV%1tcE%+KS(Dp<&vU&vHj
z$gB~{Seaa$n4YSao1apelUl4-mYQ6WUlgC4pOP1!lA2eX%2k?IkeQsFlNw)U$W_Rq
z0a0FDQdF8;Qd*R%mzD_9P|1~^nwMIXnH&%0$HTO76|&;glarsHU0M*Io|B)Hn8Q`b
z7Ru#Tl$z=bc1j_8YfvGFH@i2hH)DGtr$z>=Mh06bw_9djW=X1BW@=7KAy;cqAva6~
z57d^T%)Insz0ACl)b!LMuH3}z)OZ-DkT;akv^A)ZFO;#OwUFO0lm+C?LV-}G>e>vx
z4Bk*i!`7fe!H$wbq1uu{;h;hhZ{|+Fl0wnil0vbdLh;x_2^34xz;200u@Mw<T)z1!
zT!oS#0}Wb(3Z*~{kiF6wBJDwiG8u3g*$jw~97M>ZHK<S?Dx{F=&FszEQ4&<B7|Q4i
z3H02=lA_ECJqTq0j~K2(C8)C?GEfB|mq6n%J}oCdv4qPPtRGXnP#I!AB2r89G7C#n
z<BL)Yic*VH^GYB|sWh)BHKjB;m8(z%q5;*u;)2BFRH!AvV0NLZMuvztvo~{RC~I0y
zW?o65T1jntp?XlEMrUoIW+-z?YDu9M#Pgt_*M@ptr`VgZBb1Yck&%UkftiV+-J7c<
zs8F{wDYj4#>QzXf7v$$u=H=&RCg$knmgbaX#v=scb25{PGxO3*a}tZ-K^5;C0M~({
zpim#;Bg%~p%FIhgHQFFUB$TPbpwKXsslu?(D3qzfsL;5*&;*B#C8<TZ@%cq5sYP5N
zsYSW|U{;~2W@DjQZK1hFC~rK>Tk*vuMTHijOeqD0mZ2Q+<*AwJ870MqR(_%E@sOw~
zwDt>Sjn7NWO)azu<xELUFG?-TNv$Zf4dsi^O-xQK%}J~@0vlr&%I+SNTIQ2lQD`43
zg0LbtzbG{+CqFs6xX{6yA(TBnCp9m<B%{#Ln>my#J~uHvHxaDgDU?$QYPwRPb0~X!
zd`f<De0-rxh!7(K1D6ZP>QsfI)Uwo~;#7s4)QZgH{Pd#4f{e^$1r4~vG!;O;R{;B7
zkBiGEwL~EyCM7jpqarR*Q^8gtG2T!?TOl#tNI_d6CMCb57|hE{&`~JKNX_F)sEA8c
zuu-UpOG;44OjAhAOHs(r%c%shk&LlXfEt;knV^tgglYqlRAOEVS4l={QK~{}MP_kH
zu|k5OLQGDoLME8ZOHe2-P0mm#$w(|wNJxy&Q?OM?iqF%5xJySNF}^xe+prca3TA<X
zG8OC;lHxNH^tcLLL)qh@0qdq&n$#Xt=w4gsfh%=`(sfE^atWkBa}6mi$VufY^sFuP
z@@DX6EcRw@3o7)6WF$~2;seb{z8RjiU^%}G5VO$Vo57n2qB;N~66nnc(;o!UZ`>MG
z7!1`PlHplf80yUgQxcW|775n?*$NUa1)Cm`;al1kR2Z3|pW$9x7^MNy6%A4Xu_^{)
zFerz|LJf`sDT#*|!|2TjF(v_QI@rWSi0hIN?o9?u7N#KFn+h@3s5PiC4QgyU$k+^!
z!yq<iLNsMTEMkILl%0_da&JzmMh0VkVQy_<9;hPBU;$S$92uOTQi};x^5@r<6cz*(
z7RDA9X&`JXhT2vF5dsBRDO9K|)td=YY?p^J`erC;WGH8-WPpo7CU2(B3~>2Z5mZ>&
hSzB0@0WJDK22?{0r~wy!EKH2d%#c#Awlt|-4*<zFuDbvL

diff --git a/keys/bsp_uov_old.priv b/keys/bsp_uov_old.priv
new file mode 100644
index 0000000000000000000000000000000000000000..b58b64b7dff26ab5dfef0d56e179a060c63bb4f9
GIT binary patch
literal 2023
zcmZo*(nwCuNh~f-E!N9O%_&GND%NvMOUukl4Jk^@D^ANV%1tcE%+KS(Dp<&vU&vHj
z$gB~{Seaa$n4YSao1apelUl4-mYQ6WUlgC4pOP1!lA2eX%2k?IkeQsFlNw)U$W_Rq
z0a0FDQdF8;Qd*R%mzD_9P|1~^nwMIXnH&%0$HTO76|&;glarsHU0M*Io|B)Hn8Q`b
z7Ru#Tl$z=bc1j_8YfvGFH@i2hH)DGtr$z>=Mh06bw_9djW=X1BW@=7KAy;cqA$JBR
z)cB&zy!2wd%)FA+^wc7*+{EnEco?UUCzR2&HK>p`l(C|<kk2oa1?0a%{!pgs+6>+d
zo=`@^)}TUxj*>#b+LA({ph979=1#woLXp~%LeZc?vDiX!6id>;j)+IG5fo%xzWFI!
zg%ThGja!2XB|!|3y;2#%?Lmdo8DJTZRWcb6Az6qJNU<DLNIun@*_*YaB&bj!l+hOw
z+PR4(MVS?P5Xt}^BV2`wP-j78pb9`Pfks|@T26jq370QeKc;x062yE&Y?kI_7M7;Q
z7o`>yr52~=l|a%^X<kukN@;Q`SD`XQ1FC(+1&PV2P)mZr>_Qcd3}J6(Z|2TW*0h|=
zyplrIlG^q{wV*=v&e}qaQ0A1>l0r>{=e3}o*Dm&E><Hy#WMN@qU}9usYWL<U2`bbn
zO^Pklg?bed=mq&Xm3jHOnTa`ixurQJnehmL_?*n7;>^7C(wxL1cu>Xr2EcWoC@9o}
z_=s|2gEI5dQH|Em5DsOkFeo$#WvVbNGz?{`Fe)@^FEqwsV@YaJZhU@GN@@{TNNQ28
zKbTc$qS;tzT3cwQ5y~46^HzLuNl~GBC{s#7p+zW1e0geSdPYfcp`~9adpsm+3a$J?
zS>y8(b5jegLpf7Y(~DBea#AY_Z9@6ta}$#jOLGz{jljm(hO)Z{rIz`mRutNWiXg1W
z%`Zw#%E?d8E-tk9W(Z}E&q>WoFUcr$@MaF>iqB0<&rJmDcMRoJf|{;W=oHExAD@z+
z93Nlk93sTXz`*4KvN~0vD77rLs5n(2C$%CoIX}H9u^=NeSwREtFii!J?-jtl*W=>y
zNi9)Gh)GFJ*Qkg~)KsulNQ^gB&{jx{H&W16h)KyWDF*ZM5_A+wGE(!n5-Q>n6>JnL
z;*t^+GSd_i^HLP@^KvRdY$RiB6re^XX(lM-7opmKB$b$#!c~%yT9m4gT9H{?Qml|*
zs1TErs*njL^AZ$_OOrDcN-`2l6cQ5S^Av0qlH&7pAnwvpNQ|$})HbXIi-K7op-crk
zg{1h*1U;@omr(Y2Xu!H^mL|0a6}r_Hy5maSpmd#*nOp)X&|E`G3vyDq3O#BIJ-r#c
z8H>G{+ky(cAQ{P|HK@=Vnvr}mJZiymz8N59p`SN{Hxop)KSU(Jn-Qiz5TYMc3I##+
z2WNQH7KV5;!IXq%fJMSIK(>N}OTngxXZV!11r<hQ=w-Oo7Dj4-bVY%bK&*;}7z`@$
zVxR`cf|SHTjA8U<gcuVKHXUqY0>pKR2=^v|B@2_i;qFa=7;DrTRG11iHVtHKI>=!V
zn=>GqG9eZ*!7R$kNCUYyJ5?itF~2aUwlEh|17@&*YZs0TPEe`E1S<LSYD)_9g9-~`
z3kx+Mwi&br6&68lD@F*FK!r+Ey_q1zc3CK+Z-$~qhEj%d2Dlhx@@DGH0GEH|L4_5a
hwS|=#(4r3%FjY_ks=-Ac3nK#qBc#-;DNSnE0|4RgtZ)DT

literal 0
HcmV?d00001

-- 
GitLab