Compare commits

..

100 Commits

Author SHA1 Message Date
228230bb1b Config
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-30 11:00:16 +02:00
9d3c011816 Config files
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-29 20:15:27 +02:00
18bfac4a86 Bcrypt salting
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 20:09:37 +02:00
6d2441d931 dirty workaround
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 18:05:37 +02:00
841c5d4c20 asd
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:52:54 +02:00
0e3ba17a8e basedir
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:52:34 +02:00
ec5a36c700 do not allow getting out
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:45:23 +02:00
fe26bd1727 asd
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:38:28 +02:00
4466ee6172 use unipath
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:33:15 +02:00
7f1a5f1013 now
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:22:14 +02:00
3bcb7e18ce maybe this
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:18:41 +02:00
37d2e06a18 OK
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:16:08 +02:00
978d7cf092 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:11:41 +02:00
73c91d1426 OK 2021-04-29 17:11:33 +02:00
fc5385af63 seb
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:07:42 +02:00
fd4434f504 listdir
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:06:25 +02:00
152177473d better things
Some checks failed
continuous-integration/drone/push Build is failing
2021-04-29 17:00:50 +02:00
00d4542404 remove more redundant try
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 23:22:45 +02:00
09c376debf remove redundant try
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 23:16:47 +02:00
8acd49fe09 omg
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:59:23 +02:00
034f1e3403 fail better
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:56:06 +02:00
c4333ed827 remove autism
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:48:11 +02:00
784f065478 return error
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:41:37 +02:00
2d426a9f73 some niceness2
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:40:04 +02:00
cced3c49ef error
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:33:44 +02:00
3d1178d8ac do the magic
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:33:04 +02:00
62dd8872d6 hatvannegyedik bazis
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:23:20 +02:00
66877d52a1 lets see
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:19:09 +02:00
b4a9ccb334 szezon meg a fazon
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:06:07 +02:00
d40b20e753 fix public key shittery
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 22:02:06 +02:00
90969aeadb better append to dict
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 21:52:11 +02:00
101a8ab8d6 fixie wuxie
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 21:41:45 +02:00
540044c259 some printing, should replace with logger
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 20:37:32 +02:00
1616150c2f minor mistake
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 19:35:03 +02:00
c682fe1e2a missing comma
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 19:33:33 +02:00
4837948fba refactor and better crypto
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 19:31:55 +02:00
56d77f0476 refactor chacha
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 18:13:38 +02:00
a8730ceac3 foggyos vagyok
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 17:19:36 +02:00
f409aefdc0 use authenticated chacha20
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 16:58:50 +02:00
b08da25d21 Test for MKD / RMD works like a charm
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 14:40:32 +02:00
3e0afb0d45 copypaste went wild
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 13:50:28 +02:00
df79776ede move
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 13:31:00 +02:00
0c6c1c6622 memes
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 13:30:17 +02:00
a14e0414b6 fail less
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 13:28:57 +02:00
ae743cde15 some more login rework
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 13:18:50 +02:00
772a9e6d2c encode
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 00:26:23 +02:00
6bf93241f1 pep8
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 00:24:24 +02:00
63733a317f cipherkey is now guaranteed to be 32 characters strong
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-26 00:22:05 +02:00
ded1968f26 fail harder
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 20:27:37 +02:00
4fc32ddeea key
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 19:23:07 +02:00
45bab9c9f3 Long key
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 19:15:08 +02:00
c5d4859326 Error in auth
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:42:38 +02:00
149c206830 fix circular dependency
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:40:41 +02:00
798b74e5d8 fix server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:35:01 +02:00
3ad96cf71a Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server into master
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:34:09 +02:00
56a77f9c7e fix import 2021-04-25 18:33:50 +02:00
ccc664e0ea Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:29:55 +02:00
4e5634eb1d DNL 2021-04-25 18:29:49 +02:00
b6d46ea1bf return bytes
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:29:00 +02:00
b70c214584 fix cascading memes
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:25:27 +02:00
b6b3dd3a35 fixd
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:20:55 +02:00
f345d4b961 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:19:18 +02:00
487f5ec772 UPL 2021-04-25 18:19:08 +02:00
5378ec8cdc better recievemessage
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:18:37 +02:00
89e8bd1295 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server into master
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:13:24 +02:00
dc43cc3056 use bytes 2021-04-25 18:13:14 +02:00
8957cd6a04 Key export doesnt need protection tpye because DER format has default: PBKDF2WithHMAC-SHA1AndDES-EDE3-CBC
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:11:53 +02:00
81ea634b3a Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:09:51 +02:00
5e1e9f3e69 Duplicate row in auth 2021-04-25 18:09:43 +02:00
42fff36545 unresolved reference
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:08:21 +02:00
621c59dce2 fix decode
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:05:49 +02:00
a5490854af no return, send message
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 18:02:29 +02:00
4bd161de54 create init function
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:55:05 +02:00
0874645719 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server into master 2021-04-25 17:51:08 +02:00
f6461273ab Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:50:50 +02:00
8d7754edc2 oops 2021-04-25 17:50:43 +02:00
7628156340 server execute 2021-04-25 17:50:39 +02:00
f8161f34fa no message
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:45:22 +02:00
7c0e66c450 add main
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:36:19 +02:00
c091532f74 comment pszeudoprogramming meme
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:35:39 +02:00
c5d89d8b13 invoke server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:29:50 +02:00
15bd2b13ca things
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:20:19 +02:00
75f6e77668 remove unresolved reference
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:15:11 +02:00
edfd2bd889 do the magic, this will not run
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:12:20 +02:00
e3d1280cb6 some cleanup
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:09:37 +02:00
904c01db47 use ascii
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 17:06:25 +02:00
f1220dd49e Netwrapper key gen
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 16:38:46 +02:00
3dbde8fbb8 Authentication_test corrections
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 16:06:56 +02:00
c69241249e Source address
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 15:40:08 +02:00
f0c5281697 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 15:24:27 +02:00
b87e2c3b3d Init script extension and key loading for netwrapper 2021-04-25 15:24:24 +02:00
bfdec0e727 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 14:38:08 +02:00
977b87634c login, logout in server, invoke server's logout in netwrapper 2021-04-25 14:28:29 +02:00
d526063dcf linerror
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 13:24:23 +02:00
a5b77d0306 finish netwrapper of server and executor improvements
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 00:42:36 +02:00
90396c2826 user login
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-25 00:35:23 +02:00
4fae36ff79 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server into master
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-23 18:54:20 +02:00
6157c68c30 fix login 2021-04-23 18:54:05 +02:00
02ef40a303 Merge branch 'master' of https://git.kmlabz.com/BiztProtoBois/server
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-23 18:13:25 +02:00
4005a86058 Netwrapper 2021-04-23 18:13:18 +02:00
12 changed files with 403 additions and 106 deletions

