feat: Добавил Dockerfile, изменил структуру

nihonium
Nihonium 2 months ago
parent 3bdab827ff
commit c054da67f1
Signed by: nihonium
GPG Key ID: 0251623741027CFC

@ -0,0 +1,8 @@
FROM python:3.12-slim
WORKDIR /opt/McEliece
COPY . .
RUN pip install --no-cache-dir -r requirements.txt
CMD [ "python", "McEliece_console.py" ]

Binary file not shown.

@ -1,130 +0,0 @@
#pyinstaller -F -w -i "icon.ico" McEliece_GUI.py
import cryptosystem_core as core
import tkinter as tk
def mymessagebox(fontsize, butsize, mytitle, mytext):
toplevel = tk.Toplevel(window)
toplevel.title(mytitle)
toplevel.geometry(f"600x400+{window.winfo_x()+40}+{window.winfo_y()+15}")
toplevel.resizable(False, False)
l = tk.Label(toplevel, text = mytext, font = ("TkDefaultFont", fontsize))
l.pack()
b = tk.Button(toplevel, text = "Close", command = toplevel.destroy, width = 10, font = ("TkDefaultFont", butsize))
b.pack()
def show_error():
mymessagebox(30, 30, "Error!", "ERROR!\n\nPress help button\nto show common\nmistakes in usage.\n")
def button0_click():
mymessagebox(15, 15, "Source code: github.com/vovuas2003/McEliece", "Program can work slow and doesn't response, it is normal.\n1st line = current configuration of cryptosystem.\n2nd line = public key (send to anybody).\n3rd line = first half (s) of private key (keep in secret!).\n4th line = second half (p) of private key (keep in secret!).\nBig field = place for writing text or pasting message.\nGenerate keys = rewrite all 3 keys.\nEncrypt = pubkey is required.\nDecrypt = both privkeys are required.\nYou can restore any key from the other two.\nConfig = change cryptosystem parameters n and k.\n(two numbers separated by a space, default: 255 210)\n(255 mod n = 0; 255 = 3 * 5 * 17)\n(2 <= k <= n; (n - k) div 2 bytes are randomly changed)\nPT! = just easter egg :)")
def button1_click():
try:
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)
except:
show_error()
def button2_click():
try:
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)
except:
show_error()
def button3_click():
try:
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)
except:
show_error()
def button4_click():
try:
S = entry2.get()
P = entry3.get()
new_text1 = core.restore_G(S, P)
entry1.delete(0, tk.END)
entry1.insert(0, new_text1)
except:
show_error()
def button5_click():
try:
G = entry1.get()
P = entry3.get()
new_text2 = core.break_S(G, P)
entry2.delete(0, tk.END)
entry2.insert(0, new_text2)
except:
show_error()
def button6_click():
try:
G = entry1.get()
S = entry2.get()
new_text3 = core.break_P(G, S)
entry3.delete(0, tk.END)
entry3.insert(0, new_text3)
except:
show_error()
def button7_click():
try:
core.config(entry0.get())
except:
entry0.delete(0, tk.END)
entry0.insert(0, str(core.n) + " " + str(core.k))
show_error()
def button8_click():
mymessagebox(200, 15, "PT!" * 25, "PT!")
window = tk.Tk()
window.title("McEliece by vovuas2003")
frame_buttons = tk.Frame(window)
frame_buttons.pack(side = tk.TOP, fill = tk.X)
buttons = []
but_names = ["help", "generate keys", "encrypt text", "decrypt message", "pubkey = s + p", "s = pubkey + p", "p = pubkey + s", "change config", "PT!"]
but_com = [button0_click, button1_click, button2_click, button3_click, button4_click, button5_click, button6_click, button7_click, button8_click]
for i in range(9):
buttons.append(tk.Button(frame_buttons, text = but_names[i], command = but_com[i]))
for button in buttons:
button.pack(side = tk.LEFT)
entry0 = tk.Entry(window, width = 50)
entry1 = tk.Entry(window, width = 50)
entry2 = tk.Entry(window, width = 50)
entry3 = tk.Entry(window, width = 50)
entry4 = tk.Text(window, height = 20, width = 50)
entry0.insert(0, "255 210 (default config)")
entry1.insert(0, "pubkey")
entry2.insert(0, "privkey s")
entry3.insert(0, "privkey p")
entry4.insert("1.0", "Write a text or paste a message here!\nAll utf-8 symbols are supported, e.g. alt codes and Russian text.\n\n(use ctrl+a before crtl+v or ctrl+c)\n(switch keyboard layout to english to use these shortcuts)\n\nYou can't resize window, but can scroll down.\nProgram can work slow, don't kill it please :)")
entry0.pack()
entry1.pack()
entry2.pack()
entry3.pack()
entry4.pack(fill = tk.BOTH, expand = True)
window.resizable(False, False)
window.mainloop()

