Compare commits

...

10 Commits

7 changed files with 220 additions and 76 deletions

View File

@ -1,6 +1,30 @@
# Splitted Secret # Splitted Secret
The purpose of this software is to splitt a secret over multiple people. Just if a defined amount of this people meet together they can encrypt the secret and have access to it. The purpose of this software is to splitt a secret over multiple people. Just if a defined amount of this people meet together they can encrypt the secret and have access to it.
# testing
```bash
python scripts/main.py --mode cleanup &&
python scripts/main.py --amount 3 --quota 50 --mode encrypt --add-user-information --master-password "ewrwerwerew" << END_OF_INPUTS
alpha bravo
123123812908
asfdasd@asdskjd.de
street in straat
charlie delta
1888888
sadasfdasd@asdskjd.de
street in strutt
echo2 foxtrott
99999999
asfdasd@sdskjd.de
street in strasdlasöd
END_OF_INPUTS
python scripts/main.py --mode decrypt --master-password "ewrwerwerew" &&
python scripts/main.py --mode decrypt --user "1"
python scripts/main.py --mode cleanup --user "1" && python scripts/main.py --mode decrypt --user "1" --user-password "O3ITMWXZED9FKYQ0PB2WNVRWSCSCYVXCD00PJ6GQ4MFPIUWBVDCYSSSX9ZDBW5QU"
```
# Requirements to know # Requirements to know
- Amount of People - Amount of People
- How much people need to reunite for decrypting - How much people need to reunite for decrypting
@ -12,6 +36,9 @@ The purpose of this software is to splitt a secret over multiple people. Just if
# setup # setup
```bash ```bash
pip install numpy pip install numpy
gpg
python
pip
``` ```
## Further Information ## Further Information

View File

@ -1,11 +1,30 @@
from .Cli import Cli from .Cli import Cli
class AbstractSplittedSecret(Cli): class AbstractSplittedSecret(Cli):
def __init__(self): def __init__(self):
super(Cli, self).__init__() super(Cli, self).__init__()
self.encrypted_folder="data/encrypted/" self.data_folder = "data/"
self.decrypted_folder="data/encrypted/"
self.encrypted_group_files_folder = self.encrypted_folder + "group_files/" def getFolderPath(self,folder_type):
self.decrypted_group_files_folder = self.decrypted_folder + "group_files/" return self.data_folder + folder_type + "/"
self.encrypted_user_files_folder = self.encrypted_folder + "user_files/"
self.decrypted_user_files_folder = self.encrypted_folder + "user_files/" 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 == "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,26 +1,37 @@
from .AbstractSplittedSecret import AbstractSplittedSecret from .AbstractSplittedSecret import AbstractSplittedSecret
class Cleanup(AbstractSplittedSecret): class Cleanup(AbstractSplittedSecret):
def __init__(self): def __init__(self):
super(Cleanup, self).__init__() super(Cleanup, self).__init__()
self.encrypted_files_folders = [self.decrypted_group_files_folder,self.decrypted_user_files_folder]
self.decrypted_files_folders = [self.encrypted_group_files_folder,self.encrypted_user_files_folder] def getAllFilePaths(self,file_type):
return [
self.getGroupFilesFolderPath(file_type),
self.getUserFilesFolderPath(file_type),
self.getAccumulatedFilePath(file_type)
]
def deleteAllFilesInFolder(self,folder_path): def deleteAllFilesInFolder(self,folder_path):
try: try:
self.executeCommand('rm -v ' + folder_path + '*') self.executeCommand('rm -v ' + folder_path + '*')
print(self.getCommandString())
print(self.getOutputString())
except: except:
pass pass
def deleteAllDecryptedFiles(self): def deleteAllFiles(self,file_type):
for folder_path in self.decrypted_files_folders: for folder_path in self.getAllFilePaths(file_type):
self.deleteAllFilesInFolder(folder_path) self.deleteAllFilesInFolder(folder_path)
def deleteAllEncryptedFiles(self): def deleteAllEncryptedFiles(self):
for folder_path in self.encrypted_files_folders: for folder_path in self.encrypted_files_folders:
self.deleteAllFilesInFolder(folder_path) self.deleteAllFilesInFolder(folder_path)
def cleanupForUser(self,user):
try:
self.executeCommand('find "' + self.getFolderPath("encrypted") + '" -not -name "*' + str(user) +'*" -type f -print | xargs rm -v')
except:
pass
self.deleteAllFiles("decrypted")
def deleteAll(self): def deleteAll(self):
self.deleteAllEncryptedFiles() self.deleteAllFiles("encrypted")
self.deleteAllDecryptedFiles() self.deleteAllFiles("decrypted")

View File

