"template": "default_prescription",
"preset_directory": "preset",
"preset_newline": "True",
- "preset_delimiter": ","
+ "preset_delimiter": ",",
+ "private_key": "",
+ "certificate": ""
}
with open(config_file) as conf:
"template": "default",
"preset_directory": "preset",
"preset_newline": "True",
- "preset_delimiter": ","
+ "preset_delimiter": ",",
+ "certificate": "",
+ "private_key": ""
}
import os, shutil, glob, tempfile, json
from zipfile import ZipFile
from config import config
+from signature import Signature
class FileHandler():
self.file=file
with ZipFile(self.file, "r", strict_timestamps=False) as source:
source.extractall(self.directory.name)
+
+ #def hash(self):
+ # allfiles=[]
+ # allhash=""
+ # #with open(os.path.join(self.directory.name, "prescription.json"), "rb") as f:
+ # # print(sha256(f.read()).hexdigest())
+ # for root, dirs, files in os.walk(self.directory.name):
+ # for file in files:
+ # allfiles.append(os.path.join(root, file))
+ # try:
+ # allfiles.remove(os.path.join(self.directory.name, "certificate.pem"))
+ # allfiles.remove(os.path.join(self.directory.name, "signature.p7m"))
+ # except ValueError as e:
+ # pass
+ # for file in allfiles:
+ # with open(file, "rb") as f:
+ # allhash=allhash+sha256(f.read()).hexdigest()
+ # return(allhash)
+
+ def sign(self):
+ with open(os.path.join(self.directory.name, "prescription.json"), "r") as file:
+ data=file.read()
+ signature=Signature.sign(data, certificate=config["certificate"], privkey=config["private_key"])
+ with open(os.path.join(self.directory.name, "signature.p7m"), "w") as file:
+ file.write(signature)
+ shutil.copyfile(config["certificate"], os.path.join(self.directory.name, "certificate.pem"))
+
+ def verify(self):
+ with open(os.path.join(self.directory.name, "prescription.json"), "r") as file:
+ data=file.read()
+ try:
+ with open(os.path.join(self.directory.name, "certificate.pem")) as file:
+ certificate=file.read()
+ with open(os.path.join(self.directory.name, "signature.p7m")) as file:
+ signature=file.read()
+ return Signature.verify(data, certificate=os.path.join(self.directory.name, "certificate.pem"), signature=os.path.join(self.directory.name, "signature.p7m"))
+ except FileNotFoundError as e:
+ print(e)
def write_to(self, file):
with open(file, "w") as f:
+ del self.file
f.write(self.get_json())
self.file=file
--- /dev/null
+# MedScript
+# Copyright (C) 2023 Dr. Agnibho Mondal
+# This file is part of MedScript.
+# MedScript is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+# MedScript is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License along with MedScript. If not, see <https://www.gnu.org/licenses/>.
+
+from M2Crypto import BIO, Rand, SMIME, X509
+from config import config
+from hashlib import sha256
+
+class Signature():
+
+ def sign(data, certificate, privkey):
+ try:
+ hash=sha256(data.encode()).hexdigest()
+ smime=SMIME.SMIME()
+ smime.load_key(privkey, certificate)
+ p7=smime.sign(BIO.MemoryBuffer(hash.encode()), SMIME.PKCS7_DETACHED)
+ out=BIO.MemoryBuffer()
+ smime.write(out, p7)
+ return(out.read().decode())
+ except Exception as e:
+ print(e)
+ return None
+
+ def verify(data, certificate, signature):
+ hash=sha256(data.encode()).hexdigest()
+ smime=SMIME.SMIME()
+
+ x509=X509.load_cert(certificate)
+ sk=X509.X509_Stack()
+ sk.push(x509)
+ smime.set_x509_stack(sk)
+
+ st=X509.X509_Store()
+ st.load_info(certificate)
+ smime.set_x509_store(st)
+
+ with open(signature) as file:
+ buf=BIO.MemoryBuffer(file.read().encode())
+ p7=SMIME.smime_load_pkcs7_bio(buf)[0]
+
+ try:
+ v=smime.verify(p7, BIO.MemoryBuffer(hash.encode()))
+ return(x509.get_subject().as_text())
+ except SMIME.PKCS7_Error as e:
+ print(e)
+ return False
self.signal_view.emit(target)
self.renderbox.showMaximized()
else:
- QMessageBox.information(self,"Save first", "Please save the file before rendering.")
+ QMessageBox.information(self, "Save first", "Please save the file before rendering.")
+
+ def cmd_sign(self):
+ self.update_instance()
+ if(self.save_state==md5(self.prescription.get_json().encode()).hexdigest()):
+ try:
+ self.current_file.sign()
+ self.cmd_save()
+ except FileNotFoundError as e:
+ print(e)
+ QMessageBox.information(self, "Save first", "Please save the file before signing.")
+ except TypeError as e:
+ print(e)
+ QMessageBox.information(self, "Configure", "Please add valid key and certificate to the config file.")
+ except Exception as e:
+ print(e)
+ QMessageBox.information(self, "Failed", "Failed to sign.")
+ else:
+ QMessageBox.information(self, "Save first", "Please save the file before signing.")
+
+ def cmd_verify(self):
+ try:
+ result=self.current_file.verify()
+ if result is False:
+ QMessageBox.critical(self, "Verification failed", "Signature is invalid.")
+ elif result is None:
+ QMessageBox.warning(self, "No Siganture", "No signature was found.")
+ else:
+ print(result)
+ QMessageBox.information(self, "Valid signature", "Valid signature found with the following information:\n"+result)
+ except FileNotFoundError as e:
+ print(e)
+ QMessageBox.warning(self, "No Siganture", "No signature was found.")
+ except Exception as e:
+ print(e)
+ QMessageBox.warning(self, "Failed", "Failed to verify.")
def cmd_prescriber(self):
self.edit_prescriber.show()
action_render2=QAction(icon_render, "Render", self)
action_render.triggered.connect(self.cmd_render)
action_render2.triggered.connect(self.cmd_render)
+ action_sign=QAction("Sign", self)
+ action_sign.triggered.connect(self.cmd_sign)
+ action_verify=QAction("Verify", self)
+ action_verify.triggered.connect(self.cmd_verify)
action_prescriber=QAction("Prescriber", self)
action_prescriber.triggered.connect(self.cmd_prescriber)
action_switch=QAction("Switch", self)
menu_file.addAction(action_quit)
menu_prepare=menubar.addMenu("Prepare")
menu_prepare.addAction(action_render)
+ menu_prepare.addAction(action_sign)
+ menu_prepare.addAction(action_verify)
menu_prepare.addAction(action_refresh)
menu_prepare.addAction(action_prescriber)
menu_prepare.addAction(action_switch)