Compare commits

..

3 Commits

@ -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" ]

@ -1,8 +1,5 @@
#pyinstaller -F -i "icon.ico" McEliece_console_v2.py
import hashlib
import getpass
import pyperclip
def main():
safe_start()
@ -10,8 +7,8 @@ def main():
def safe_start():
try:
start_menu()
except:
print("\nUnknown error (maybe ctrl+c), emergency exit!")
except (KeyboardInterrupt, EOFError):
print("\nExiting...")
def start_menu():
f = True
@ -30,14 +27,14 @@ def start_menu():
input()
def menu():
import cryptosystem_core_v2 as ME_core
import cryptosystem_core as ME_core
core = ME_core.McEliece_core()
global_info = "All files are interpreted as raw bytes and must be located in the directory with this executable file.\nDefault filenames with .bin extension: pubkey, privkey_S, privkey_p, plaintext, ciphertext, ciphered_string.\nDon't forget to import (or generate) keys before encryption/decryption and after changing config!\nYou can restore any one key from two another (don't forget to import before).\n"
info = "Menu numbers: 0 = exit, s = print short info, h = print this info, g = print global info, c = change config;\n1 = generate keys, 10 = unsafe generate keys (seed = hash(password));\n11 = export pubkey, 12 = export privkey_S, 13 = export privkey_p,\n14 = import pubkey, 15 = import privkey_S, 16 = import privkey_p,\n17 = restore pubkey, 18 = restore privkey_S, 19 = restore privkey_p;\n2 = encrypt,\n21 = encrypt non-default filename, 22 = encrypt string from keyboard, 23 = encrypt hided string;\n3 = decrypt,\n31 = decrypt non-default filename, 32 = decrypt string on screen, 33 = decrypt string to clipboard.\n"
info = "Menu numbers: 0 = exit, s = print short info, h = print this info, g = print global info, c = change config;\n1 = generate keys, 10 = unsafe generate keys (seed = hash(password)),\n11 = export pubkey, 12 = export privkey_S, 13 = export privkey_p,\n14 = import pubkey, 15 = import privkey_S, 16 = import privkey_p,\n17 = restore pubkey, 18 = restore privkey_S, 19 = restore privkey_p;\n2 = encrypt,\n21 = encrypt non-default filename, 22 = encrypt string from keyboard, 23 = encrypt hided string.\n3 = decrypt,\n31 = decrypt non-default filename, 32 = decrypt string and show on screen\n"
short_info = "0 = exit, s/h/g = print short/extended/global info, c = change config;\n1 = generate keys, 2 = encrypt, 3 = decrypt\n"
err = "Error! Check global info (menu number g) and try again!\n"
ok = "Operation successful.\n"
inp = ['0', 's', 'h', 'g', 'c'] + [str(i) for i in range(1, 4)] + [str(i) for i in range(10, 20)] + [str(i) for i in range(21, 24)] + [str(i) for i in range(31, 34)] + ['1337']
inp = ['0', 's', 'h', 'g', 'c'] + [str(i) for i in range(1, 4)] + [str(i) for i in range(10, 20)] + [str(i) for i in range(21, 24)] + [str(i) for i in range(31, 33)] + ['1337']
print("\nMcEliece cryptosystem implementation by vovuas2003. Version 2.\n")
print(global_info)
print(info)
@ -226,7 +223,7 @@ def menu():
except:
print(err)
elif s == '32':
print("Need ciphered_string.bin! Visible input!!!")
print("Need ciphered_string.bin!")
if(not get_yes_no()):
continue
try:
@ -234,20 +231,6 @@ def menu():
print(ok)
except:
print(err)
elif s == '33':
print("Need ciphered_string.bin! Copy to clipboard.")
if(not get_yes_no()):
continue
try:
tmp = bytes(core.decrypt([int(i) for i in read_file("ciphered_string.bin")])).decode('utf-8')
except:
print(err)
continue
try:
pyperclip.copy(tmp)
print(ok)
except:
print("Decryption was successful, but program can't use clipboard.\nOn Linux (especially Ubuntu) try to install xclip (e.g. via apt-get).")
elif s == '1337':
PT()
else:

