libexam/libexam.py

347 lines
9.5 KiB
Python
Raw Permalink Normal View History

2024-05-29 14:22:49 +08:00
#SPDX-FileCopyrightText: 2024 Crimson Hawk
#SPDX-License-Identifier: GPL-3.0-or-later
2024-04-24 17:51:21 +08:00
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
import string
import time
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode()
2024-05-15 08:39:15 +08:00
unpad = lambda s: s[:-ord(s[len(s) - 1:])]
2024-04-24 17:51:21 +08:00
def iv():
"""
The initialization vector to use for encryption or decryption.
It is ignored for MODE_ECB and MODE_CTR.
"""
return chr(0) * 16
2024-05-15 08:39:15 +08:00
2024-04-24 17:51:21 +08:00
class AESCipher(object):
"""
https://github.com/dlitz/pycrypto
"""
def __init__(self, key):
self.key = key
#self.key = hashlib.sha256(key.encode()).digest()
def encrypt(self, message):
"""
It is assumed that you use Python 3.0+
, so plaintext's type must be str type(== unicode).
"""
message = message.encode()
raw = pad(message)
cipher = AES.new(self.key, AES.MODE_CBC, iv())
enc = cipher.encrypt(raw)
return base64.b64encode(enc).decode('utf-8')
def decrypt(self, enc):
enc = base64.b64decode(enc)
cipher = AES.new(self.key, AES.MODE_CBC, iv())
dec = cipher.decrypt(enc)
return unpad(dec).decode('utf-8')
2024-05-15 08:39:15 +08:00
2024-04-24 17:51:21 +08:00
class question:
2024-05-15 08:39:15 +08:00
def __init__(self, qtype, qproblem, qoption1, qoption2, qoption3,
qoption4):
2024-04-24 17:51:21 +08:00
qtype = self.qtype
qproblem = self.qproblem
qoption1 = self.qoption1
qoption2 = self.qoption2
qoption3 = self.qoption3
qoption4 = self.qoption4
class libexam:
def __init__(self, mode, mode_set, username, questions, password):
self.mode = mode = 0
self.mode_set = mode_set = 0
self.username = username = ""
self.questions = questions = []
self.password = password = -1
2024-04-24 17:51:21 +08:00
def setmode(modein):
self.mode = modein
self.modeset = 1
2024-05-15 08:39:15 +08:00
print(f"Mode set to: {mode}\n") #1: client 2: admin
2024-04-24 17:51:21 +08:00
return 0
def status():
return f"""Mode: {mode}
Username: {username}\n"""
def setuser(user):
self.username = user
2024-04-24 17:51:21 +08:00
print(f"Username set to: {user}\n")
return 0
2024-05-13 11:27:07 +08:00
def setadmin():
passwordf = open("password.txt", "r")
while (True): #hash check
temp = passwordf.readline()
if (temp == "chk"):
sha256.update(temp)
rhash = sha256.digest()
ehash = passwordf.readline()
if (rhash == ehash):
print(f"Hashes match: {rhash}\n")
break
else:
print(
f"Hashes does not match !\nExpected: {ehash}\nGot: {rhash}\n"
)
return 1
sha256.update(temp)
passwordf.close()
passwordf = open("password.txt", "r")
self.password = passwordf.readline()
if (rhash == ehash):
print(f"Hashes match: {rhash}\n")
else:
print(
f"Hashes does not match !\nExpected: {ehash}\nGot: {rhash}\n")
2024-05-13 11:27:07 +08:00
print(f"Read password: {password}\n")
return 0
2024-04-24 17:51:21 +08:00
def readquestions():
2024-05-15 08:39:15 +08:00
sha256 = hashlib.sha256()
2024-04-24 17:51:21 +08:00
questiondocs = open("question.txt", "r")
n = questiondocs.readline()
sha256.update(n)
print(f"n={n}\n")
2024-05-15 08:39:15 +08:00
counter = n
while (True): #hash check
2024-04-24 17:51:21 +08:00
temp = questiondocs.readline()
2024-05-15 08:39:15 +08:00
if (temp == "chk"):
2024-04-24 17:51:21 +08:00
sha256.update(temp)
2024-05-15 08:39:15 +08:00
rhash = sha256.digest()
2024-04-24 17:51:21 +08:00
ehash = questiondocs.readline()
2024-05-15 08:39:15 +08:00
if (rhash == ehash):
2024-04-24 17:51:21 +08:00
print(f"Hashes match: {rhash}\n")
break
else:
2024-05-15 08:39:15 +08:00
print(
f"Hashes does not match !\nExpected: {ehash}\nGot: {rhash}\n"
)
2024-04-24 17:51:21 +08:00
return 1
sha256.update(temp)
questiondocs.close()
questiondocs = open("question.txt", "r")
temp = questiondocs.readline()
2024-05-15 08:39:15 +08:00
while (True):
2024-04-24 17:51:21 +08:00
temp = questiondocs.readline()
2024-05-15 08:39:15 +08:00
if (temp == "chk"):
2024-04-24 17:51:21 +08:00
break
qtype = temp
temp = questiondocs.readline()
temp = temp.split("|")
self.questions.append(
2024-05-15 08:39:15 +08:00
question(qtype, temp[0], temp[1], temp[2], temp[3], temp[4]))
def writeanswer(qn, ans):
if (self.username == ""):
2024-04-24 17:51:21 +08:00
print(f"Username not set!\n")
return 1
md5 = hashlib.md5()
md5.update(self.username)
2024-04-24 17:51:21 +08:00
filename = md5.digest()
print(f"MD5 hash of {user}: {filename}")
2024-05-15 08:39:15 +08:00
2024-04-24 17:51:21 +08:00
sha256 = hashlib.sha256()
datadocs = open(f"{filename}.txt", "r")
n = datadocs.readline()
sha256.update(n)
2024-05-15 08:39:15 +08:00
while (True): #hash check
2024-04-24 17:51:21 +08:00
temp = data.readline()
2024-05-15 08:39:15 +08:00
if (temp == "chk"):
2024-04-24 17:51:21 +08:00
sha256.update(temp)
2024-05-15 08:39:15 +08:00
rhash = sha256.digest()
2024-04-24 17:51:21 +08:00
ehash = data.readline()
2024-05-15 08:39:15 +08:00
if (rhash == ehash):
2024-04-24 17:51:21 +08:00
print(f"Hashes match: {rhash}\n")
break
else:
2024-05-15 08:39:15 +08:00
print(
f"Hashes does not match !\nExpected: {ehash}\nGot: {rhash}\n"
)
2024-04-24 17:51:21 +08:00
return 1
sha256.update(temp)
datadocs.close()
datadocs = open(f"{filename}.txt", "r+")
2024-05-15 08:39:15 +08:00
timestamp = hex(int(time.time())) #part c of a line according to docs
while (len(timestamp) != 16):
2024-04-24 17:51:21 +08:00
timestamp = "0" + timestamp
2024-05-15 08:39:15 +08:00
2024-04-24 17:51:21 +08:00
cd = timestamp + ans
bhash = hashlib.sha256()
bhash.update(cd)
b = bhash.digest()
print(f"Timestamp: {timestamp}\nAnswer: {ans}\nPart B Hash: {b}")
userhash = hashlib.sha256()
userhash.update(self.username)
2024-05-15 08:39:15 +08:00
key = userhash.digest() #generated key for encryption
2024-04-24 17:51:21 +08:00
print(f"Key generated: {key}\n")
2024-05-15 08:39:15 +08:00
bcd = AESCipher(key).encrypt(b + cd) #encrypt
2024-04-24 17:51:21 +08:00
print(f"Parts B C D Encrypted: {bcd}\n")
ahash = hashlib.sha256()
ahash.update(bcd)
a = ahash.digest()
print(f"Parts A Hash: {a}\n")
2024-05-15 08:39:15 +08:00
print(f"Data to write: {a + bcd}\n")
2024-04-24 17:51:21 +08:00
# read a list of lines into data
data = datadocs.readlines()
# now change the answer line, note that you have to add a newline
data[qn] = a + bcd
# and write everything back
datadocs.writelines(data)
datadocs.close()
datadocs = open(f"{filename}.txt", "r+")
n = datadocs.readline()
sha256.update(n)
2024-05-15 08:39:15 +08:00
while (True): #calculate hash
2024-04-24 17:51:21 +08:00
temp = data.readline()
2024-05-15 08:39:15 +08:00
if (temp == "chk"):
2024-04-24 17:51:21 +08:00
sha256.update(temp)
targethash = data.readline()
break
sha256.update(temp)
2024-05-15 08:39:15 +08:00
2024-04-24 17:51:21 +08:00
print(f"New hash generated: {targethash}\n")
# read a list of lines into data
data = datadocs.readlines()
# now change the answer line, note that you have to add a newline
2024-05-15 08:39:15 +08:00
data[1 + n] = targethash
2024-04-24 17:51:21 +08:00
# and write everything back
datadocs.writelines(data)
datadocs.close()
return 0
2024-05-14 08:40:21 +08:00
def readanswer(qn):
if (self.username == ""):
2024-05-14 08:40:21 +08:00
print(f"Username not set!\n")
return 1
md5 = hashlib.md5()
md5.update(self.username)
2024-05-14 08:40:21 +08:00
filename = md5.digest()
print(f"MD5 hash of {user}: {filename}")
2024-05-15 08:39:15 +08:00
2024-05-14 08:40:21 +08:00
sha256 = hashlib.sha256()
datadocs = open(f"{filename}.txt", "r")
n = datadocs.readline()
sha256.update(n)
2024-05-15 08:39:15 +08:00
while (True): #hash check
2024-05-14 08:40:21 +08:00
temp = data.readline()
2024-05-15 08:39:15 +08:00
if (temp == "chk"):
2024-05-14 08:40:21 +08:00
sha256.update(temp)
2024-05-15 08:39:15 +08:00
rhash = sha256.digest()
2024-05-14 08:40:21 +08:00
ehash = data.readline()
2024-05-15 08:39:15 +08:00
if (rhash == ehash):
2024-05-14 08:40:21 +08:00
print(f"Hashes match: {rhash}\n")
break
else:
2024-05-15 08:39:15 +08:00
print(
f"Hashes does not match !\nExpected: {ehash}\nGot: {rhash}\n"
)
2024-05-14 08:40:21 +08:00
return 1
sha256.update(temp)
datadocs.close()
datadocs = open(f"{filename}.txt", "r")
contents = datadocs.readlines()
line = contents[qn]
2024-05-15 08:39:15 +08:00
s1hash = line[0:63] #hash of stage 1
s1data = line[64:] #data after hash
2024-05-14 08:40:21 +08:00
s1h = hashlib.sha256()
2024-05-15 08:39:15 +08:00
s1h.update(s1data) #update hash
2024-05-14 08:40:21 +08:00
print(f"Stage 1 integrity check\n")
2024-05-15 08:39:15 +08:00
if (s1hash == s1h.digest()):
2024-05-14 08:40:21 +08:00
print(f"Hashes match: {s1hash}\n")
else:
2024-05-15 08:39:15 +08:00
print(
f"Hashes does not match !\nExpected: {s1h.digest()}\nGot: {s1hash}\n"
)
2024-05-14 08:40:21 +08:00
return 1
userhash = hashlib.sha256()
userhash.update(self.username)
2024-05-15 08:39:15 +08:00
key = userhash.digest() #generated key for decryption
2024-05-14 08:40:21 +08:00
print(f"Key generated: {key}\n")
2024-05-15 08:39:15 +08:00
s2 = AESCipher(key).decrypt(s1data) #decrypt
2024-05-14 08:40:21 +08:00
print(f"Decrypted data: {s2}\n")
2024-05-15 08:39:15 +08:00
s2hash = s2[0:63] #hash of stage 2
s2data = s2[64:] #data after hash
2024-05-14 08:40:21 +08:00
s2h = hashlib.sha256()
2024-05-15 08:39:15 +08:00
s2h.update(s2data) #update hash
2024-05-14 08:40:21 +08:00
print(f"Stage 2 integrity check\n")
2024-05-15 08:39:15 +08:00
if (s2hash == s2h.digest()):
2024-05-14 08:40:21 +08:00
print(f"Hashes match: {s2hash}\n")
else:
2024-05-15 08:39:15 +08:00
print(
f"Hashes does not match !\nExpected: {s2h.digest()}\nGot: {s2hash}\n"
)
2024-05-14 08:40:21 +08:00
return 1
timestamp = int(s2data[0:15], 16)
print(f"Detected timestamp: {timestamp}")
print(f"Found answer: {s2data[16:]}")
return s2data[16:]