View File

@ -1 +1,3 @@
pycryptodome pycryptodome
pydh
unipath

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python3
import json import json
import logging import logging
import os import os
@ -7,13 +9,16 @@ from base64 import b64encode
from Crypto.Hash import SHA256 from Crypto.Hash import SHA256
from Crypto.Protocol.KDF import bcrypt, bcrypt_check from Crypto.Protocol.KDF import bcrypt, bcrypt_check
from Crypto.PublicKey import RSA
from Crypto.PublicKey.RSA import RsaKey
from Crypto.Random import get_random_bytes
auth_logger = logging.getLogger('AUTH APPLICATION ') auth_logger = logging.getLogger('AUTH APPLICATION ')
auth_logger.root.setLevel(logging.INFO) auth_logger.setLevel(logging.INFO)
class Authetication: class Authetication:
ABSOLUTE_PATH = os.path.abspath(os.path.dirname(sys.argv[0])) ABSOLUTE_PATH = os.path.abspath(os.path.dirname(sys.argv[0]))
HOME_DIRECTORY_LOCATION = ABSOLUTE_PATH + os.path.sep +"home" HOME_DIRECTORY_LOCATION = ABSOLUTE_PATH + os.path.sep + "home"
CONFIG_DIRECTORY_LOCATION = ABSOLUTE_PATH + os.path.sep + "config" CONFIG_DIRECTORY_LOCATION = ABSOLUTE_PATH + os.path.sep + "config"
CONFIG_FILE_LOCATION = ABSOLUTE_PATH + os.path.sep + "config" + os.path.sep + "config.txt" CONFIG_FILE_LOCATION = ABSOLUTE_PATH + os.path.sep + "config" + os.path.sep + "config.txt"
PRIVATE_KEY_DIRECTORY_LOCATION = CONFIG_DIRECTORY_LOCATION + os.path.sep + "private_keys" PRIVATE_KEY_DIRECTORY_LOCATION = CONFIG_DIRECTORY_LOCATION + os.path.sep + "private_keys"
@ -43,15 +48,17 @@ class Authetication:
for user in data['user']: for user in data['user']:
if username == user['username']: if username == user['username']:
b64pwd = b64encode(SHA256.new(password.encode('utf-8')).digest())
try: try:
b64pwd = b64encode(SHA256.new(password.encode('utf-8')).digest()) b64pwd = b64encode(SHA256.new(password.encode('utf-8')).digest())
bcrypt_check(b64pwd, user['password'].encode('utf-8')) bcrypt_check(b64pwd, user['password'].encode('utf-8'))
auth_logger.debug("User logged in: " + username)
return self.HOME_DIRECTORY_LOCATION + os.path.sep + user['homeDir']
except ValueError: except ValueError:
auth_logger.debug("User NOT logged in: " + username) auth_logger.debug("User NOT logged in: " + username)
return '' return ''
auth_logger.debug("User logged in: " + username) else:
return user['homeDir'] auth_logger.error("User not found")
return ''
def checkUserExists(self, username: str) -> bool: def checkUserExists(self, username: str) -> bool:
with open(self.CONFIG_FILE_LOCATION) as json_file: with open(self.CONFIG_FILE_LOCATION) as json_file:
@ -70,14 +77,16 @@ class Authetication:
shutil.rmtree(self.HOME_DIRECTORY_LOCATION) shutil.rmtree(self.HOME_DIRECTORY_LOCATION)
os.mkdir(self.HOME_DIRECTORY_LOCATION) os.mkdir(self.HOME_DIRECTORY_LOCATION)
os.mkdir(self.HOME_DIRECTORY_LOCATION + os.path.sep + '0')
shutil.rmtree(self.PRIVATE_KEY_DIRECTORY_LOCATION) shutil.rmtree(self.PRIVATE_KEY_DIRECTORY_LOCATION)
os.mkdir(self.PRIVATE_KEY_DIRECTORY_LOCATION) os.mkdir(self.PRIVATE_KEY_DIRECTORY_LOCATION)
def saveUser(self, username: str, password: str) -> bool: def saveUser(self, username: str, password: str) -> bool:
user_salt = get_random_bytes(16)
bytePass = password.encode('utf-8') bytePass = password.encode('utf-8')
b64pwd = b64encode(SHA256.new(bytePass).digest()) b64pwd = b64encode(SHA256.new(bytePass).digest())
bcrypt_hash = bcrypt(b64pwd, 12) bcrypt_hash = bcrypt(password=b64pwd, cost=12, salt=user_salt)
with open(self.CONFIG_FILE_LOCATION) as json_file: with open(self.CONFIG_FILE_LOCATION) as json_file:
data = json.load(json_file) data = json.load(json_file)
@ -108,3 +117,34 @@ class Authetication:
auth_logger.debug("User NOT saved! Home directory already exists") auth_logger.debug("User NOT saved! Home directory already exists")
return True return True
def loadUserPublicKeys(self) -> dict:
with open(self.CONFIG_FILE_LOCATION) as json_file:
data = json.load(json_file)
dictionary = dict()
for user in data['user']:
key = user['publicKey']
key = bytes.fromhex(key)
try:
rsaKey = RSA.import_key(key)
dictionary[user['username']] = rsaKey
except ValueError:
print('Invalid server public key!')
return dictionary
def loadServerPrivateKey(self, passphrase: str) -> RsaKey:
with open(self.CONFIG_FILE_LOCATION) as json_file:
data = json.load(json_file)
key = data['serverPrivateKey']
key = bytes.fromhex(key)
try:
rsaKey = RSA.import_key(key, passphrase)
except ValueError:
print('Invalid server private key!')
return rsaKey