@ -0,0 +1,50 @@
from cryptosystem_core import *
def main(): #comment "return" for testing
core = McEliece_core()
n, k = core.get_config()
print(n, k)
core.change_config(5, 3) #check comments in class implementation to understand possible values
n, k = core.get_config()
print(n, k)
print()
core.generate_keys() #true random
print(core.get_pubkey())
print(core.get_privkey_S())
print(core.get_privkey_p())
print()
core.generate_keys(sum([ord(i) for i in list("password")])) #very simple seed
G = core.get_pubkey()
S = core.get_privkey_S()
p = core.get_privkey_p()
print(G)
print(S)
print(p)
print()
core.change_config(5, 3) #unset all keys inside core
core.set_privkey_S(S)
core.set_privkey_p(p)
core.restore_pubkey()
print(core.get_pubkey() == G)
core.change_config(5, 3) #unset all keys inside core
core.set_pubkey(G)
core.set_privkey_p(p)
core.restore_privkey_S()
print(core.get_privkey_S() == S)
core.change_config(5, 3) #unset all keys inside core
core.set_pubkey(G)
core.set_privkey_S(S)
core.restore_privkey_p()
print(core.get_privkey_p() == p)
print()
for j in range(2):
text = [i + 1 for i in range(5)]
msg = core.encrypt(text)
print(msg)
text = core.decrypt(msg)
print(text)
print()
print("All tests are finished!")
if __name__ == "__main__":
main()

@ -0,0 +1,15 @@
McEliece cryptosystem implementation by vovuas2003
Required Python libraries: numpy, galois.
UPDATE: version 2 is available. Check cryptosystem_core_v2 and McEliece_console_v2.
All cryptosystem functions are implemented in cryptosystem_core.py, just import it into your project and enjoy!
For example, I coded a console menu (that works with text in txt files and also with any files in binary mode) and a GUI app (for text encryption).
It is possible to build portable exe with pyinstaller and run code on a computer that does not have Python installed.
But it is NOT compilation, so exe file will be quite large.
The pdf presentation in Russian contains a bit of theory about the Mceliece cryptosystem.
icon.ico is an optional file for pyinstaller
old_portable.py can support another order of galois field, but saves raw integers and does not specify utf-8 encoding for strings and txt files

@ -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()

@ -1,92 +0,0 @@
import numpy as np
import galois
import random
import getpass
import hashlib
import pyperclip
def main():
try:
menu()
except:
print("Error!")
def menu():
core = McEliece_core()
core.generate_keys(normalhash(getpass.getpass("Password: ")))
pyperclip.copy(bytes(core.decrypt([int(i) for i in read_file("only_password")])).decode('utf-8'))
print("OK!")
class McEliece_core:
def __init__(self):
self._order = 256
self._n = 255
self._k = 210
self._GF = galois.GF(2, 8, irreducible_poly = "x^8 + x^4 + x^3 + x^2 + 1", primitive_element = "x", verify = False)
self._rs = galois.ReedSolomon(self._n, self._k, field = self._GF)
self._G = self._GF.Zeros((self._k, self._n))
self._S = self._GF.Zeros((self._k, self._k))
self._S_inv = self._GF.Zeros((self._k, self._k))
self._P = self._GF.Zeros((self._n, self._n))
self._P_inv = self._GF.Zeros((self._n, self._n))
self._p = [0 for i in range(self._n)]
def generate_keys(self, seed):
seed %= 2**32
self._unsafe_generate_S(seed)
self._unsafe_generate_P(seed)
self._G = self._S @ self._rs.G @ self._P
def decrypt(self, msg):
try:
msg = [msg[i - self._n : i] for i in range(self._n, len(msg) + self._n, self._n)]
msg = [self._decrypt_one(self._GF(i)) for i in msg]
return [i for j in msg for i in j]
except:
raise
def _unsafe_generate_S(self, seed):
pseudo = np.random.RandomState(seed)
S = self._GF(pseudo.randint(0, self._order, (self._k, self._k)))
while np.linalg.det(S) == 0:
S = self._GF(pseudo.randint(0, self._order, (self._k, self._k)))
self._S = S
self._S_inv = np.linalg.inv(S)
def _unsafe_generate_P(self, seed):
pseudo = np.random.RandomState(seed)
p = [i for i in range(self._n)]
pseudo.shuffle(p)
self._p = p
self._P = self._GF.Zeros((self._n, self._n))
self._P_inv = self._GF.Zeros((self._n, self._n))
for i in range(self._n):
self._P[i, p[i]] = 1
self._P_inv[p[i], i] = 1
def _decrypt_one(self, msg):
msg = msg @ self._P_inv
msg, e = self._rs.decode(msg, errors = True)
if e == -1:
raise Exception()
msg = msg @ self._S_inv
msg = [int(i) for i in msg]
try:
msg = self._unpad_message(msg)
except:
raise
return msg
def _unpad_message(self, msg):
last_value = msg[-1]
if last_value >= self._k or last_value <= 0:
raise Exception()
for i in range(1, last_value + 1):
if msg[-i] != last_value:
raise Exception()
return msg[: -last_value]
def read_file(name):
with open(name, "rb") as f:
data = f.read()
return data
def normalhash(s):
return int(hashlib.sha256(bytearray(s, 'utf-8')).hexdigest(), 16)
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()

