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__

View File

@ -18,12 +18,13 @@ echo2 foxtrott
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 --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
EOQXCYGEY2IMKAJP5VOCRVRH9LPYAPK9IC0ID0GMSJ5KXNXJHPNUBUKEVLE2WHQJ
YGC6FLI5FIFL4WV4JPZZI7RVOZTWLROCLY4HVGDMWWSTAIQJTLUQK1VBBY0E24PN
END_OF_INPUTS
```
# Requirements to know
@ -38,16 +39,14 @@ END_OF_INPUTS
```bash
pip install numpy
gpg
ecryptfs-utils
ecryptfs-simple
python
pip
```
## todo
- implement tails setup script
- add data-input attribut
- add data-output attribut
- implement relativ call
- implement tmp mount for decrypted files
## Further Information
- https://www.tutorialspoint.com/python/python_command_line_arguments.htm
@ -55,5 +54,4 @@ END_OF_INPUTS
- https://wiki.ubuntuusers.de/GoCryptFS/
- https://pynative.com/python-generate-random-string/
- 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://linuxconfig.org/how-to-create-compressed-encrypted-archives-with-tar-and-gpg
- https://numpy.org/doc/stable/reference/generated/numpy.base_repr.html?highlight=base_repr#numpy.base_repr

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

View File

@ -1,17 +1,16 @@
from .AbstractSplittedSecret import AbstractSplittedSecret
import json
from pathlib import Path
class Decryption():
class Decryption(AbstractSplittedSecret):
def __init__(self,cli,paths):
def __init__(self):
self.user_id='0';
self.user_password=''
self.cli = cli
self.paths = paths
super(Decryption, self).__init__()
def initializeUser(self,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):
self.decryptUserFile()
@ -21,9 +20,9 @@ class Decryption():
def initializeGroupDataEncryption(self):
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.master_password = self.loadTxtFile(self.encrypted_group_file_path).strip()
self.master_password = self.loadTxtFile(self.encrypted_group_file_path)
def initializeNeededDecryptersAmount(self):
self.needed_decrypters_amount = len(str(list(self.user_data['groups'].keys())[0]))
@ -98,20 +97,17 @@ class Decryption():
return data
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):
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)
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)
def decryptAccumulatedFile(self):
input_file_path = self.paths.getAccumulatedFilePath(self.paths.TYPE_ENCRYPTED)
output_file_path = self.paths.getAccumulatedFilePath(self.paths.TYPE_DECRYPTED)
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() + '"')
input_file_path = self.getAccumulatedFilePath(AbstractSplittedSecret.TYPE_ENCRYPTED)
output_file_path = self.getAccumulatedFilePath(AbstractSplittedSecret.TYPE_DECRYPTED)
self.decryptFile(self.user_password, input_file_path, output_file_path)

View File

@ -4,18 +4,12 @@ import math
import numpy
import re
import json
from .Paths import Paths
from .AbstractSplittedSecret import AbstractSplittedSecret
class Encryption():
class Encryption(AbstractSplittedSecret):
USER_PASSWORD_LENGTHS = 64
OVERALL_PASSWORD_LENGTHS = 128
# 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):
def __init__(self, amount_of_secret_holders, decryption_quota,master_password):
super(Encryption, self).__init__()
self.amount_of_secret_holders = amount_of_secret_holders
self.decryption_quota = decryption_quota
self.master_password = master_password
@ -23,9 +17,7 @@ class Encryption():
self.group_members_amount=math.ceil(self.amount_of_secret_holders * self.quota_factor)
self.initializeUserData()
self.initializeGroupData()
self.cli = cli
self.paths = paths
def initializeUserData(self):
self.user_mapped_data = {}
user_count = 1
@ -38,13 +30,7 @@ class Encryption():
def addInformationToUser(self,user_id,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):
index = 0
start_number = ''
@ -104,33 +90,29 @@ class Encryption():
index += 1
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):
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'])
def encryptToJsonFile(self,data,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:
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]
password=self.user_mapped_data[user_id]['user_password']
self.encryptToJsonFile(data,file_path,password)
def encryptAccumulatedFile(self):
file_path=self.paths.getAccumulatedFilePath(Paths.TYPE_ENCRYPTED)
def encryptAccumulatedData(self):
file_path=self.getAccumulatedFilePath(AbstractSplittedSecret.TYPE_ENCRYPTED)
data={"user_mapped": self.user_mapped_data, "group_mapped": self.group_mapped_data}
self.encryptToJsonFile(data,file_path,self.master_password)
def encryptMainData(self):
self.cli.executeCommand('tar -cvzf - "' + self.paths.getDecryptedMainDataStandartFolder() + '" | gpg -c --batch --passphrase "' + self.master_password +'" > "' + self.paths.getEncryptedMainDataFile() + '"');
def encryptAll(self):
self.encryptUserFile()
self.encryptAccumulatedFile()
def encrypt(self):
self.encryptUserData()
self.encryptAccumulatedData()
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,41 +3,36 @@ from classes.Encryption import Encryption
from classes.Cleanup import Cleanup
from classes.Decryption import Decryption
from getpass import getpass
from classes.AbstractSplittedSecret import AbstractSplittedSecret
import traceback
from classes.Cli import Cli
from classes.Paths import Paths
cli = Cli()
paths = Paths()
cleanup = Cleanup(cli,paths)
cleanup = Cleanup()
def clean_exit():
print("Cleaning up.")
try:
cleanup.cleanupFiles(Paths.TYPE_DECRYPTED)
cleanup.cleanupFiles(AbstractSplittedSecret.TYPE_DECRYPTED)
except:
pass
standard_exit()
print("Leaving program.")
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("TO REMOVE DECRYPTED DATA EXECUTE:\nmain.py --mode cleanup --file-types " + Paths.TYPE_DECRYPTED)
standard_exit()
def standard_exit():
print("TO REMOVE DECRYPTED DATA EXECUTE:\nmain.py --mode cleanup --file-types " + AbstractSplittedSecret.TYPE_DECRYPTED)
print("Leaving program.")
exit()
try:
if __name__ == '__main__':
parser = argparse.ArgumentParser()
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('--amount',type=int, dest='amount_of_secret_holders',required=False,choices=Encryption.getCoSecretHoldersRange())
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=AbstractSplittedSecret.getCoSecretHoldersRange())
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('--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)
args = parser.parse_args()
@ -50,16 +45,16 @@ try:
if args.user is None:
print("Deleting all encrypted and decrypted files.")
cleanup.deleteAll()
standard_exit()
clean_exit()
print("Deleting all files which aren't related to user: " + str(args.user));
cleanup.cleanupForUser(args.user)
standard_exit()
clean_exit()
print("Deleting all " + args.file_types + " files.")
cleanup.cleanupFiles(args.file_types)
standard_exit()
clean_exit()
if args.mode == 'decrypt':
decrypt = Decryption(cli,paths)
decrypt = Decryption()
if args.master_password is None:
if args.user is None:
print("Type in the user id:")
@ -125,14 +120,11 @@ try:
break;
except:
print("An unexpected error occured: \n" + traceback.format_exc())
print("Decrypting main data.")
decrypt.decryptMainData()
print("All data decrypted.")
dirty_exit()
print("Decrypting accumulated data.")
print("Decrypting accumulated file...")
decrypt.setUserPassword(args.master_password)
decrypt.decryptAccumulatedFile()
dirty_exit()
clean_exit()
if args.mode == 'encrypt':
if args.master_password is None:
@ -140,16 +132,15 @@ try:
master_password = getpass()
else:
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:
for user_id in encrypt.user_mapped_data:
for label in ['name','phone','email','address']:
print("Enter attribut <<" + label + ">> for user <<" + user_id+ ">>:" )
encrypt.addInformationToUser(user_id, label, str(input()))
encrypt.compileData()
encrypt.encryptAll()
dirty_exit()
encrypt.encrypt()
clean_exit()
except KeyboardInterrupt:
print("Program interrupted by user.")
clean_exit()