@ -0,0 +1,41 @@
from .AbstractSplittedSecret import AbstractSplittedSecret
import json
class Decryption(AbstractSplittedSecret):
def __init__(self):
self.user_id='0';
self.user_password=''
super(Decryption, self).__init__()
def setUserId(self,user_id):
self.user_id=str(user_id)
self.user_file_decrypted_path = self.getUserFilePath(self.user_id,"decrypted")
def setUserPassword(self,user_password):
self.user_password = str(user_password)
def loadJsonFile(self,file_path):
file = open(file_path)
data = json.load(file)
file.close()
return data
def setNeededEncryptersAmount(self):
self.needed_encrypters_amount = len(str(list(self.user_data['groups'].keys())[0]))-1
def decryptFile(self,password,input_file_path,output_file_path):
self.executeCommand('gpg --batch --passphrase "'+ password + '" -o "' + output_file_path +'" "'+ input_file_path+'"')
def decryptUserFile(self):
input_file_path = self.getUserFilePath(self.user_id,"encrypted")
self.decryptFile(self.user_password, input_file_path, self.user_file_decrypted_path)
def decryptAccumulatedFile(self):
input_file_path = self.getAccumulatedFilePath("encrypted")
output_file_path = self.getAccumulatedFilePath("decrypted")
self.decryptFile(self.user_password, input_file_path, output_file_path)
def initializeData(self):
self.decryptUserFile()
self.user_data = self.loadJsonFile(self.user_file_decrypted_path)
self.setNeededEncryptersAmount()

View File