@ -1,445 +0,0 @@
#pyinstaller -F -i "icon.ico" McEliece_console.py
import hashlib
import getpass
import random
import base64
def main():
safe_start()
def safe_start():
try:
start_menu()
except:
print("\nUnknown error (maybe ctrl+c), emergency exit!")
def start_menu():
f = True
print("\nA soldering iron is into a black hole.")
#thermorectal cryptanalysis
if myhash(getpass.getpass("Login: ")) != 1314399736851798576:
f = False
if myhash(getpass.getpass("Password: ")) != 192441972608755898:
f = False
if f:
print("Authorization successful, wait a bit.")
menu()
else:
print("Permission denied.")
print("\nPress ENTER to exit.", end = '')
input()
def menu():
import cryptosystem_core as core
print("\nMcEliece cryptosystem implementation by vovuas2003.\n")
print("All necessary txt files must be in utf-8 and located in the directory with this exe program.\n")
info = "Menu numbers: 0 = exit; 1 = generate keys, 2 = encrypt, 3 = decrypt,\n4 = restore pubkey, 5 = break privkey_s, 6 = break privkey_p;\n-0 = init all txt files, -1 = init keys, -2 = init text, -3 = init message,\n-4 = init pubkey, -5 = init privkey_s, -6 = init privkey_p;\nc = config, b = binary menu, u = unsafe keygen by password, h = help.\n"
err = "Error! Check command info and try again!\n"
ok = "Operation successful.\n"
inp = [str(i) for i in range(7)] + ['-' + str(i) for i in range(7)] + ['c', 'b', 'h', 'u'] + ['1337', '-1337']
print(info)
while True:
s = input("Menu number: ")
while s not in inp:
s = input("Wrong menu number, h = help: ")
if s == 'h':
print(info)
elif s == 'b':
print("Go to binary files encryption menu? Don't forget to generate keys and change config before that (if you want)!")
if(not get_yes_no()):
continue
try:
if(bin_menu(core)):
break
except:
raise Exception()
elif s == 'c':
print("Default config is 255 210, current is " + str(core.n) + " " + str(core.k) + ". Change config?")
if(not get_yes_no()):
continue
try:
print("Config is two numbers n >= k >= 2; (3 * 5 * 17) mod n = 0. Larger values = larger keys.\nRandomly change (n - k) div 2 bytes during encryption, but add (n - k + 1) bytes to each chunk with len (k - 1).")
core.config(input("Write n and k separated by a space: "))
print(ok)
except:
print(err)
elif s == '0':
print("\nGood luck!")
break
elif s == 'u':
print("WARNING: setting sha256hash(password) mod 2^32 as random seed is VERY unsafe practice!\nIt is better to use menu number 1 for independent random.")
print("This operation will rewrite pubkey.txt, privkey_s.txt and privkey_p.txt; are you sure?")
if(not get_yes_no()):
continue
try:
seed = normalhash(getpass.getpass("Any password for hashing: "))
G, S, P = core.unsafe_generate(seed)
write_txt("pubkey", G)
write_txt("privkey_s", S)
write_txt("privkey_p", P)
print(ok)
except:
print(err)
elif s == '1':
print("This operation will rewrite pubkey.txt, privkey_s.txt and privkey_p.txt; are you sure?")
if(not get_yes_no()):
continue
try:
G, S, P = core.generate()
write_txt("pubkey", G)
write_txt("privkey_s", S)
write_txt("privkey_p", P)
print(ok)
except:
print(err)
elif s == '2':
print("Write your text into text.txt; pubkey.txt is required, message.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
G = read_txt("pubkey")
text = read_txt("text")
msg = core.encrypt(G, text)
write_txt("message", msg)
print(ok)
except:
print(err)
elif s == '3':
print("You need message.txt, privkey_s.txt and privkey_p.txt; text.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
S = read_txt("privkey_s")
P = read_txt("privkey_p")
msg = read_txt("message")
text = core.decrypt(S, P, msg)
write_txt("text", text)
print(ok)
except:
print(err)
elif s == '4':
print("You need privkey_s.txt and privkey_p.txt; pubkey.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
S = read_txt("privkey_s")
P = read_txt("privkey_p")
G = core.restore_G(S, P)
write_txt("pubkey", G)
print(ok)
except:
print(err)
elif s == '5':
print("You need pubkey.txt and privkey_p.txt; privkey_s.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
G = read_txt("pubkey")
P = read_txt("privkey_p")
S = core.break_S(G, P)
write_txt("privkey_s", S)
print(ok)
except:
print(err)
elif s == '6':
print("You need pubkey.txt and privkey_s.txt; privkey_p.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
G = read_txt("pubkey")
S = read_txt("privkey_s")
P = core.break_P(G, S)
write_txt("privkey_p", P)
print(ok)
except:
print(err)
elif s == '-0':
print("Create (or make empty) all 5 necessary txt files in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("pubkey", "")
write_txt("privkey_s", "")
write_txt("privkey_p", "")
write_txt("text", "")
write_txt("message", "")
print(ok)
except:
print(err)
elif s == '-1':
print("Create (or make empty) all 3 keys txt files in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("pubkey", "")
write_txt("privkey_s", "")
write_txt("privkey_p", "")
print(ok)
except:
print(err)
elif s == '-2':
print("Create (or make empty) text.txt in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("text", "")
print(ok)
except:
print(err)
elif s == '-3':
print("Create (or make empty) message.txt in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("message", "")
print(ok)
except:
print(err)
elif s == '-4':
print("Create (or make empty) pubkey.txt in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("pubkey", "")
print(ok)
except:
print(err)
elif s == '-5':
print("Create (or make empty) privkey_s.txt in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("privkey_s", "")
print(ok)
except:
print(err)
elif s == '-6':
print("Create (or make empty) privkey_p.txt in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("privkey_p", "")
print(ok)
except:
print(err)
elif s == '1337':
c = input("Move the soldering iron into the black hole number: ")
try:
PT(int(c))
except:
print("Iron: 'I don't know this hole.'")
continue
elif s == '-1337':
print("Do you want to format your system disk?")
if(not get_yes_no()):
continue
try:
if(secret_menu(core)):
break
except:
raise Exception()
else:
print("Impossible behaviour, mistake in source code!\nThe string allowed in the inp array is not bound to the call of any function!")
break
def bin_menu(core):
print("\nFirst line in binary.txt is a name of the original file (with extension), you can edit it.")
print("Default config is 255 210, current is " + str(core.n) + " " + str(core.k) + ".")
info = "Binary menu numbers: 0 = go back to common menu; 1 = encrypt, 2 = decrypt;\n-0 = init binary.txt; -1 = to base64, -2 = from base64; h = help.\n"
err = "Error! Check command info and try again!\n"
ok = "Operation successful.\n"
inp = [str(i) for i in range(3)] + ['-' + str(i) for i in range(3)] + ['h']
print(info)
while True:
s = input("Binary menu number: ")
while s not in inp:
s = input("Wrong menu number, h = help: ")
if s == 'h':
print(info)
elif s == '0':
print("Going back to common menu.\n")
break
elif s == '1':
print("You need pubkey.txt and any file that you want to encrypt; binary.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
G = read_txt("pubkey")
name = input("Write name of file with extension: ")
with open(name, "rb") as f:
b = f.read()
out = core.bin_encrypt(G, b)
write_txt("binary", name + '\n' + out)
print(ok)
except:
print(err)
elif s == '2':
print("You need privkey_s.txt, privkey_p.txt and binary.txt; name of new file is the first string in binary.txt.")
if(not get_yes_no()):
continue
try:
S = read_txt("privkey_s")
P = read_txt("privkey_p")
name, msg = read_txt("binary").split('\n')
text = core.bin_decrypt(S, P, msg)
with open(name, "wb") as f:
f.write(text)
print(ok)
except:
print(err)
elif s == '-0':
print("Create (or make empty) binary.txt in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("binary", "")
print(ok)
except:
print(err)
elif s == '-1':
print("Convert any file to base64 string without any encryption; binary.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
name = input("Write name of file with extension: ")
with open(name, "rb") as f:
b = f.read()
out = base64.b64encode(b).decode()
write_txt("binary", name + '\n' + out)
print(ok)
except:
print(err)
elif s == '-2':
print("Convert binary.txt from base64; name of new file is the first string in binary.txt.")
if(not get_yes_no()):
continue
try:
name, msg = read_txt("binary").split('\n')
text = base64.b64decode(msg)
with open(name, "wb") as f:
f.write(text)
print(ok)
except:
print(err)
else:
print("Impossible behaviour, mistake in source code!\nThe string allowed in the inp array is not bound to the call of any function!")
return 1
return 0
def secret_menu(core):
#1qaz@WSX
if myhash(getpass.getpass("canp: ")) == 1355332552418299328:
print("Authorization successful.")
else:
print("Permission denied.")
return 0
print("\nHidden input from keyboard, writing to secret_message.txt.")
print("Default config is 255 210, current is " + str(core.n) + " " + str(core.k) + ".")
info = "Secret menu numbers: 0 = go back; 1 = encrypt, 2 = decrypt; -0 = init txt; h = help.\n"
err = "Error! Check command info and try again!\n"
ok = "Operation successful.\n"
inp = [str(i) for i in range(3)] + ['-0'] + ['h']
print(info)
while True:
s = input("Secret menu number: ")
while s not in inp:
s = input("Wrong menu number, h = help: ")
if s == 'h':
print(info)
elif s == '0':
print("Going back to common menu.\n")
break
elif s == '1':
print("You need pubkey.txt; secret_message.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
G = read_txt("pubkey")
text = getpass.getpass("Secret text: ")
msg = core.encrypt(G, text)
write_txt("secret_message", msg)
print(ok)
except:
print(err)
elif s == '2':
print("You need privkey_s.txt, privkey_p.txt and secret_message.txt.")
if(not get_yes_no()):
continue
try:
S = read_txt("privkey_s")
P = read_txt("privkey_p")
msg = read_txt("secret_message")
text = core.decrypt(S, P, msg)
print('\nSecret text: ' + text + '\n')
print(ok)
except:
print(err)
elif s == '-0':
print("Create (or make empty) secret_message.txt in right utf-8 encoding.")
if(not get_yes_no()):
continue
try:
write_txt("secret_message", "")
print(ok)
except:
print(err)
else:
print("Impossible behaviour, mistake in source code!\nThe string allowed in the inp array is not bound to the call of any function!")
return 1
return 0
def get_yes_no():
s = input("Confirm (0 = go back, 1 = continue): ")
while s not in ['0', '1']:
s = input("Try again, 0 or 1: ")
return int(s)
def myhash(s, m = 2**61 - 1, p = 257):
a = 0
for i in range(len(s)):
a = ((a * p) % m + ord(s[i])) % m
return a
def normalhash(s):
return int(hashlib.sha256(bytearray(s, 'utf-8')).hexdigest(), 16)
def PT(m, M = 3):
if m == 0:
print("Iron: 'OK, I will choose the number by myself.'")
while m == 0:
m = random.randint(-M, M)
s = "PT!"
p = " "
f = False
if m < 0:
s, p = p, s
m *= -1
f = True
if m > M:
print("Iron: 'Are you sure to move me so far?'")
if(not get_yes_no()):
return
print()
if f:
print(p * (10 * m + 1))
print(p + (s * 3 + p + s * 3 + p + s + p) * m)
print(p + (s + p + s + p * 2 + s + p * 2 + s + p) * m)
print(p + (s * 3 + p * 2 + s + p * 2 + s + p) * m)
print(p + (s + p * 4 + s + p * 4) * m)
print(p + (s + p * 4 + s + p * 2 + s + p) * m)
if f:
print(p * (10 * m + 1))
print()
def write_txt(name, string):
with open(name + ".txt", "w", encoding = "utf-8") as f:
f.write(string)
def read_txt(name):
with open(name + ".txt", "r", encoding = "utf-8") as f:
out = f.read()
return out
if __name__ == "__main__":
main()

@ -1,246 +0,0 @@
#McEliece cryptosystem implementation by vovuas2003
#Usage:
#G = pubkey; S and P = privkeys; text = plaintext; msg = encrypted text
#all these variables are strings, so it's easy to integrate this code into any project (check GUI and console examples)
#text must be in utf-8 encoding (e.g. force encoding when open txt files, check console example)
#keys and messages are saved as base64 strings
#you can use bin_encrypt and bin_decrypt functions if text is a byte array (check console example)
'''
import cryptosystem_core as core
G, S, P = core.generate()
G, S, P = core.unsafe_generate(seed) #e.g. seed = hash(password)
msg = core.encrypt(G, text)
text = core.decrypt(S, P, msg)
G = core.restore_G(S, P)
S = core.break_S(G, P)
P = core.break_P(G, S)
core.config("255 210") #this is the default configuration, NO NEED TO WRITE THIS LINE FOR INITIALIZATION, it is just an example of using the function
#these parameters n and k affect the length of the keys, messages and the number of erroneous bytes in the message
#larger values = larger keys; randomly change (n - k) div 2 bytes during encryption, but add (n - k + 1) bytes to each chunk with len (k - 1).
#see the comments below to understand the requirements for n and k (or check console example)
'''
#if you want to figure out how the code below works, keep in mind that
#G_ is a pubkey, G is a Reed Solomon code matrix and P is saved as permutation array
#to use the core of the cryptosystem, you don't need to think about it, just write the code as in the example above
import numpy as np
import galois
import random
import base64
order = 256 #p^m = 2**8; encrypt each byte and save in base64 format
n = 255 #(order - 1) mod n = 0 for Reed Solomon code; 255 = 3 * 5 * 17 = (order - 1)
k = 210 #2 <= k <= n; randomly change (n - k) div 2 bytes during encryption
GF = galois.GF(2, 8, irreducible_poly = "x^8 + x^4 + x^3 + x^2 + 1", primitive_element = "x", verify = False) #hardcoded galois.GF(2**8).properties for pyinstaller
rs = galois.ReedSolomon(n, k, field = GF)
def main(): #for testing
pass
def config(string):
global n
global k
global rs
try:
nn, kk = map(int, string.split()[:2])
if kk < 2:
raise Exception()
rrss = galois.ReedSolomon(nn, kk, field = GF)
except:
raise Exception()
else:
n = nn
k = kk
rs = rrss
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 unsafe_generate(h):
seed = h % (2**32)
S = unsafe_generate_S(seed)
G = rs.G
P, p = unsafe_generate_P(seed)
G_ = S @ G @ P
return write_pubkey(G_), write_privkey_s(S), write_privkey_p(p)
def unsafe_generate_S(seed):
pseudo = np.random.RandomState(seed)
S = GF(pseudo.randint(0, order, (k, k)))
while np.linalg.det(S) == 0:
S = GF(pseudo.randint(0, order, (k, k)))
return S
def unsafe_generate_P(seed):
pseudo = np.random.RandomState(seed)
p = [i for i in range(n)]
pseudo.shuffle(p)
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_]
row = bytes([i for j in rows for i in j])
return base64.b64encode(row).decode()
def write_privkey_s(S):
rows = [bytes(row) for row in S]
row = bytes([i for j in rows for i in j])
return base64.b64encode(row).decode()
def write_privkey_p(p):
return base64.b64encode(bytes(p)).decode()
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):
return bin_encrypt(key, text.encode("utf-8"))
def decrypt(s, p, msg):
return bin_decrypt(s, p, msg).decode("utf-8")
def bin_encrypt(key, text):
G_ = GF(read_pubkey(key))
out = bytes()
while len(text) > k - 1:
tmp = text[: k - 1]
text = text[k - 1 :]
out += encrypt_one(G_, tmp)
out += encrypt_one(G_, text)
return base64.b64encode(out).decode()
def bin_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)
return msg
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 bytes(c)
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)
if __name__ == "__main__":
main()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

@ -1,350 +0,0 @@
#pip install pyinstaller
#pyinstaller -F -i "icon.ico" portable.py
#exe into dist folder
import numpy as np
import galois
import random
import getpass
def main():
safe_start()
def safe_start():
try:
start_menu()
except:
print("\nUnknown error, maybe ctrl+c\n")
def start_menu():
f = True
print("\nA soldering iron is into a black hole.")
#thermorectal cryptanalysis
if myhash(getpass.getpass("Login: ")) != 1314399736851798576:
f = False
if myhash(getpass.getpass("Password: ")) != 192441972608755898:
f = False
if f:
print("Authorization successful, wait a bit.")
menu()
else:
print("Permission denied.")
print("\nPress ENTER to exit.", end = '')
input()
def menu():
order = 2 ** 8
n = order - 1
k = 210
#print(galois.GF(2 ** 8).properties)
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)
print("\nMcEliece cryptosystem implementation by vovuas2003.\n")
print("All necessary txt files must be located in the directory with this exe program.\n")
info = "Menu numbers: 0 = exit, 1 = generate keys, 2 = encrypt, 3 = decrypt,\n4 = restore pubkey, 5 = break privkey_s, 6 = break privkey_p; h = help.\n"
err = "Error! Check command info and try again!\n"
ok = "Operation successful.\n"
inp = [str(i) for i in range(7)] + ['h'] + ['1337']
print(info)
while True:
s = input("Menu number: ")
while s not in inp:
s = input("Wrong menu number, h = help: ")
if s == 'h':
print(info)
elif s == '0':
print("\nGood luck!")
break
elif s == '1':
print("This operation will rewrite pubkey.txt, privkey_s.txt and privkey_p.txt; are you sure?")
if(not get_yes_no()):
continue
try:
generate(n, k, GF, rs)
print(ok)
except:
print(err)
elif s == '2':
print("Write your text into text.txt; pubkey.txt is required, message.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
encrypt(n, k, order, GF)
print(ok)
except:
print(err)
elif s == '3':
print("You need message.txt, privkey_s.txt and privkey_p.txt; text.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
decrypt(n, GF, rs)
print(ok)
except:
print(err)
elif s == '4':
print("You need privkey_s.txt and privkey_p.txt; pubkey.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
restore_G_(n, GF, rs)
print(ok)
except:
print(err)
elif s == '5':
print("You need pubkey.txt and privkey_p.txt; privkey_s.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
break_S(n, k, GF)
print(ok)
except:
print(err)
elif s == '6':
print("You need pubkey.txt and privkey_s.txt; privkey_p.txt will be rewritten.")
if(not get_yes_no()):
continue
try:
break_P(n, GF, rs)
print(ok)
except:
print(err)
elif s == '1337':
c = input("Move the soldering iron into the black hole number: ")
try:
PT(int(c))
except:
print("Iron: 'I don't know this hole.'")
continue
else:
print("Impossible behaviour, mistake in source code!\nThe string allowed in the inp array is not bound to the call of any function!")
break
def get_yes_no():
s = input("Confirm (0 = go back, 1 = continue): ")
while s not in ['0', '1']:
s = input("Try again, 0 or 1: ")
return int(s)
def myhash(s, m = 2**61 - 1, p = 257):
a = 0
for i in range(len(s)):
a = ((a * p) % m + ord(s[i])) % m
return a
def PT(m):
M = 5
if m == 0:
print("Iron: 'OK, I will choose the number by myself.'")
while m == 0:
m = random.randint(-M, M)
s = "PT!"
p = " "
f = False
if m < 0:
s, p = p, s
m *= -1
f = True
if m > M:
print("Iron: 'Are you sure to move me so far?'")
if(not get_yes_no()):
return
print()
if f:
print(p * (10 * m + 1))
print(p + (s * 3 + p + s * 3 + p + s + p) * m)
print(p + (s + p + s + p * 2 + s + p * 2 + s + p) * m)
print(p + (s * 3 + p * 2 + s + p * 2 + s + p) * m)
print(p + (s + p * 4 + s + p * 4) * m)
print(p + (s + p * 4 + s + p * 2 + s + p) * m)
if f:
print(p * (10 * m + 1))
print()
def generate(n, k, GF, rs):
S = generate_S(k, GF)
G = rs.G
P, p = generate_P(n, GF)
G_ = S @ G @ P
write_pubkey(G_)
write_privkey(S, p)
def generate_S(k, GF):
S = GF.Random((k, k))
while np.linalg.det(S) == 0:
S = GF.Random((k, k))
return S
def generate_P(n, GF):
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 = [" ".join([str(int(cell)) for cell in row]) for row in G_]
output = "\n".join(rows)
with open("pubkey.txt", "w") as f:
f.write(output)
def write_privkey(S, p):
output = " ".join([str(i) for i in p])
with open("privkey_p.txt", "w") as f:
f.write(output)
rows = [" ".join([str(int(cell)) for cell in row]) for row in S]
output = "\n".join(rows)
with open("privkey_s.txt", "w") as f:
f.write(output)
def read_pubkey():
out = []
tmp = []
with open("pubkey.txt", "r") as f:
while True:
tmp = f.readline()
if not tmp:
break
out.append([int(i) for i in tmp.split()])
return out
def read_privkey_s():
out = []
tmp = []
with open("privkey_s.txt", "r") as f:
while True:
tmp = f.readline()
if not tmp:
break
out.append([int(i) for i in tmp.split()])
return out
def read_privkey_p():
with open("privkey_p.txt", "r") as f:
out = f.readline().split()
return [int(i) for i in out]
def build_P(n, GF, p):
P = GF.Zeros((n, n))
for i in range(n):
P[i, p[i]] = 1
return P
def build_P_inv(n, GF, 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(n, k, order, GF):
G_ = GF(read_pubkey())
with open("text.txt", "r") as f:
text = f.read()
text = text.encode()
with open("message.txt", "w") as f:
while len(text) > k - 1:
tmp = text[: k - 1]
text = text[k - 1 :]
c = encrypt_one(n, k, order, GF, G_, tmp)
f.write(" ".join([str(i) for i in c]))
f.write("\n")
c = encrypt_one(n, k, order, GF, G_, text)
f.write(" ".join([str(i) for i in c]))
def encrypt_one(n, k, order, GF, 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
return c + GF(z)
def decrypt(n, GF, rs):
S_inv = np.linalg.inv(GF(read_privkey_s()))
P_inv = GF(build_P_inv(n, GF, read_privkey_p()))
s = []
with open("message.txt", "r") as inp, open("text.txt", "w") as out:
while True:
msg = inp.readline()
if not msg:
break
msg = GF(list(map(int, msg.split())))
s += decrypt_one(rs, S_inv, P_inv, msg)
out.write(bytes(s).decode())
def decrypt_one(rs, 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_(n, GF, rs):
S = GF(read_privkey_s())
G = rs.G
P = GF(build_P(n, GF, read_privkey_p()))
G_ = S @ G @ P
write_pubkey(G_)
def break_S(n, k, GF):
G_ = GF(read_pubkey())
P_inv = GF(build_P_inv(n, GF, read_privkey_p()))
S = G_ @ P_inv
S = S[:, : k]
rows = [" ".join([str(int(cell)) for cell in row]) for row in S]
output = "\n".join(rows)
with open("privkey_s.txt", "w") as f:
f.write(output)
def break_P(n, GF, rs):
G_ = GF(read_pubkey())
S_inv = np.linalg.inv(GF(read_privkey_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()
output = " ".join([str(i) for i in p])
with open("privkey_p.txt", "w") as f:
f.write(output)
if __name__ == "__main__":
main()

@ -0,0 +1,2 @@
numpy
galois
Loading…
Cancel
Save