@ -1,249 +0,0 @@
import numpy as np
import galois
import random
import getpass
import hashlib
import pyperclip
def main():
try:
menu()
except:
print("\nUnknown error (maybe ctrl+c), emergency exit!")
def menu():
info = "Menu numbers: h = info, t = test clipboard, c = config;\n0 = exit, 1 = generate, 2 = encrypt, 3 = decrypt\n"
err = "Error, try again!\n"
ok = "Operation successful.\n"
inp = ['h', 'c', 't'] + [str(i) for i in range (4)] + ['1337']
core = McEliece_core()
print("\nMcEliece password encryption by vovuas2003.\n")
print(info)
while True:
s = input("Menu number: ")
while s not in inp:
s = input("Wrong menu number; h = help: ")
if s == '0':
print("\nGood luck!")
break
elif s == 'h':
print(info)
elif s == 't':
print("Do you want to check Python ability to use clipboard in your OS?")
if(not get_yes_no()):
continue
try:
print('Trying to write "Hello, world!" to clipboard.')
mycopy("Hello, world!")
print("Success! You can check ctrl+v.")
except:
print("Python cannot use clipboard. On Linux maybe you need to run command: sudo apt-get install xclip.\nOr try code below to check python error log:\nimport pyperclip #don't forget to pip install pyperclip\npyperclip.copy(\"Hello, world!\")")
elif s == 'c':
n, k = core.get_config()
print("Default config is 255 210, current is " + str(n) + " " + str(k) + ". Change config? Also reset all keys!")
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).")
n, k = map(int, input("Write n and k separated by a space: ").split())
core.change_config(n, k)
print(ok)
except:
print(err)
elif s == '1':
print("Reset all keys!")
if(not get_yes_no()):
continue
try:
core.generate_keys(normalhash(getpass.getpass("Password for hash: ")))
print(ok)
except:
print(err)
elif s == '2':
print("Encrypt hided input (ONLY ONE LINE!!!) from clipboard!")
if(not get_yes_no()):
continue
try:
inp_str = getpass.getpass("Hided string to encrypt: ")
out_name = input("Filename to save: ")
if not out_name:
print("Using default name ciphered_string.bin")
out_name = "ciphered_string.bin"
write_file(out_name, bytes(core.encrypt([int(i) for i in inp_str.encode('utf-8')])))
print(ok)
except:
print(err)
elif s == '3':
print("Decrypt string from file and copy to clipboard!")
if(not get_yes_no()):
continue
try:
inp_name = input("Filename to decrypt: ")
if not inp_name:
print("Using default name ciphered_string.bin")
inp_name = "ciphered_string.bin"
mycopy(bytes(core.decrypt([int(i) for i in read_file(inp_name)])).decode('utf-8'))
print(ok)
except:
print(err)
elif s == '1337':
mycopy(PT())
else:
print("Impossible behaviour, mistake in source code, emergency exit!\nThe string allowed in the inp array is not bound to the call of any function!")
break
class McEliece_core:
def __init__(self):
self._order = 256
self._n = 255
self._k = 210
self._t = (self._n - self._k) // 2
self._GF = galois.GF(2, 8, irreducible_poly = "x^8 + x^4 + x^3 + x^2 + 1", primitive_element = "x", verify = False)
self._rs = galois.ReedSolomon(self._n, self._k, field = self._GF)
self._G = self._GF.Zeros((self._k, self._n))
self._S = self._GF.Zeros((self._k, self._k))
self._S_inv = self._GF.Zeros((self._k, self._k))
self._P = self._GF.Zeros((self._n, self._n))
self._P_inv = self._GF.Zeros((self._n, self._n))
self._p = [0 for i in range(self._n)]
def change_config(self, n, k):
try:
if k < 2:
raise Exception()
rs = galois.ReedSolomon(n, k, field = self._GF)
except:
raise
else:
self._n = n
self._k = k
self._t = (n - k) // 2
self._rs = rs
self._G = self._GF.Zeros((self._k, self._n))
self._S = self._GF.Zeros((self._k, self._k))
self._S_inv = self._GF.Zeros((self._k, self._k))
self._P = self._GF.Zeros((self._n, self._n))
self._P_inv = self._GF.Zeros((self._n, self._n))
self._p = [0 for i in range(self._n)]
def get_config(self):
return self._n, self._k
def generate_keys(self, seed):
seed %= 2**32
self._unsafe_generate_S(seed)
self._unsafe_generate_P(seed)
self._G = self._S @ self._rs.G @ self._P
def encrypt(self, text):
try:
out = []
while len(text) > self._k - 1:
tmp = text[: self._k - 1]
text = text[self._k - 1 :]
out += self._encrypt_one(tmp)
out += self._encrypt_one(text)
return out
except:
raise
def decrypt(self, msg):
try:
msg = [msg[i - self._n : i] for i in range(self._n, len(msg) + self._n, self._n)]
msg = [self._decrypt_one(self._GF(i)) for i in msg]
return [i for j in msg for i in j]
except:
raise
def _unsafe_generate_S(self, seed):
pseudo = np.random.RandomState(seed)
S = self._GF(pseudo.randint(0, self._order, (self._k, self._k)))
while np.linalg.det(S) == 0:
S = self._GF(pseudo.randint(0, self._order, (self._k, self._k)))
self._S = S
self._S_inv = np.linalg.inv(S)
def _unsafe_generate_P(self, seed):
pseudo = np.random.RandomState(seed)
p = [i for i in range(self._n)]
pseudo.shuffle(p)
self._p = p
self._P = self._GF.Zeros((self._n, self._n))
self._P_inv = self._GF.Zeros((self._n, self._n))
for i in range(self._n):
self._P[i, p[i]] = 1
self._P_inv[p[i], i] = 1
def _encrypt_one(self, text):
msg = self._pad_message(text)
m = self._GF(msg)
c = m.T @ self._G
z = np.zeros(self._n, dtype = int)
p = [i for i in range(self._n)]
for i in range(self._t):
ind = p.pop(random.randint(0, self._n - 1 - i))
z[ind] = random.randint(1, self._order - 1)
c = c + self._GF(z)
return [int(i) for i in c]
def _decrypt_one(self, msg):
msg = msg @ self._P_inv
msg, e = self._rs.decode(msg, errors = True)
if e == -1:
raise Exception()
msg = msg @ self._S_inv
msg = [int(i) for i in msg]
try:
msg = self._unpad_message(msg)
except:
raise
return msg
def _pad_message(self, msg):
last_value = self._k - (len(msg) % self._k)
return msg + [last_value] * last_value
def _unpad_message(self, msg):
last_value = msg[-1]
if last_value >= self._k or last_value <= 0:
raise Exception()
for i in range(1, last_value + 1):
if msg[-i] != last_value:
raise Exception()
return msg[: -last_value]
def write_file(name, data):
with open(name, "wb") as f:
f.write(data)
def read_file(name):
with open(name, "rb") as f:
data = f.read()
return data
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 normalhash(s):
return int(hashlib.sha256(bytearray(s, 'utf-8')).hexdigest(), 16)
def PT(m = -3, M = 3):
if m == 0 or abs(m) > M:
return "PT!"
s = "PT!"
p = " "
f = False
if m < 0:
s, p = p, s
m *= -1
f = True
out = "\n"
if f:
out += p * (10 * m + 1) + "\n"
out += p + (s * 3 + p + s * 3 + p + s + p) * m + "\n"
out += p + (s + p + s + p * 2 + s + p * 2 + s + p) * m + "\n"
out += p + (s * 3 + p * 2 + s + p * 2 + s + p) * m + "\n"
out += p + (s + p * 4 + s + p * 4) * m + "\n"
out += p + (s + p * 4 + s + p * 2 + s + p) * m + "\n"
if f:
out += p * (10 * m + 1) + "\n"
out += "\n"
return out
def mycopy(s):
pyperclip.copy(s)
if __name__ == "__main__":
main()

