Add files via upload
commit
adfe360621
@ -0,0 +1,60 @@
|
|||||||
|
#break cryptosystem if know a half of private key
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import galois
|
||||||
|
|
||||||
|
import pubkey
|
||||||
|
import privkey
|
||||||
|
import message
|
||||||
|
|
||||||
|
n = 127
|
||||||
|
k = 32
|
||||||
|
order = 2 ** 7
|
||||||
|
GF = galois.GF(order)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
G_ = GF(pubkey.get()) #we need to know a public matrix
|
||||||
|
P = GF(privkey.get_P()) #and P - only one of two private matrices
|
||||||
|
S = break_S(P, G_) #to calculate S - the second part of private key
|
||||||
|
c = GF(message.get())
|
||||||
|
print(decode(S, P, c)) #and decode the message
|
||||||
|
|
||||||
|
def unpad_message(msg):
|
||||||
|
padding_byte = msg[-1]
|
||||||
|
for i in range(1, padding_byte + 1):
|
||||||
|
if msg[-i] != padding_byte:
|
||||||
|
raise ValueError("Incorrect padding!")
|
||||||
|
return msg[:-padding_byte]
|
||||||
|
|
||||||
|
def my_fix(A):
|
||||||
|
#make square matrix by deleting right columns
|
||||||
|
l = len(A)
|
||||||
|
r = GF.Zeros((l, l))
|
||||||
|
for i in range(l):
|
||||||
|
for j in range(l):
|
||||||
|
r[i][j] = A[i][j]
|
||||||
|
return r
|
||||||
|
|
||||||
|
def decode(S, P, c):
|
||||||
|
rs = galois.ReedSolomon(n, k, field=GF)
|
||||||
|
c = c @ np.linalg.inv(P)
|
||||||
|
c = rs.decode(c)
|
||||||
|
c = c @ np.linalg.inv(S)
|
||||||
|
c = [int(i) for i in c]
|
||||||
|
c = unpad_message(c)
|
||||||
|
c = bytes(c)
|
||||||
|
c = c.decode()
|
||||||
|
return c
|
||||||
|
|
||||||
|
def break_S(P, G_):
|
||||||
|
#G_ = S @ G @ P
|
||||||
|
rs = galois.ReedSolomon(n, k, field=GF)
|
||||||
|
G = rs.G
|
||||||
|
G_ = G_ @ np.linalg.inv(P)
|
||||||
|
G_ = my_fix(G_)
|
||||||
|
G = my_fix(G)
|
||||||
|
S = G_ @ np.linalg.inv(G)
|
||||||
|
return S
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -0,0 +1,37 @@
|
|||||||
|
import numpy as np
|
||||||
|
import galois
|
||||||
|
|
||||||
|
import privkey
|
||||||
|
import message
|
||||||
|
|
||||||
|
n = 127
|
||||||
|
k = 32
|
||||||
|
order = 2 ** 7
|
||||||
|
GF = galois.GF(order)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
S = GF(privkey.get_S())
|
||||||
|
P = GF(privkey.get_P())
|
||||||
|
c = GF(message.get())
|
||||||
|
print(decode(S, P, c))
|
||||||
|
|
||||||
|
def unpad_message(msg):
|
||||||
|
padding_byte = msg[-1]
|
||||||
|
for i in range(1, padding_byte + 1):
|
||||||
|
if msg[-i] != padding_byte:
|
||||||
|
raise ValueError("Incorrect padding!")
|
||||||
|
return msg[:-padding_byte]
|
||||||
|
|
||||||
|
def decode(S, P, c):
|
||||||
|
rs = galois.ReedSolomon(n, k, field=GF)
|
||||||
|
c = c @ np.linalg.inv(P)
|
||||||
|
c = rs.decode(c)
|
||||||
|
c = c @ np.linalg.inv(S)
|
||||||
|
c = [int(i) for i in c]
|
||||||
|
c = unpad_message(c)
|
||||||
|
c = bytes(c)
|
||||||
|
c = c.decode()
|
||||||
|
return c
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -0,0 +1,40 @@
|
|||||||
|
import numpy as np
|
||||||
|
import galois
|
||||||
|
|
||||||
|
import pubkey
|
||||||
|
|
||||||
|
n = 127
|
||||||
|
k = 32
|
||||||
|
order = 2 ** 7
|
||||||
|
GF = galois.GF(order)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
G_ = GF(pubkey.get())
|
||||||
|
print("Message to encode (max len = k-1 = 31):")
|
||||||
|
message = input()
|
||||||
|
if len(message) > k-1:
|
||||||
|
print("Message is too long!")
|
||||||
|
return
|
||||||
|
ct = encrypt(G_, message)
|
||||||
|
ct = list(map(int, ct))
|
||||||
|
export(ct)
|
||||||
|
print("Done!")
|
||||||
|
|
||||||
|
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 encrypt(G_, text):
|
||||||
|
msg = pad_message(text.encode(), k)
|
||||||
|
m = GF(msg)
|
||||||
|
c = m.T @ G_
|
||||||
|
return c
|
||||||
|
|
||||||
|
def export(ct):
|
||||||
|
output = "ct = [ " + ", ".join([str(int(cell)) for cell in ct]) + " ]"
|
||||||
|
with open("message.py", "w") as f:
|
||||||
|
f.write(output)
|
||||||
|
f.write("\ndef get():\n\treturn ct")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -0,0 +1,58 @@
|
|||||||
|
import numpy as np
|
||||||
|
import galois
|
||||||
|
import random
|
||||||
|
|
||||||
|
n = 127
|
||||||
|
k = 32
|
||||||
|
order = 2 ** 7
|
||||||
|
GF = galois.GF(order)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
S = generate_S()
|
||||||
|
G = generate_G()
|
||||||
|
P = generate_P()
|
||||||
|
G_ = S @ G @ P
|
||||||
|
export_pubkey(G_)
|
||||||
|
export_privkey(S, P)
|
||||||
|
print("Done!")
|
||||||
|
|
||||||
|
def generate_S():
|
||||||
|
S = GF.Random((k, k))
|
||||||
|
while np.linalg.det(S) == 0:
|
||||||
|
S = GF.Random((k, k))
|
||||||
|
return S
|
||||||
|
|
||||||
|
def generate_G():
|
||||||
|
rs = galois.ReedSolomon(n, k, field=GF)
|
||||||
|
G = rs.G
|
||||||
|
return G
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def export_pubkey(G_):
|
||||||
|
rows = [", ".join([str(int(cell)) for cell in row]) for row in G_]
|
||||||
|
output = "G_ = [ " + ",\n".join([f"[{row}]" for row in rows]) + " ]"
|
||||||
|
with open("pubkey.py", "w") as f:
|
||||||
|
f.write(output)
|
||||||
|
f.write("\ndef get():\n\treturn G_")
|
||||||
|
|
||||||
|
def export_privkey(S, P):
|
||||||
|
rows = [", ".join([str(int(cell)) for cell in row]) for row in S]
|
||||||
|
output = "S = [ " + ",\n".join([f"[{row}]" for row in rows]) + " ]\n"
|
||||||
|
rows = [", ".join([str(int(cell)) for cell in row]) for row in P]
|
||||||
|
output += "P = [ " + ",\n".join([f"[{row}]" for row in rows]) + " ]\n"
|
||||||
|
with open("privkey.py", "w") as f:
|
||||||
|
f.write(output)
|
||||||
|
f.write("\ndef get_S():\n\treturn S")
|
||||||
|
f.write("\ndef get_P():\n\treturn P")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -0,0 +1,13 @@
|
|||||||
|
McEliece cryptosystem implementation
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
0. pip install numpy and galois
|
||||||
|
1. generate.py - generate and save public and private keys
|
||||||
|
2. send pubkey.py and encode.py to your friend
|
||||||
|
3. your friend runs encode.py, write secret string and send message.py to you
|
||||||
|
4. decode.py - get secret string
|
||||||
|
|
||||||
|
Hacker can get your private key if he will know a half of it (and pubkey.py, decode.py and Reed-Solomon algo).
|
||||||
|
Check break.py to understand how hacker can do this.
|
||||||
|
|
||||||
|
todo: check randomization during encode (add vector z, check https://en.wikipedia.org/wiki/McEliece_cryptosystem)
|
Loading…
Reference in New Issue