@ -6,15 +6,30 @@ import re
import json import json
from .AbstractSplittedSecret import AbstractSplittedSecret from .AbstractSplittedSecret import AbstractSplittedSecret
class Generate(AbstractSplittedSecret): class Encryption(AbstractSplittedSecret):
def __init__(self, amount_of_secret_holders, decryption_quota,master_password): def __init__(self, amount_of_secret_holders, decryption_quota,master_password):
super(Generate, self).__init__() super(Encryption, self).__init__()
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
self.quota_factor=self.decryption_quota/100 self.quota_factor=self.decryption_quota/100
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.initializeGroupData()
def initializeUserData(self):
self.user_mapped_data = {}
user_count = 1
while user_count <= self.amount_of_secret_holders:
self.user_mapped_data[str(user_count)] = {"groups":{},"user_password":self.createPassword(64),"about":{}}
user_count += 1;
def initializeGroupData(self):
self.group_mapped_data = {}
def addInformationToUser(self,user_id,label,content):
self.user_mapped_data[user_id]['about'][label] = content;
def getStartnumber(self): def getStartnumber(self):
index = 0 index = 0
@ -32,14 +47,6 @@ class Generate(AbstractSplittedSecret):
index += 1 index += 1
return int(start_number) return int(start_number)
def savePassword(self,password,password_file_path):
print("Saving password to: " + password_file_path)
master_password_file = open(password_file_path, "a")
master_password_file.seek(0)
master_password_file.truncate()
master_password_file.write(password)
master_password_file.close()
def createPassword(self,length): def createPassword(self,length):
characters = string.ascii_letters + string.digits characters = string.ascii_letters + string.digits
return (''.join(random.choice(characters) for i in range(length)).upper()) return (''.join(random.choice(characters) for i in range(length)).upper())
@ -50,19 +57,18 @@ class Generate(AbstractSplittedSecret):
unvalid_sequenz = re.compile("(.)\\1+") unvalid_sequenz = re.compile("(.)\\1+")
return re.search(valid_numbers, password_group_index_str) and not re.search(unvalid_sequenz, password_group_index_str) return re.search(valid_numbers, password_group_index_str) and not re.search(unvalid_sequenz, password_group_index_str)
def createUserMappedDataFrame(self): def compileContacts(self):
self.user_mapped_data = {} contacts = {}
user_count = 1 for user_id in self.user_mapped_data:
while user_count <= self.amount_of_secret_holders: contacts[user_id] = self.user_mapped_data[user_id]['about']
self.user_mapped_data[str(user_count)] = {"groups":{},"user_password":self.createPassword(64)} for user_id in self.user_mapped_data:
user_count += 1; self.user_mapped_data[user_id]['contacts'] = {}
for contact_id in contacts:
if contact_id != user_id:
self.user_mapped_data[user_id]['contacts'][contact_id] = contacts[contact_id]
def createGroupMappedDataFrame(self): def compileData(self):
self.group_mapped_data = {} self.compileContacts()
def generateMappedData(self):
self.createUserMappedDataFrame()
self.createGroupMappedDataFrame()
index = self.getStartnumber() index = self.getStartnumber()
while index < self.getEndnumber(): while index < self.getEndnumber():
password_group_index_str = ''.join(sorted(str(index))) password_group_index_str = ''.join(sorted(str(index)))
@ -84,47 +90,29 @@ class Generate(AbstractSplittedSecret):
index += 1 index += 1
def encryptStringToFile(self,text,output_file,password): def encryptStringToFile(self,text,output_file,password):
self.executeCommand('echo \'' + text + '\' | gpg --symmetric --armor --batch --passphrase "' + password + '" -o "' + output_file + '.gpg"') self.executeCommand('echo \'' + text + '\' | gpg --symmetric --armor --batch --passphrase "' + password + '" -o "' + output_file + '"')
print(self.getCommandString())
def generateEncryptedGroupFiles(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_splitted_password_file = AbstractSplittedSecret().encrypted_group_files_folder + str(password_group_index_int) + ".txt" encrypted_group_password_file_path = self.getGroupFilePath(password_group_index_int,"encrypted")
self.encryptStringToFile(self.master_password,encrypted_splitted_password_file,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 encryptUserMappedData(self): def encryptUserData(self):
for user_id in self.user_mapped_data: for user_id in self.user_mapped_data:
file_path=self.encrypted_user_files_folder+user_id+'.json' file_path=self.getUserFilePath(user_id,"encrypted")
self.encryptToJsonFile(self.user_mapped_data[user_id]['groups'],file_path,self.user_mapped_data[user_id]['user_password']) data=self.user_mapped_data[user_id]
password=self.user_mapped_data[user_id]['user_password']
self.encryptToJsonFile(data,file_path,password)
def encryptAccumulatedMappedData(self): def encryptAccumulatedData(self):
file_path=self.encrypted_folder+'accumulated.json' file_path=self.getAccumulatedFilePath("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 saveMappedData(self): def encrypt(self):
self.encryptUserMappedData() self.encryptUserData()
self.encryptAccumulatedMappedData() self.encryptAccumulatedData()
self.encryptGroupFiles()
def encryptMappedUserData(self):
self.user_passwords = {}
for user_id in self.user_mapped_data:
self.user_passwords[user_id] = self.createPassword(64)
def encryptMappedData(self):
self.encryptMappedUserData()
def generate(self):
self.generateMappedData()
self.saveMappedData()
self.encryptMappedData()
self.generateEncryptedGroupFiles()
def getUserMappedData(self):
return self.user_mapped_data
def getGroupMappedData(self):
return self.group_mapped_data

View File

@ -1,27 +1,85 @@
import argparse import argparse
from classes.Generate import Generate from classes.Encryption import Encryption
from classes.Cleanup import Cleanup from classes.Cleanup import Cleanup
from classes.Decryption import Decryption
from getpass import getpass from getpass import getpass
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--mode',type=str, dest='mode',required=True,choices=['cleanup','generate']) parser.add_argument('--mode',type=str, dest='mode',required=True,choices=['cleanup','encrypt','decrypt'])
parser.add_argument('--amount',type=int, dest='amount_of_secret_holders',required=False,choices=range(1,9)) parser.add_argument('--amount',type=int, dest='amount_of_secret_holders',required=False,choices=range(1,9))
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',type=int, dest='user',choices=range(1,9),required=False)
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()
mode = args.mode
if args.mode == 'cleanup': print("Splitted Secret Interface started.")
print("Selected Mode: " + mode)
if mode == 'cleanup':
cleanup = Cleanup() cleanup = Cleanup()
if args.user is None:
print("Delete all files.")
cleanup.deleteAll() cleanup.deleteAll()
exit() exit()
print("Delete files for user <<" + str(args.user) + ">>");
cleanup.cleanupForUser(args.user)
exit()
if args.mode == 'generate': if mode == 'decrypt':
decrypt = Decryption()
if args.master_password is None:
if args.user is None:
print("Please type in the user number:")
decrypt.setUserId(input())
else:
decrypt.setUserId(args.user)
if args.user_password is None:
while True:
print("Please enter the user password:")
decrypt.setUserPassword(getpass())
print("Decrypting User File...")
try:
decrypt.initializeData();
break;
except:
print("Wrong password :(")
else:
decrypt.setUserPassword(args.user_password)
print("Decrypting User File...")
try:
decrypt.initializeData();
except:
print("Wrong password :(")
exit()
print("File decrypted :) \n")
print("Please contact the following persons and tell them that you need help to encrypt the data: \n")
for contact_id in decrypt.user_data['contacts']:
print("user_id: " + contact_id)
for label in decrypt.user_data['contacts'][contact_id]:
print(label + ": " + decrypt.user_data['contacts'][contact_id][label])
print("You need at least <<" + str(decrypt.needed_encrypters_amount) +">> other person to decrypt the secret.")
exit()
print("Decrypting accumulated file...")
decrypt.setUserPassword(args.master_password)
decrypt.decryptAccumulatedFile()
exit()
if mode == 'encrypt':
if args.master_password is None: if args.master_password is None:
print("Please enter the master password:") print("Please enter the master password:")
master_password = getpass() master_password = getpass()
else: else:
master_password = args.master_password master_password = args.master_password
generate = Generate(args.amount_of_secret_holders, args.decryption_quota,master_password) encrypt = Encryption(args.amount_of_secret_holders, args.decryption_quota, master_password)
generate.generate() if args.add_user_information is not None:
for user_id in encrypt.user_mapped_data:
for label in ['name','phone','email','address']:
print("Please enter attribut <<" + label + ">> for user <<" + user_id+ ">>:" )
encrypt.addInformationToUser(user_id, label, str(input()))
encrypt.compileData()
encrypt.encrypt()
exit() exit()