View File

@ -35,7 +35,7 @@ def testAuth(username: str, password: str):
auth.saveUser(username, password) auth.saveUser(username, password)
homeDir = auth.login(username, password) homeDir = auth.login(username, password)
if homeDir == '1': if homeDir == auth.HOME_DIRECTORY_LOCATION + os.path.sep + '1':
test_logger.info('TEST 1 --> Authentication test with VALID :: PASSED') test_logger.info('TEST 1 --> Authentication test with VALID :: PASSED')
else: else:
test_logger.info('TEST 1 --> Authentication test with VALID :: FAILED') test_logger.info('TEST 1 --> Authentication test with VALID :: FAILED')
@ -68,10 +68,13 @@ def testPersistency():
logging.info('PERSISTENCY TEST') logging.info('PERSISTENCY TEST')
auth = Authetication() auth = Authetication()
auth.initConfig() auth.initConfig()
serverPublicKey = init.generatePrivateKeyForServer(auth, 'admin')
auth.saveUser('alma','alma') auth.saveUser('alma','alma')
init.generatePrivateKeyForUser(auth, 'alma', 'amla') homeDir = auth.login('alma','alma')
init.generatePrivateKeyForUser(auth, 'alma', 'amla', serverPublicKey, init.generateSourceAddress(homeDir))
auth.saveUser('citrom','citrom') auth.saveUser('citrom','citrom')
init.generatePrivateKeyForUser(auth, 'citrom', 'mortic') homeDir = auth.login('citrom','citrom')
init.generatePrivateKeyForUser(auth, 'citrom', 'mortic', serverPublicKey, init.generateSourceAddress(homeDir))
auth2 = Authetication() auth2 = Authetication()
if auth2.checkUserExists('alma'): if auth2.checkUserExists('alma'):
@ -115,4 +118,4 @@ if __name__ == '__main__':
testSaveUser("Diósbejglia", "Diósbejgli") testSaveUser("Diósbejglia", "Diósbejgli")
testAuth("Diósbejglia", "Diósbejgli") testAuth("Diósbejglia", "Diósbejgli")
testUserExists("Diósbejglia", "Diósbejgli") testUserExists("Diósbejglia", "Diósbejgli")
testPersistency() #testPersistency()

