Compare commits

..

No commits in common. "c85c108db5b389afdc8a0269a5d1f0bf6719c281" and "a00550e0b60f5d8283d09e359c6a5e339994f0d4" have entirely different histories.

14 changed files with 121 additions and 158 deletions

5
.gitignore vendored
View File

@ -1 +1,6 @@
data/decrypted/group_files/*
data/decrypted/user_files/*
data/encrypted/group_files/*
data/encrypted/user_files/*
accumulated.json*
__pycache__ __pycache__

View File

@ -18,12 +18,13 @@ echo2 foxtrott
asfdasd@sdskjd.de asfdasd@sdskjd.de
street in strasdlasöd street in strasdlasöd
END_OF_INPUTS END_OF_INPUTS
python scripts/main.py --mode decrypt --master-password "ewrwerwerew" python scripts/main.py --mode decrypt --master-password "ewrwerwerew" &&
python scripts/main.py --mode decrypt --user "1"
python scripts/main.py --mode cleanup --file-types decrypted && python scripts/main.py --mode decrypt --user "1" --user-password "DDB2QYHP4X0PDR0ZX9LBLACNL6VAXLXMNEZJDOOGUTENSI6UDYGPOR5CV01YLI49" << END_OF_INPUTS python scripts/main.py --mode cleanup --file-types decrypted && python scripts/main.py --mode decrypt --user "1" --user-password "O3ITMWXZED9FKYQ0PB2WNVRWSCSCYVXCD00PJ6GQ4MFPIUWBVDCYSSSX9ZDBW5QU" << END_OF_INPUTS
2 2
EOQXCYGEY2IMKAJP5VOCRVRH9LPYAPK9IC0ID0GMSJ5KXNXJHPNUBUKEVLE2WHQJ YGC6FLI5FIFL4WV4JPZZI7RVOZTWLROCLY4HVGDMWWSTAIQJTLUQK1VBBY0E24PN
END_OF_INPUTS END_OF_INPUTS
``` ```
# Requirements to know # Requirements to know
@ -38,16 +39,14 @@ END_OF_INPUTS
```bash ```bash
pip install numpy pip install numpy
gpg gpg
ecryptfs-utils
ecryptfs-simple
python python
pip pip
``` ```
## todo ## todo
- implement tails setup script - implement tails setup script
- add data-input attribut - implement relativ call
- add data-output attribut - implement tmp mount for decrypted files
## Further Information ## Further Information
- https://www.tutorialspoint.com/python/python_command_line_arguments.htm - https://www.tutorialspoint.com/python/python_command_line_arguments.htm
@ -56,4 +55,3 @@ END_OF_INPUTS
- https://pynative.com/python-generate-random-string/ - https://pynative.com/python-generate-random-string/
- https://www.studimup.de/abitur/stochastik/anzahl-der-m%C3%B6glichketen-berechnen-kombinatorik/ - https://www.studimup.de/abitur/stochastik/anzahl-der-m%C3%B6glichketen-berechnen-kombinatorik/
- https://numpy.org/doc/stable/reference/generated/numpy.base_repr.html?highlight=base_repr#numpy.base_repr - https://numpy.org/doc/stable/reference/generated/numpy.base_repr.html?highlight=base_repr#numpy.base_repr
- https://linuxconfig.org/how-to-create-compressed-encrypted-archives-with-tar-and-gpg

2
data/.gitignore vendored
View File

@ -1,2 +0,0 @@
*.gpg
*.txt

View File

@ -1,3 +0,0 @@
main_data/*
*.json
*.txt

View File

@ -1 +0,0 @@
*.txt

View File

@ -1 +0,0 @@
*.json

View File

@ -1 +0,0 @@
*.gpg

View File

@ -1 +0,0 @@
*.gpg

View File

@ -0,0 +1,45 @@
from .Cli import Cli
class AbstractSplittedSecret(Cli):
USER_PASSWORD_LENGTHS = 64
OVERALL_PASSWORD_LENGTHS = 128
# At the moment the programm can used deal with one digit numbers.
MAXIMUM_SECRET_HOLDERS = 9
MINIMUM_SECRET_HOLDERS = 2
TYPE_ENCRYPTED="encrypted"
TYPE_DECRYPTED="decrypted"
def __init__(self):
super(Cli, self).__init__()
self.data_folder = "data/"
def getCoSecretHoldersRange():
return range(AbstractSplittedSecret.MINIMUM_SECRET_HOLDERS,AbstractSplittedSecret.MAXIMUM_SECRET_HOLDERS)
def getSecretHoldersRange():
return range(1,AbstractSplittedSecret.MAXIMUM_SECRET_HOLDERS)
def getFolderPath(self,folder_type):
return self.data_folder + folder_type + "/"
def getGroupFilesFolderPath(self,folder_type):
return self.getFolderPath(folder_type) + "group_files/"
def getUserFilesFolderPath(self,folder_type):
return self.getFolderPath(folder_type) + "user_files/"
def getFileExtension(self,file_type):
if file_type == AbstractSplittedSecret.TYPE_ENCRYPTED:
return '.gpg'
return ''
def getUserFilePath(self,user_id,file_type):
return self.getUserFilesFolderPath(file_type)+user_id+'.json' + self.getFileExtension(file_type);
def getGroupFilePath(self,group_id,file_type):
return self.getGroupFilesFolderPath(file_type) + str(group_id) + '.txt' + self.getFileExtension(file_type);
def getAccumulatedFilePath(self,file_type):
return self.getFolderPath(file_type) + 'accumulated.json' + self.getFileExtension(file_type);

View File

@ -1,25 +1,20 @@
from .Paths import Paths from .AbstractSplittedSecret import AbstractSplittedSecret
class Cleanup(AbstractSplittedSecret):
class Cleanup(): def __init__(self):
def __init__(self,cli,paths): super(Cleanup, self).__init__()
self.cli = cli
self.paths = paths
def getAllFilePaths(self,file_type): def getAllFilePaths(self,file_type):
all_file_paths = [ return [
self.paths.getGroupFilesFolderPath(file_type), self.getGroupFilesFolderPath(file_type),
self.paths.getUserFilesFolderPath(file_type), self.getUserFilesFolderPath(file_type),
self.paths.getAccumulatedFilePath(file_type) self.getAccumulatedFilePath(file_type)
] ]
if file_type == Paths.TYPE_DECRYPTED:
all_file_paths.append(self.paths.getDecryptedMainDataStandartFolder())
return all_file_paths
def deleteAllFilesInFolder(self,folder_path): def deleteAllFilesInFolder(self,folder_path):
try: try:
self.cli.executeCommand('rm -r ' + folder_path + '*') self.executeCommand('rm -v ' + folder_path + '*')
except Exception as error: except:
print(error) pass
def cleanupFiles(self,file_type): def cleanupFiles(self,file_type):
for folder_path in self.getAllFilePaths(file_type): for folder_path in self.getAllFilePaths(file_type):
@ -27,11 +22,11 @@ class Cleanup():
def cleanupForUser(self,user): def cleanupForUser(self,user):
try: try:
self.cli.executeCommand('find "' + self.paths.getDataFolderPath(Paths.TYPE_ENCRYPTED) + '" -not -name "*' + str(user) +'*" -type f -print | xargs rm -v') self.executeCommand('find "' + self.getFolderPath(AbstractSplittedSecret.TYPE_ENCRYPTED) + '" -not -name "*' + str(user) +'*" -type f -print | xargs rm -v')
except Exception as error: except:
print(error) pass
self.cleanupFiles(Paths.TYPE_DECRYPTED) self.cleanupFiles(AbstractSplittedSecret.TYPE_DECRYPTED)
def deleteAll(self): def deleteAll(self):
self.cleanupFiles(Paths.TYPE_ENCRYPTED) self.cleanupFiles(AbstractSplittedSecret.TYPE_ENCRYPTED)
self.cleanupFiles(Paths.TYPE_DECRYPTED) self.cleanupFiles(AbstractSplittedSecret.TYPE_DECRYPTED)

View File

@ -1,17 +1,16 @@
from .AbstractSplittedSecret import AbstractSplittedSecret
import json import json
from pathlib import Path from pathlib import Path
class Decryption(AbstractSplittedSecret):
class Decryption(): def __init__(self):
def __init__(self,cli,paths):
self.user_id='0'; self.user_id='0';
self.user_password='' self.user_password=''
self.cli = cli super(Decryption, self).__init__()
self.paths = paths
def initializeUser(self,user_id): def initializeUser(self,user_id):
self.user_id=str(user_id) self.user_id=str(user_id)
self.user_file_decrypted_path = self.paths.getUserFilePath(self.user_id,self.paths.TYPE_DECRYPTED) self.user_file_decrypted_path = self.getUserFilePath(self.user_id,AbstractSplittedSecret.TYPE_DECRYPTED)
def initializeUserDataDecryption(self): def initializeUserDataDecryption(self):
self.decryptUserFile() self.decryptUserFile()
@ -21,9 +20,9 @@ class Decryption():
def initializeGroupDataEncryption(self): def initializeGroupDataEncryption(self):
self.group_name = self.getDecryptersGroupName() self.group_name = self.getDecryptersGroupName()
self.encrypted_group_file_path = self.paths.getGroupFilePath(self.group_name, self.paths.TYPE_DECRYPTED) self.encrypted_group_file_path = self.getGroupFilePath(self.group_name, AbstractSplittedSecret.TYPE_DECRYPTED)
self.decryptGroupFile() self.decryptGroupFile()
self.master_password = self.loadTxtFile(self.encrypted_group_file_path).strip() self.master_password = self.loadTxtFile(self.encrypted_group_file_path)
def initializeNeededDecryptersAmount(self): def initializeNeededDecryptersAmount(self):
self.needed_decrypters_amount = len(str(list(self.user_data['groups'].keys())[0])) self.needed_decrypters_amount = len(str(list(self.user_data['groups'].keys())[0]))
@ -98,20 +97,17 @@ class Decryption():
return data return data
def decryptFile(self,password,input_file_path,output_file_path): def decryptFile(self,password,input_file_path,output_file_path):
self.cli.executeCommand('gpg --batch --passphrase "'+ password + '" -o "' + output_file_path +'" "'+ input_file_path+'"') self.executeCommand('gpg --batch --passphrase "'+ password + '" -o "' + output_file_path +'" "'+ input_file_path+'"')
def decryptUserFile(self): def decryptUserFile(self):
input_file_path = self.paths.getUserFilePath(self.user_id,self.paths.TYPE_ENCRYPTED) input_file_path = self.getUserFilePath(self.user_id,AbstractSplittedSecret.TYPE_ENCRYPTED)
self.decryptFile(self.user_password, input_file_path, self.user_file_decrypted_path) self.decryptFile(self.user_password, input_file_path, self.user_file_decrypted_path)
def decryptGroupFile(self): def decryptGroupFile(self):
input_file_path = self.paths.getGroupFilePath(self.group_name, self.paths.TYPE_ENCRYPTED) input_file_path = self.getGroupFilePath(self.group_name, AbstractSplittedSecret.TYPE_ENCRYPTED)
self.decryptFile(self.getGroupPassword(), input_file_path, self.encrypted_group_file_path) self.decryptFile(self.getGroupPassword(), input_file_path, self.encrypted_group_file_path)
def decryptAccumulatedFile(self): def decryptAccumulatedFile(self):
input_file_path = self.paths.getAccumulatedFilePath(self.paths.TYPE_ENCRYPTED) input_file_path = self.getAccumulatedFilePath(AbstractSplittedSecret.TYPE_ENCRYPTED)
output_file_path = self.paths.getAccumulatedFilePath(self.paths.TYPE_DECRYPTED) output_file_path = self.getAccumulatedFilePath(AbstractSplittedSecret.TYPE_DECRYPTED)
self.decryptFile(self.user_password, input_file_path, output_file_path) self.decryptFile(self.user_password, input_file_path, output_file_path)
def decryptMainData(self):
self.cli.executeCommand('gpg --batch --passphrase "' + self.getMasterPassword() + '" -d "' + self.paths.getEncryptedMainDataFile() + '" | tar -xvzf - "' + self.paths.getDecryptedMainDataStandartFolder() + '"')

View File

@ -4,18 +4,12 @@ import math
import numpy import numpy
import re import re
import json import json
from .Paths import Paths from .AbstractSplittedSecret import AbstractSplittedSecret
class Encryption(): class Encryption(AbstractSplittedSecret):
USER_PASSWORD_LENGTHS = 64 def __init__(self, amount_of_secret_holders, decryption_quota,master_password):
OVERALL_PASSWORD_LENGTHS = 128 super(Encryption, self).__init__()
# At the moment the programm can only deal with one digit numbers.
MAXIMUM_SECRET_HOLDERS = 9
MINIMUM_SECRET_HOLDERS = 2
def __init__(self, cli, paths, amount_of_secret_holders, decryption_quota,master_password):
self.amount_of_secret_holders = amount_of_secret_holders self.amount_of_secret_holders = amount_of_secret_holders
self.decryption_quota = decryption_quota self.decryption_quota = decryption_quota
self.master_password = master_password self.master_password = master_password
@ -23,8 +17,6 @@ class Encryption():
self.group_members_amount=math.ceil(self.amount_of_secret_holders * self.quota_factor) self.group_members_amount=math.ceil(self.amount_of_secret_holders * self.quota_factor)
self.initializeUserData() self.initializeUserData()
self.initializeGroupData() self.initializeGroupData()
self.cli = cli
self.paths = paths
def initializeUserData(self): def initializeUserData(self):
self.user_mapped_data = {} self.user_mapped_data = {}
@ -39,12 +31,6 @@ class Encryption():
def addInformationToUser(self,user_id,label,content): def addInformationToUser(self,user_id,label,content):
self.user_mapped_data[user_id]['about'][label] = content; self.user_mapped_data[user_id]['about'][label] = content;
def getCoSecretHoldersRange():
return range(Encryption.MINIMUM_SECRET_HOLDERS,Encryption.MAXIMUM_SECRET_HOLDERS)
def getSecretHoldersRange():
return range(1,Encryption.MAXIMUM_SECRET_HOLDERS)
def getStartnumber(self): def getStartnumber(self):
index = 0 index = 0
start_number = '' start_number = ''
@ -104,33 +90,29 @@ class Encryption():
index += 1 index += 1
def encryptStringToFile(self,text,output_file,password): def encryptStringToFile(self,text,output_file,password):
self.cli.executeCommand('echo \'' + text + '\' | gpg --symmetric --armor --batch --passphrase "' + password + '" -o "' + output_file + '"') self.executeCommand('echo \'' + text + '\' | gpg --symmetric --armor --batch --passphrase "' + password + '" -o "' + output_file + '"')
def encryptGroupFiles(self): def encryptGroupFiles(self):
for password_group_index_int in self.group_mapped_data: for password_group_index_int in self.group_mapped_data:
encrypted_group_password_file_path = self.paths.getGroupFilePath(password_group_index_int,Paths.TYPE_ENCRYPTED) encrypted_group_password_file_path = self.getGroupFilePath(password_group_index_int,AbstractSplittedSecret.TYPE_ENCRYPTED)
self.encryptStringToFile(self.master_password,encrypted_group_password_file_path,self.group_mapped_data[password_group_index_int]['password']) self.encryptStringToFile(self.master_password,encrypted_group_password_file_path,self.group_mapped_data[password_group_index_int]['password'])
def encryptToJsonFile(self,data,file_path,password): def encryptToJsonFile(self,data,file_path,password):
self.encryptStringToFile(json.dumps(data,ensure_ascii=False), file_path, password) self.encryptStringToFile(json.dumps(data,ensure_ascii=False), file_path, password)
def encryptUserFile(self): def encryptUserData(self):
for user_id in self.user_mapped_data: for user_id in self.user_mapped_data:
file_path=self.paths.getUserFilePath(user_id,Paths.TYPE_ENCRYPTED) file_path=self.getUserFilePath(user_id,AbstractSplittedSecret.TYPE_ENCRYPTED)
data=self.user_mapped_data[user_id] data=self.user_mapped_data[user_id]
password=self.user_mapped_data[user_id]['user_password'] password=self.user_mapped_data[user_id]['user_password']
self.encryptToJsonFile(data,file_path,password) self.encryptToJsonFile(data,file_path,password)
def encryptAccumulatedFile(self): def encryptAccumulatedData(self):
file_path=self.paths.getAccumulatedFilePath(Paths.TYPE_ENCRYPTED) file_path=self.getAccumulatedFilePath(AbstractSplittedSecret.TYPE_ENCRYPTED)
data={"user_mapped": self.user_mapped_data, "group_mapped": self.group_mapped_data} data={"user_mapped": self.user_mapped_data, "group_mapped": self.group_mapped_data}
self.encryptToJsonFile(data,file_path,self.master_password) self.encryptToJsonFile(data,file_path,self.master_password)
def encryptMainData(self): def encrypt(self):
self.cli.executeCommand('tar -cvzf - "' + self.paths.getDecryptedMainDataStandartFolder() + '" | gpg -c --batch --passphrase "' + self.master_password +'" > "' + self.paths.getEncryptedMainDataFile() + '"'); self.encryptUserData()
self.encryptAccumulatedData()
def encryptAll(self):
self.encryptUserFile()
self.encryptAccumulatedFile()
self.encryptGroupFiles() self.encryptGroupFiles()
self.encryptMainData()

View File

@ -1,40 +0,0 @@
import os
class Paths():
TYPE_ENCRYPTED="encrypted"
TYPE_DECRYPTED="decrypted"
ROOT_PATH= os.path.join(os.path.dirname(os.path.abspath(__file__)),"../","../")
def __init__(self):
self.data_folder = os.path.join(self.ROOT_PATH,"data") + '/'
def getDataFolderPath(self,folder_type):
return self.data_folder + folder_type + "/"
def getGroupFilesFolderPath(self,folder_type):
return self.getDataFolderPath(folder_type) + "group_files/"
def getUserFilesFolderPath(self,folder_type):
return self.getDataFolderPath(folder_type) + "user_files/"
def getEncryptedMainDataFile(self):
return self.getDataFolderPath(Paths.TYPE_ENCRYPTED) + "main_data.tar.gz.gpg"
def getDecryptedMainDataStandartFolder(self):
return self.getDataFolderPath(Paths.TYPE_DECRYPTED) + "main_data/"
def getFileExtension(self,file_type):
if file_type == Paths.TYPE_ENCRYPTED:
return '.gpg'
return ''
def getUserFilePath(self,user_id,file_type):
return self.getUserFilesFolderPath(file_type)+user_id+'.json' + self.getFileExtension(file_type);
def getGroupFilePath(self,group_id,file_type):
return self.getGroupFilesFolderPath(file_type) + str(group_id) + '.txt' + self.getFileExtension(file_type);
def getAccumulatedFilePath(self,file_type):
return self.getDataFolderPath(file_type) + 'accumulated.json' + self.getFileExtension(file_type);

View File

@ -3,28 +3,23 @@ from classes.Encryption import Encryption
from classes.Cleanup import Cleanup from classes.Cleanup import Cleanup
from classes.Decryption import Decryption from classes.Decryption import Decryption
from getpass import getpass from getpass import getpass
from classes.AbstractSplittedSecret import AbstractSplittedSecret
import traceback import traceback
from classes.Cli import Cli
from classes.Paths import Paths
cli = Cli() cleanup = Cleanup()
paths = Paths()
cleanup = Cleanup(cli,paths)
def clean_exit(): def clean_exit():
print("Cleaning up.") print("Cleaning up.")
try: try:
cleanup.cleanupFiles(Paths.TYPE_DECRYPTED) cleanup.cleanupFiles(AbstractSplittedSecret.TYPE_DECRYPTED)
except: except:
pass pass
standard_exit() print("Leaving program.")
exit()
def dirty_exit(): def dirty_exit():
print("ATTENTION: SECURITY RISK !!!\nPROGRAM DIDN'T CLEAN UP DECRYPTED DATA. \nDECRYPTED DATA EXISTS AND CAN BE READ BY EVERYBODY!") print("ATTENTION: SECURITY RISK !!!\nPROGRAM DIDN'T CLEAN UP DECRYPTED DATA. \nDECRYPTED DATA EXISTS AND CAN BE READ BY EVERYBODY!")
print("TO REMOVE DECRYPTED DATA EXECUTE:\nmain.py --mode cleanup --file-types " + Paths.TYPE_DECRYPTED) print("TO REMOVE DECRYPTED DATA EXECUTE:\nmain.py --mode cleanup --file-types " + AbstractSplittedSecret.TYPE_DECRYPTED)
standard_exit()
def standard_exit():
print("Leaving program.") print("Leaving program.")
exit() exit()
@ -32,12 +27,12 @@ try:
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--mode',type=str, dest='mode',required=True,choices=['cleanup','encrypt','decrypt']) parser.add_argument('--mode',type=str, dest='mode',required=True,choices=['cleanup','encrypt','decrypt'])
parser.add_argument('--file-types',type=str, dest='file_types',required=False,choices=[Paths.TYPE_DECRYPTED, Paths.TYPE_ENCRYPTED]) parser.add_argument('--file-types',type=str, dest='file_types',required=False,choices=[AbstractSplittedSecret.TYPE_DECRYPTED, AbstractSplittedSecret.TYPE_ENCRYPTED])
parser.add_argument('--amount',type=int, dest='amount_of_secret_holders',required=False,choices=Encryption.getCoSecretHoldersRange()) parser.add_argument('--amount',type=int, dest='amount_of_secret_holders',required=False,choices=AbstractSplittedSecret.getCoSecretHoldersRange())
parser.add_argument('--quota', type=int, dest='decryption_quota', choices=range(1,101),required=False) parser.add_argument('--quota', type=int, dest='decryption_quota', choices=range(1,101),required=False)
parser.add_argument('--master-password',type=str, dest='master_password',required=False) parser.add_argument('--master-password',type=str, dest='master_password',required=False)
parser.add_argument('--user-password',type=str, dest='user_password',required=False) parser.add_argument('--user-password',type=str, dest='user_password',required=False)
parser.add_argument('--user',type=int, dest='user',choices=Encryption.getSecretHoldersRange(),required=False) parser.add_argument('--user',type=int, dest='user',choices=AbstractSplittedSecret.getSecretHoldersRange(),required=False)
parser.add_argument('--add-user-information',type=bool, dest='add_user_information', default=False, required=False, action=argparse.BooleanOptionalAction) parser.add_argument('--add-user-information',type=bool, dest='add_user_information', default=False, required=False, action=argparse.BooleanOptionalAction)
args = parser.parse_args() args = parser.parse_args()
@ -50,16 +45,16 @@ try:
if args.user is None: if args.user is None:
print("Deleting all encrypted and decrypted files.") print("Deleting all encrypted and decrypted files.")
cleanup.deleteAll() cleanup.deleteAll()
standard_exit() clean_exit()
print("Deleting all files which aren't related to user: " + str(args.user)); print("Deleting all files which aren't related to user: " + str(args.user));
cleanup.cleanupForUser(args.user) cleanup.cleanupForUser(args.user)
standard_exit() clean_exit()
print("Deleting all " + args.file_types + " files.") print("Deleting all " + args.file_types + " files.")
cleanup.cleanupFiles(args.file_types) cleanup.cleanupFiles(args.file_types)
standard_exit() clean_exit()
if args.mode == 'decrypt': if args.mode == 'decrypt':
decrypt = Decryption(cli,paths) decrypt = Decryption()
if args.master_password is None: if args.master_password is None:
if args.user is None: if args.user is None:
print("Type in the user id:") print("Type in the user id:")
@ -125,14 +120,11 @@ try:
break; break;
except: except:
print("An unexpected error occured: \n" + traceback.format_exc()) print("An unexpected error occured: \n" + traceback.format_exc())
print("Decrypting main data.")
decrypt.decryptMainData()
print("All data decrypted.")
dirty_exit() dirty_exit()
print("Decrypting accumulated data.") print("Decrypting accumulated file...")
decrypt.setUserPassword(args.master_password) decrypt.setUserPassword(args.master_password)
decrypt.decryptAccumulatedFile() decrypt.decryptAccumulatedFile()
dirty_exit() clean_exit()
if args.mode == 'encrypt': if args.mode == 'encrypt':
if args.master_password is None: if args.master_password is None:
@ -140,16 +132,15 @@ try:
master_password = getpass() master_password = getpass()
else: else:
master_password = args.master_password master_password = args.master_password
encrypt = Encryption(cli,paths,args.amount_of_secret_holders, args.decryption_quota, master_password) encrypt = Encryption(args.amount_of_secret_holders, args.decryption_quota, master_password)
if args.add_user_information is not None: if args.add_user_information is not None:
for user_id in encrypt.user_mapped_data: for user_id in encrypt.user_mapped_data:
for label in ['name','phone','email','address']: for label in ['name','phone','email','address']:
print("Enter attribut <<" + label + ">> for user <<" + user_id+ ">>:" ) print("Enter attribut <<" + label + ">> for user <<" + user_id+ ">>:" )
encrypt.addInformationToUser(user_id, label, str(input())) encrypt.addInformationToUser(user_id, label, str(input()))
encrypt.compileData() encrypt.compileData()
encrypt.encryptAll() encrypt.encrypt()
clean_exit()
dirty_exit()
except KeyboardInterrupt: except KeyboardInterrupt:
print("Program interrupted by user.") print("Program interrupted by user.")
clean_exit() clean_exit()