@ -1,5 +0,0 @@
McEliece cryptosystem implementation by vovuas2003
Required additional Python libraries: numpy, galois (numpy extension).
Version 2 is the latest. Check cryptosystem_core_v2 and McEliece_console_v2.

@ -11,62 +11,11 @@ import numpy as np
import galois
import random
#import cryptosystem_core_v2 as ME_core
#core = ME_core.McEliece_core()
def main(): #comment "return" for testing
return
core = McEliece_core()
n, k = core.get_config()
print(n, k)
core.change_config(5, 3) #check comments in class implementation to understand possible values
n, k = core.get_config()
print(n, k)
print()
core.generate_keys() #true random
print(core.get_pubkey())
print(core.get_privkey_S())
print(core.get_privkey_p())
print()
core.generate_keys(sum([ord(i) for i in list("password")])) #very simple seed
G = core.get_pubkey()
S = core.get_privkey_S()
p = core.get_privkey_p()
print(G)
print(S)
print(p)
print()
core.change_config(5, 3) #unset all keys inside core
core.set_privkey_S(S)
core.set_privkey_p(p)
core.restore_pubkey()
print(core.get_pubkey() == G)
core.change_config(5, 3) #unset all keys inside core
core.set_pubkey(G)
core.set_privkey_p(p)
core.restore_privkey_S()
print(core.get_privkey_S() == S)
core.change_config(5, 3) #unset all keys inside core
core.set_pubkey(G)
core.set_privkey_S(S)
core.restore_privkey_p()
print(core.get_privkey_p() == p)
print()
for j in range(2):
text = [i + 1 for i in range(5)]
msg = core.encrypt(text)
print(msg)
text = core.decrypt(msg)
print(text)
print()
print("All tests are finished!")
class McEliece_core:
def __init__(self):
self._order = 256 #p^m = 2**8; encryption of each byte
self._n = 255 #(order - 1) mod n = 0 for Reed Solomon code; 255 = 3 * 5 * 17 = (order - 1)
self._k = 210 #2 <= k <= n; randomly change t = (n - k) div 2 bytes during encryption, but add (n - k + 1) bytes to each chunk with len (k - 1); k != 1 for padding function; k almost equal to n is very bad because of small amount of randomly changed bytes (k == n -> privkey for decryption == numpy.linalg.inv(pubkey))
self._t = (self._n - self._k) // 2
self._k = 210 #2 <= k <= n; randomly change (n - k) div 2 bytes during encryption, but add (n - k + 1) bytes to each chunk with len (k - 1); k != 1 for padding function; k almost equal to n is very bad because of small amount of randomly changed bytes (k == n -> privkey for decryption == numpy.linalg.inv(pubkey))
self._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
self._rs = galois.ReedSolomon(self._n, self._k, field = self._GF)
self._G = self._GF.Zeros((self._k, self._n)) #pubkey
@ -85,7 +34,6 @@ class McEliece_core:
else:
self._n = n
self._k = k
self._t = (n - k) // 2
self._rs = rs
#Also unset all keys!
self._G = self._GF.Zeros((self._k, self._n))
@ -103,9 +51,8 @@ class McEliece_core:
elif type(seed) != int:
raise Exception()
else:
seed %= 2**32
self._unsafe_generate_S(seed)
self._unsafe_generate_P(seed)
self._unsafe_generate_S(seed % (2**32))
self._unsafe_generate_P(seed % (2**32))
self._G = self._S @ self._rs.G @ self._P
def get_pubkey(self):
return [int(i) for j in self._G for i in j]
@ -171,8 +118,6 @@ class McEliece_core:
if f:
continue
raise Exception()
if sorted(p) != [i for i in range(self._n)]:
raise Exception()
self._p = p
self._P = self._GF.Zeros((self._n, self._n))
self._P_inv = self._GF.Zeros((self._n, self._n))
@ -236,9 +181,10 @@ class McEliece_core:
msg = self._pad_message(text)
m = self._GF(msg)
c = m.T @ self._G
t = (self._n - self._k) // 2
z = np.zeros(self._n, dtype = int)
p = [i for i in range(self._n)]
for i in range(self._t):
for i in range(t):
ind = p.pop(random.randint(0, self._n - 1 - i))
z[ind] = random.randint(1, self._order - 1)
c = c + self._GF(z)
@ -266,6 +212,3 @@ class McEliece_core:
if msg[-i] != last_value:
raise Exception()
return msg[: -last_value]
if __name__ == "__main__":
main()

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