View File

@ -1,2 +0,0 @@
#!/usr/bin/env python3

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python3
import json import json
import os import os
@ -5,21 +7,22 @@ from Crypto.PublicKey import RSA
from authentication import Authetication from authentication import Authetication
def generatePrivateKeyForUser(auth: Authetication,username: str, user_passphrase: str, public_server_key: str,address: str) -> bool:
def generatePrivateKeyForUser(auth: Authetication, username: str, user_passphrase: str, public_server_key='') -> bool:
if auth.checkUserExists(username): if auth.checkUserExists(username):
with open(auth.CONFIG_FILE_LOCATION) as json_file: with open(auth.CONFIG_FILE_LOCATION) as json_file:
data = json.load(json_file) data = json.load(json_file)
private_key = RSA.generate(2048) private_key = RSA.generate(8192)
public_key = private_key.publickey() public_key = private_key.publickey()
private_key_value = bytes.hex(private_key.exportKey('DER', passphrase=user_passphrase, pkcs=8)) private_key_value = bytes.hex(private_key.exportKey('DER', passphrase=user_passphrase, pkcs=8))
public_key_value = bytes.hex(public_key.exportKey('DER', pkcs=8)) public_key_value = bytes.hex(public_key.exportKey('DER', pkcs=8))
##Save private key in separate file ##Save private key in separate file
user_privatekey = {'passphrase': user_passphrase, 'privateClientKey': private_key_value, user_privatekey = {'address': address,
'privateClientKey': private_key_value,
'publicServerKey': public_server_key} 'publicServerKey': public_server_key}
with open(auth.PRIVATE_KEY_DIRECTORY_LOCATION + os.path.sep + str(data['index']) + '.txt', 'w+') as outfile: with open(auth.PRIVATE_KEY_DIRECTORY_LOCATION + os.path.sep + str(data['index']) + '.txt',
'w+') as outfile:
json.dump(user_privatekey, outfile) json.dump(user_privatekey, outfile)
outfile.close() outfile.close()
@ -27,7 +30,7 @@ def generatePrivateKeyForUser(auth: Authetication, username: str, user_passphras
for user in data['user']: for user in data['user']:
if username == user['username']: if username == user['username']:
user['publicKey'] = public_key_value user['publicKey'] = public_key_value
with open(auth.CONFIG_FILE_LOCATION, 'w') as outfile: with open(auth.CONFIG_FILE_LOCATION, 'w+') as outfile:
json.dump(data, outfile) json.dump(data, outfile)
break break
outfile.close() outfile.close()
@ -36,10 +39,34 @@ def generatePrivateKeyForUser(auth: Authetication, username: str, user_passphras
return False return False
def generatePrivateKeyForServer(auth: Authetication,passphrase: str) -> str:
with open(auth.CONFIG_FILE_LOCATION) as json_file:
data = json.load(json_file)
json_file.close()
private_key = RSA.generate(8192)
public_key = private_key.publickey()
private_key_value = bytes.hex(private_key.exportKey('DER', passphrase=passphrase, pkcs=8, protection="scryptAndAES128-CBC"))
public_key_value = bytes.hex(public_key.exportKey('DER', pkcs=8))
data['serverPrivateKey'] = private_key_value
with open(auth.CONFIG_FILE_LOCATION, 'w+') as outfile:
json.dump(data, outfile)
return public_key_value
def generateSourceAddress(index: str) -> chr:
return chr(ord(index[0]) + 17)
if __name__ == '__main__': if __name__ == '__main__':
auth = Authetication() auth = Authetication()
auth.initConfig() auth.initConfig()
auth.saveUser('alma' ,'alma') serverPublicKey = generatePrivateKeyForServer(auth, 'admin')
generatePrivateKeyForUser('alma', 'amla') auth.saveUser('alma', 'alma')
auth.saveUser('citrom' ,'citrom') homeDir = auth.login('alma', 'alma')
generatePrivateKeyForUser('citrom', 'mortic') generatePrivateKeyForUser(auth, 'alma', 'amla', serverPublicKey, generateSourceAddress(homeDir))
auth.saveUser('citrom', 'citrom')
homeDir = auth.login('citrom', 'citrom')
generatePrivateKeyForUser(auth, 'citrom', 'mortic', serverPublicKey, generateSourceAddress(homeDir))

View File

@ -3,16 +3,14 @@
import os import os
import re import re
from unipath import Path
class Executor: class Executor:
"""This class executes commands recieved by the server""" """This class executes commands recieved by the server"""
def __init__(self, currentDiectory: str, baseDir: str = ""): def __init__(self, baseDir: str):
self.currentDirectory = currentDiectory self.currentDirectory = ""
if baseDir == "": self.baseDir = baseDir + os.path.sep
self.baseDir = self.currentDirectory
else:
self.baseDir = baseDir
def sanitizeDirectory(self, inDirectory: str) -> str: def sanitizeDirectory(self, inDirectory: str) -> str:
return re.sub('[^a-zA-Z0-9]', '', inDirectory) return re.sub('[^a-zA-Z0-9]', '', inDirectory)
@ -22,14 +20,15 @@ class Executor:
def createDirectory(self, dirName: str) -> str: def createDirectory(self, dirName: str) -> str:
dirName = self.sanitizeDirectory(dirName) dirName = self.sanitizeDirectory(dirName)
actualDirName = os.path.join(self.currentDirectory, dirName) actualDirName: str = os.path.join(self.baseDir,self.currentDirectory,dirName)
os.mkdir(actualDirName) os.mkdir(actualDirName)
return actualDirName return actualDirName
def removeDirectory(self, dirName: str) -> str: def removeDirectory(self, dirName: str) -> str:
dirName = self.sanitizeDirectory(dirName) dirName = self.sanitizeDirectory(dirName)
actualDirName = os.path.join(self.currentDirectory, dirName) actualDirName: str = os.path.join(self.baseDir, self.currentDirectory, dirName)
os.rmdir(actualDirName) if actualDirName:
os.rmdir(actualDirName)
return actualDirName return actualDirName
def getCurrentDirectory(self) -> str: def getCurrentDirectory(self) -> str:
@ -37,44 +36,58 @@ class Executor:
def setCurrentDirectory(self, dirName: str) -> str: def setCurrentDirectory(self, dirName: str) -> str:
if dirName == "..": if dirName == "..":
if self.currentDirectory == self.baseDir: p = Path(os.path.join(self.baseDir, self.currentDirectory))
parentpath = p.parent
if (str(parentpath) + os.path.sep)== self.baseDir:
self.currentDirectory = ""
return self.currentDirectory return self.currentDirectory
else: else:
directories = self.currentDirectory.split("/") if len(str(parentpath).split('/')) < len(self.baseDir.split('/')):
strdirectory = "" return self.currentDirectory
for dir in directories: newpath = str(parentpath).replace(self.baseDir,'')
strdirectory += dir + "/" if os.path.exists(os.path.join(self.baseDir,newpath)):
strdirectory = strdirectory[:-3] self.currentDirectory = newpath
self.currentDirectory = strdirectory
return self.currentDirectory return self.currentDirectory
else: else:
dirName = self.sanitizeDirectory(dirName) dirName = self.sanitizeDirectory(dirName)
self.currentDirectory = os.path.join(self.currentDirectory, dirName) joinedDir = os.path.join(self.currentDirectory, dirName)
if os.path.join(self.baseDir, joinedDir):
self.currentDirectory = joinedDir
return self.currentDirectory return self.currentDirectory
def listCurrentDirectoryContent(self) -> str: def listCurrentDirectoryContent(self) -> str:
contents = os.listdir(self.currentDirectory) contents = os.listdir(os.path.join(self.baseDir, self.currentDirectory))
strdirectory = "" strdirectory = ""
for content in contents: for content in contents:
strdirectory += content + ", " strdirectory += content + ", "
strdirectory = strdirectory[:-1] strdirectory = strdirectory[:-1]
return strdirectory return strdirectory
def putFileInCurrentDirectory(self, filename: str, content) -> str: def putFileInCurrentDirectory(self, filename: str, content: bytes) -> str:
filename = self.sanitizeFile(filename) filename = self.sanitizeFile(filename)
currenctfile = os.path.join(self.currentDirectory, filename) currenctfile = os.path.join(self.baseDir, self.currentDirectory, filename)
f = open(currenctfile, "wb") f = open(currenctfile, "wb")
f.write(content) f.write(content)
f.close() f.close()
return currenctfile return currenctfile
def getFileInCurrentDirectory(self, file: str): def getFileInCurrentDirectory(self, file: str) -> bytes:
file = self.sanitizeFile(file) file = self.sanitizeFile(file)
currentfile = os.path.join(self.currentDirectory, file) currentfile = os.path.join(self.baseDir, self.currentDirectory, file)
return open(currentfile, "r") if os.path.exists(currentfile):
f = open(currentfile, "rb")
content = f.read()
f.close()
return content
else:
raise Exception('File not found')
def removeFileInCurrentDirectory(self, file: str) -> str: def removeFileInCurrentDirectory(self, file: str) -> str:
file = self.sanitizeFile(file) file = self.sanitizeFile(file)
currentfile = os.path.join(self.currentDirectory, file) if self.currentDirectory == "":
os.remove(currentfile) currentfile = os.path.join(self.baseDir, file)
else:
currentfile = os.path.join(self.baseDir, self.currentDirectory, file)
if os.path.exists(currentfile):
os.remove(currentfile)
return currentfile return currentfile

View File

@ -1,4 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from server import Server
if __name__ == '__main__': if __name__ == '__main__':
print("hi") server = Server()
server.initServer()
server.startServer()

View File

@ -1,20 +1,186 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import json
from base64 import b64encode, b64decode
import pyDH
from Crypto.Hash import SHA512
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import ChaCha20_Poly1305
from Crypto.PublicKey.RSA import RsaKey
from Crypto.Signature import pkcs1_15
from netsim import network_interface
from authentication import Authetication
class NetWrapper: class NetWrapper:
def __init__(self, publicKey: str, privateKey: str, cipherKey: str = ""): def __init__(self, clientPublicKey: dict, serverPrivateKey: RsaKey, authenticationInstance: Authetication):
self.publicKey = publicKey self.clientPublicKey = clientPublicKey
self.privateKey = privateKey self.currentClientPublicKey = "".encode('UTF-8')
self.cipherKey = cipherKey self.serverPrivateKey = serverPrivateKey
self.cipherkey = "".encode('UTF-8')
self.network = network_interface('./../../netsim/network/', 'A')
self.clientAddr = ""
self.currentUser = ""
self.homeDirectory = ""
self.authenticationInstance = authenticationInstance
def identifyServer(self): def encryptRSAMessage(self, message: bytes) -> bytes:
pass cipher_rsa = PKCS1_OAEP.new(self.currentClientPublicKey)
encrypted_msg = cipher_rsa.encrypt(message)
return encrypted_msg
def identifyCleint(self): def signRSAHeader(self, type: str, extradata: dict) -> (bytes, bytes):
pass mandatory = {'type': type, 'source': self.network.own_addr}
header = json.dumps({**mandatory, **extradata}).encode('UTF-8')
h = SHA512.new(header)
headersignature = pkcs1_15.new(self.serverPrivateKey).sign(h)
return header, headersignature
def sendMessage(self): def verifyRSAHeaderSignature(self, header: bytes, headersignature: bytes) -> bool:
pass h = SHA512.new(header)
try:
pkcs1_15.new(self.currentClientPublicKey).verify(h, headersignature)
return True
except Exception:
return False
def recieveMessage(self): def decryptRSAMessage(self, message: bytes) -> bytes:
pass cipher_rsa = PKCS1_OAEP.new(self.serverPrivateKey)
return cipher_rsa.decrypt(message)
def serverIdentify(self, msg: bytes) -> None:
incommingJson = json.loads(msg.decode('UTF-8'))
header = json.loads(b64decode(incommingJson['header']).decode('UTF-8'))
self.clientAddr = header['source']
self.currentUser = header['username']
self.currentClientPublicKey = self.clientPublicKey[self.currentUser]
if not self.verifyRSAHeaderSignature(b64decode(incommingJson['header']),
b64decode(incommingJson['headersignature'])) or header[
'type'] != 'IDY':
raise Exception('Bad initial message')
retheader, retheadersignature = self.signRSAHeader("IDY", {})
dcryptedmsg = self.decryptRSAMessage(b64decode(incommingJson['message']))
retmsg = self.encryptRSAMessage(dcryptedmsg)
identMsg = json.dumps(
{'header': b64encode(retheader).decode('UTF-8'),
'headersignature': b64encode(retheadersignature).decode('UTF-8'),
'message': b64encode(retmsg).decode('UTF-8')}).encode(
'UTF-8')
self.network.send_msg(self.clientAddr, identMsg)
def sendMessage(self, message: bytes) -> None:
self.sendTypedMessage(message, "CMD")
def sendTypedMessage(self, message: bytes, type: str) -> None:
if not (type == "AUT" or type == "CMD"):
raise Exception('Unknown message type')
cipher = ChaCha20_Poly1305.new(key=self.cipherkey)
header = json.dumps({'source': self.network.own_addr, 'type': type}).encode('UTF-8')
cipher.update(header)
ciphertext, tag = cipher.encrypt_and_digest(message)
nonce = b64encode(cipher.nonce).decode('UTF-8')
ct = b64encode(ciphertext).decode('UTF-8')
b64tag = b64encode(tag).decode('UTF-8')
sendjson = json.dumps(
{'header': b64encode(header).decode('UTF-8'), 'nonce': nonce, 'message': ct, 'tag': b64tag}).encode(
'UTF-8')
self.network.send_msg(self.clientAddr, sendjson)
def keyExchange(self) -> None:
dh = pyDH.DiffieHellman()
mypubkey = self.encryptRSAMessage(str(dh.gen_public_key()).encode('UTF-8'))
header, headersignature = self.signRSAHeader("DH", {})
jsonmsg = json.dumps(
{'header': b64encode(header).decode('UTF-8'), 'headersignature': b64encode(headersignature).decode('UTF-8'),
'message': b64encode(mypubkey).decode('UTF-8')}).encode('UTF-8')
self.network.send_msg(self.clientAddr, jsonmsg)
status, msg = self.network.receive_msg(blocking=True)
if not status:
raise Exception('Network error during connection.')
decodedmsg = json.loads(msg.decode('UTF-8'))
header = json.loads(b64decode(decodedmsg['header']).decode('UTF-8'))
if not self.verifyRSAHeaderSignature(b64decode(decodedmsg['header']),
b64decode(decodedmsg['headersignature'])) or not (
header['source'] == self.clientAddr and header['type'] == 'DH'):
raise Exception('Header signature error')
clientpubkey = int(self.decryptRSAMessage(b64decode(decodedmsg['message'])).decode('UTF-8'))
cipherkey = dh.gen_shared_key(clientpubkey).encode('UTF-8')
hasher = SHA512.new()
hasher.update(cipherkey)
self.cipherkey = (hasher.hexdigest()[:32]).encode('UTF-8')
def login(self) -> bool:
status, msg = self.network.receive_msg(blocking=True)
if not status:
raise Exception('Network error during connection.')
cleartext = self.recieveEncryptedMessage(msg, "AUT").decode('UTF-8')
if cleartext == "ERROR":
return False
else:
plaintext = cleartext.split(' ')
self.homeDirectory = self.authenticationInstance.login(plaintext[1], plaintext[2])
linsuccess = (not (len(plaintext) != 3 or plaintext[0] != "LIN" or plaintext[
1] != self.currentUser)) and self.homeDirectory
if linsuccess:
message = "OK".encode('UTF-8')
else:
message = "ERROR".encode('UTF-8')
self.sendTypedMessage(message, "AUT")
return linsuccess
def initClientConnection(self, msg: bytes) -> bytes:
print('A client is trying to connect')
try:
print('Server and Client identity verification started')
self.serverIdentify(msg)
print('Key exchange started')
self.keyExchange()
print('Authorization started')
success = self.login()
print(f'Authorization completed, success: {success}')
if success:
return "LINOK".encode('UTF-8')
else:
self.logout()
return "LINERROR".encode('UTF-8')
except Exception:
print("Error ecountered, resetting")
self.logout()
return "LINERROR".encode('UTF-8')
def recieveMessage(self) -> bytes:
status, msg = self.network.receive_msg(blocking=True)
if not status:
raise Exception('Network error during connection.')
if not self.clientAddr:
return self.initClientConnection(msg)
else:
return self.recieveEncryptedMessage(msg, "CMD")
def logout(self) -> None:
self.clientAddr = ""
self.cipherkey = "".encode('UTF-8')
self.currentClientPublicKey = "".encode('UTF-8')
self.currentUser = ""
self.homeDirectory = ""
def recieveEncryptedMessage(self, msg: bytes, type: str) -> bytes:
if not (type == "AUT" or type == "CMD"):
raise Exception('Unknown message type')
try:
b64 = json.loads(msg.decode('UTF-8'))
retheader = json.loads(b64decode(b64['header']).decode('UTF-8'))
retnonce = b64decode(b64['nonce'])
retciphertext = b64decode(b64['message'])
rettag = b64decode(b64['tag'])
retcipher = ChaCha20_Poly1305.new(key=self.cipherkey, nonce=retnonce)
retcipher.update(b64decode(b64['header']))
plaintext = retcipher.decrypt_and_verify(retciphertext, rettag)
if not (retheader['source'] == self.clientAddr and retheader['type'] == type):
return "ERROR".encode('UTF-8')
else:
return plaintext
except Exception:
print("Incorrect decryption")
return "ERROR".encode('UTF-8')

View File

@ -1,84 +1,127 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os
from authentication import Authetication
from executor import Executor from executor import Executor
from netwrapper import NetWrapper
class Server: class Server:
def __init__(self, homeDirectory: str = "", sessionTimeout: int = 120, availableServer: bool = True, def __init__(self, sessionTimeout: int = 120, availableServer: bool = True):
currentDirectory: str = ""):
self.isAuthenticated = False self.isAuthenticated = False
self.homeDirectory = homeDirectory
self.sessionTimeout = sessionTimeout self.sessionTimeout = sessionTimeout
self.availableServer = availableServer self.availableServer = availableServer
if currentDirectory == "": self.executor = Executor("")
self.currentDirectory = homeDirectory self.auth = Authetication()
else:
self.currentDirectory = currentDirectory
self.executor = Executor(homeDirectory)
def login(self, username: str, password: str) -> bool: def initServer(self):
pass print("Please enter your private key passphrase")
passphrase = input()
self.networkInstance = NetWrapper(self.auth.loadUserPublicKeys(), self.auth.loadServerPrivateKey(passphrase),
self.auth)
def login(self, homeDir: str) -> None:
self.isAuthenticated = True
self.executor = Executor(homeDir + os.path.sep)
def logout(self) -> None: def logout(self) -> None:
pass self.networkInstance.logout()
self.isAuthenticated = False
self.availableServer = False
self.executor = Executor("")
def parseCommand(self, command: str) -> str: def parseCommand(self, command: str) -> None:
if command == "LINOK":
self.login(self.networkInstance.homeDirectory)
self.networkInstance.sendMessage("OK".encode('UTF-8'))
return None
elif command == "LINERROR":
return None
elif command == "ERROR":
self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
return None
parsedCommand = command.split(" ") parsedCommand = command.split(" ")
if len(parsedCommand) > 3: if len(parsedCommand) > 3:
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
# TODO: Ez igy gecironda, ezt meg kene csinalni rendesen.
elif len(parsedCommand) == 1: elif len(parsedCommand) == 1:
return self.execute(parsedCommand[0]) self.execute(parsedCommand[0])
elif len(parsedCommand) == 2: elif len(parsedCommand) == 2:
return self.execute(parsedCommand[0], parsedCommand[1]) self.execute(parsedCommand[0], parsedCommand[1])
elif len(parsedCommand) == 3: elif len(parsedCommand) == 3:
return self.execute(parsedCommand[0], parsedCommand[1], parsedCommand[2]) self.execute(parsedCommand[0], parsedCommand[1], parsedCommand[2])
def execute(self, command: str, firstParam: str = "", secondParam: str = "") -> str: def execute(self, command: str, firstParam: str = "", secondParam: str = "") -> None:
if self.homeDirectory == "" or self.currentDirectory == "" or self.executor.currentDirectory == "" or self.executor.baseDir == "": if self.executor.baseDir == "":
raise Exception("Directories must not be empty string. Did the user log in?") raise Exception("Home directory must not be empty string. Did the user log in?")
if command == "MKD": if command == "LOUT":
if secondParam != "": if not (secondParam == "" and firstParam == ""):
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
return self.executor.createDirectory(firstParam) self.networkInstance.sendMessage("OK".encode('UTF-8'))
self.logout()
elif command == "MKD":
if secondParam != "":
self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else:
self.executor.createDirectory(firstParam)
self.networkInstance.sendMessage("OK".encode('UTF-8'))
elif command == "RMD": elif command == "RMD":
if secondParam != "": if secondParam != "":
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
return self.executor.removeDirectory(firstParam) self.executor.removeDirectory(firstParam)
self.networkInstance.sendMessage("OK".encode('UTF-8'))
elif command == "GWD": elif command == "GWD":
if secondParam != "" or firstParam != "": if not (secondParam == "" and firstParam == ""):
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
return self.executor.getCurrentDirectory() self.networkInstance.sendMessage(self.executor.getCurrentDirectory().encode('UTF-8'))
elif command == "CWD": elif command == "CWD":
if secondParam != "": if secondParam != "":
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
return self.executor.setCurrentDirectory(firstParam) self.executor.setCurrentDirectory(firstParam)
self.networkInstance.sendMessage("OK".encode('UTF-8'))
elif command == "LST": elif command == "LST":
if secondParam != "" or firstParam != "": if not (secondParam == "" and firstParam == ""):
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
return self.executor.listCurrentDirectoryContent() self.networkInstance.sendMessage(self.executor.listCurrentDirectoryContent().encode('UTF-8'))
elif command == "RMF": elif command == "RMF":
if secondParam != "": if secondParam != "":
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
return self.executor.removeFileInCurrentDirectory(firstParam) self.executor.removeFileInCurrentDirectory(firstParam)
self.networkInstance.sendMessage("OK".encode('UTF-8'))
elif command == "UPL": elif command == "UPL":
if secondParam != "": if secondParam != "":
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
# TODO fileMessage = self.networkInstance.recieveMessage()
pass eof = self.networkInstance.recieveMessage().decode('UTF-8')
if eof == "EOF":
self.executor.putFileInCurrentDirectory(firstParam, fileMessage)
self.networkInstance.sendMessage("OK".encode('UTF-8'))
else:
self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
elif command == "DNL": elif command == "DNL":
if secondParam != "": if secondParam != "":
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
# TODO try:
pass file = self.executor.getFileInCurrentDirectory(firstParam)
self.networkInstance.sendMessage(file)
self.networkInstance.sendMessage("EOF".encode('UTF-8'))
except Exception:
self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
else: else:
return "ERROR" self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
def startServer(self):
while True:
try:
message = self.networkInstance.recieveMessage().decode('UTF-8')
self.parseCommand(message)
except Exception as e:
self.networkInstance.sendMessage("ERROR".encode('UTF-8'))
print(e)