From f1d912fb5d0e183b79ce06fbcfb75dd6d2c570a4 Mon Sep 17 00:00:00 2001 From: Naumkin Vladimir Date: Thu, 18 Apr 2024 23:06:02 +0300 Subject: [PATCH] Add portable v3 --- app_local/portable_v3_core.py | 178 ++++++++++++++++++++++++++++++++++ app_local/portable_v3_gui.py | 110 +++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 app_local/portable_v3_core.py create mode 100644 app_local/portable_v3_gui.py diff --git a/app_local/portable_v3_core.py b/app_local/portable_v3_core.py new file mode 100644 index 0000000..6404af2 --- /dev/null +++ b/app_local/portable_v3_core.py @@ -0,0 +1,178 @@ +#G = pubkey; S and P = privkeys; text = plaintext; msg = encrypted text +#all these variables are strings +#Usage: +#G, S, P = generate() +#msg = encrypt(G, text) +#text = decrypt(S, P, msg) +#G = restore_G(S, P) +#S = break_S(G, P) +#P = break_P(G, S) + +import numpy as np +import galois +import random +import base64 + +order = 256 +n = 255 +k = 210 +GF = galois.GF(2, 8, irreducible_poly = "x^8 + x^4 + x^3 + x^2 + 1", primitive_element = "x", verify = False) +rs = galois.ReedSolomon(n, k, field = GF) + +def generate(): + S = generate_S() + G = rs.G + P, p = generate_P() + G_ = S @ G @ P + return write_pubkey(G_), write_privkey_s(S), write_privkey_p(p) + +def generate_S(): + S = GF.Random((k, k)) + while np.linalg.det(S) == 0: + S = GF.Random((k, k)) + return S + +def generate_P(): + r = [i for i in range(n)] + p = [] + for i in range(n): + p.append(r.pop(random.randint(0, n - 1 - i))) + P = GF.Zeros((n, n)) + for i in range(n): + P[i, p[i]] = 1 + return P, p + +def write_pubkey(G_): + rows = [bytes(row) for row in G_] + output = "".join([base64.b64encode(row).decode() for row in rows]) + return output + +def write_privkey_s(S): + rows = [bytes(row) for row in S] + output = "".join([base64.b64encode(row).decode() for row in rows]) + return output + +def write_privkey_p(p): + output = base64.b64encode(bytes(p)).decode() + return output + +def read_pubkey(out): + out = [int(i) for i in base64.b64decode(out)] + out = [out[i - n : i] for i in range(n, n * k + n, n)] + return out + +def read_privkey_s(out): + out = [int(i) for i in base64.b64decode(out)] + out = [out[i - k : i] for i in range(k, k * k + k, k)] + return out + +def read_privkey_p(out): + return [int(i) for i in base64.b64decode(out)] + +def build_P(p): + P = GF.Zeros((n, n)) + for i in range(n): + P[i, p[i]] = 1 + return P + +def build_P_inv(p): + P = GF.Zeros((n, n)) + for i in range(n): + P[p[i], i] = 1 + return P + +def pad_message(msg: bytes, pad_size: int) -> list[int]: + padding = pad_size - (len(msg) % pad_size) + return list(msg + padding.to_bytes() * padding) + +def unpad_message(msg): + padding_byte = msg[-1] + for i in range(1, padding_byte + 1): + if msg[-i] != padding_byte: + #print("Wrong privkey!") + raise Exception() + return msg[: -padding_byte] + +def encrypt(key, text): + G_ = GF(read_pubkey(key)) + text = text.encode() + out = "" + while len(text) > k - 1: + tmp = text[: k - 1] + text = text[k - 1 :] + out += encrypt_one(G_, tmp) + out += encrypt_one(G_, text) + return out + +def encrypt_one(G_, text): + msg = pad_message(text, k) + m = GF(msg) + c = m.T @ G_ + t = (n - k) // 2 + z = np.zeros(n, dtype = int) + p = [i for i in range(n)] + for i in range(t): + ind = p.pop(random.randint(0, n - 1 - i)) + z[ind] += random.randint(1, order - 1) + z[ind] %= order + c = c + GF(z) + return base64.b64encode(bytes(c)).decode() + +def decrypt(s, p, msg): + S_inv = np.linalg.inv(GF(read_privkey_s(s))) + P_inv = GF(build_P_inv(read_privkey_p(p))) + msg = [int(i) for i in base64.b64decode(msg)] + msg = [msg[i - n : i] for i in range(n, len(msg) + n, n)] + msg = [decrypt_one(S_inv, P_inv, GF(i)) for i in msg] + msg = [i for j in msg for i in j] + msg = bytes(msg).decode() + return msg + +def decrypt_one(S_inv, P_inv, msg): + msg = msg @ P_inv + msg, e = rs.decode(msg, errors = True) + if e == -1: + #print("Too many erroneous values in message!") + raise Exception() + msg = msg @ S_inv + msg = [int(i) for i in msg] + msg = unpad_message(msg) + return msg + +def restore_G(s, p): + S = GF(read_privkey_s(s)) + G = rs.G + P = GF(build_P(read_privkey_p(p))) + G_ = S @ G @ P + return write_pubkey(G_) + +def break_S(key, p): + G_ = GF(read_pubkey(key)) + P_inv = GF(build_P_inv(read_privkey_p(p))) + S = G_ @ P_inv + S = S[:, : k] + return write_privkey_s(S) + +def break_P(key, s): + G_ = GF(read_pubkey(key)) + S_inv = np.linalg.inv(GF(read_privkey_s(s))) + G = rs.G + G = G.T + G = [[int(i) for i in j] for j in G] + GP = S_inv @ G_ + GP = GP.T + GP = [[int(i) for i in j] for j in GP] + p = [0 for i in range(n)] + f = False + for i in range(n): + f = False + for j in range(n): + if G[i] == GP[j]: + p[i] = j + f = True + break + if f: + continue + #print("Wrong pubkey and privkey_s combination!") + raise Exception() + return write_privkey_p(p) diff --git a/app_local/portable_v3_gui.py b/app_local/portable_v3_gui.py new file mode 100644 index 0000000..878141c --- /dev/null +++ b/app_local/portable_v3_gui.py @@ -0,0 +1,110 @@ +#G = pubkey; S and P = privkeys; text = plaintext; msg = encrypted text +#all these variables are strings +#Usage: +#G, S, P = generate() +#msg = encrypt(G, text) +#text = decrypt(S, P, msg) +#G = restore_G(S, P) +#S = break_S(G, P) +#P = break_P(G, S) + +import portable_v3_core as core +import tkinter as tk + +def button1_click(): + new_text1, new_text2, new_text3 = core.generate() + entry1.delete(0, tk.END) + entry1.insert(0, new_text1) + entry2.delete(0, tk.END) + entry2.insert(0, new_text2) + entry3.delete(0, tk.END) + entry3.insert(0, new_text3) + +def button2_click(): + G = entry1.get() + text = entry4.get("1.0", "end-1c") + + # Выполнить какие-либо действия с текстом + new_text4 = core.encrypt(G, text) + + # Записать текст обратно в поля ввода + entry4.delete("1.0", tk.END) + entry4.insert("1.0", new_text4) + +def button3_click(): + S = entry2.get() + P = entry3.get() + msg = entry4.get("1.0", "end-1c") + + # Выполнить какие-либо действия с текстом + new_text4 = core.decrypt(S, P, msg) + + # Записать текст обратно в поля ввода + entry4.delete("1.0", tk.END) + entry4.insert("1.0", new_text4) + +def button4_click(): + S = entry2.get() + P = entry3.get() + + # Выполнить какие-либо действия с текстом + new_text1 = core.restore_G(S, P) + + # Записать текст обратно в поля ввода + entry1.delete(0, tk.END) + entry1.insert(0, new_text1) + +def button5_click(): + G = entry1.get() + P = entry3.get() + + # Выполнить какие-либо действия с текстом + new_text2 = core.break_S(G, P) + + # Записать текст обратно в поля ввода + entry2.delete(0, tk.END) + entry2.insert(0, new_text2) + +def button6_click(): + G = entry1.get() + S = entry2.get() + + # Выполнить какие-либо действия с текстом + new_text3 = core.break_P(G, S) + + # Записать текст обратно в поля ввода + entry3.delete(0, tk.END) + entry3.insert(0, new_text3) + +# Создать главное окно +window = tk.Tk() +window.title("McEliece by vovuas2003") + +# Создать поля для ввода текста +entry1 = tk.Entry(window, width=50) +entry2 = tk.Entry(window, width=50) +entry3 = tk.Entry(window, width=50) +entry4 = tk.Text(window, height=10, width=50) + +# Создать кнопки +button1 = tk.Button(window, text="generate", command=button1_click) +button2 = tk.Button(window, text="encrypt", command=button2_click) +button3 = tk.Button(window, text="decrypt", command=button3_click) +button4 = tk.Button(window, text="pubkey", command=button4_click) +button5 = tk.Button(window, text="privkey_s", command=button5_click) +button6 = tk.Button(window, text="privkey_p", command=button6_click) + +# Разместить элементы в окне +entry1.pack() +entry2.pack() +entry3.pack() +entry4.pack(fill=tk.BOTH, expand=True) +button1.pack() +button2.pack() +button3.pack() +button4.pack() +button5.pack() +button6.pack() + +# Запустить главное окно +window.mainloop()