diff --git a/AATC_Config.py b/AATC_Config.py index cc7be40..65decf9 100644 --- a/AATC_Config.py +++ b/AATC_Config.py @@ -1,16 +1,41 @@ -PRE_SHARED_ENCRYPTION_KEYS_ENABLE = False -PRE_SHARED_AES_KEY = b"00000000000000000000000000000000" -PRE_SHARED_IV_KEY = b"00000000000000000000000000000000" +SERVER_NAME = "AATC" +SERVER_PRIVATE_KEY = b'0\x82\t)\x02\x01\x00\x02\x82\x02\x01\x00\x9a`\xfa\xdf\x0e%\x8bv\x82\x94v\xe1gt\xafK\'\xa1\x87l\xef\xaeV\xc5\x9e\xfb\x8e\x00\xbal1u\xab\xbe\x92"\xd6\t\xad\x12\xdbx4\x0c\x9d\xdb\xf9\xcf\x08\x8au+\xa8[n\x1b\x86i\xb76N~\x82\xcf\xdd\xd0\xa1c\xb7\xbf\xbcT\x93\x9fT\x1c\xbb\x85\xf2\xd5\xa6\xfbx,\xf1i\xecv{\x85\x92\xd6\xc5a\x168\x93.\xa4t`\x06D\xbd\x969\xba\xec\xda<&\xaf\x8d\xb0\xc6\x99\xb6k\x86\x96\x0c\x19\x0b\x1a\x82T\x1c\xcbI\xe4P\x00\xd0\x0f\x9eP\x1cw\x06\xc1\x18\x1b\xc46g\xe2\xd8iSy\xc2?\tP\xef\xd1jlf\x97C?\xfa*\x92\x1c\xd8\xf0l\x02\xd3\xc2W7\xc4\xd8\xb2\xd2\xa5\x00?\xe9K\xce\x0e\xc0\xa3\x8c\xc7\xee\xd8\x9aq\xe0\xe2n6~\xd9-_OE]Ui9w#\x7f\xf9\x11QE\xb9^/\xdc0=\x9d\x12+nU\xd4\xc6H\xebAK\x010)OV\xab3\x1b\x0f\xe8\xa99\xbe\x18\xab\xadE\x9cs\xd7\x1co\xa3FD\xcf\x96\x88\xb6\xcay\x02\xcb!\x97x{\x13\x80\'\xdd\\\x1awL\xd63\xb4\x85\xa3\x10\xf9\xe8s\xa6\xb6\xd5\xd8P\xba\xe1\x81\x07Az4\x8f\x94\x9aR\x89\xae\xb4\x18\x9b9Q\xfeVe\xb4\xf7\xfe\xb1\xa0\xd3j5\x89 r\x92\xc0\x06\xbd\xa4sf\xdc\xd0y:=M0\xe2Y\xeez\xe2^\xd0?\xd8\xf6\xe1\xa62\x840\x91d\x99\xf7{\x909\xf4\xe4\xcd\x8c\x02\x03{\x1e\xe7]\xe4\xc4 \x94 \xe5\xcbw4\xbf\xc7\xe7J\xba\x1a\xf9\x13\xedN\xff\x85UA\xcf%V\xa8\xfa0I\xb5\x05%\x9bo@\xae]\x82\xb1-\xe1\x87\x82z\xfb\x9bA\xd8\x991\xceNx\x91\xba\x87`\x1c\x9f\xc5Y+\x8b\x87[\xd1\xb8)\x92\xb0\xfc\xee\xb7\xd1\xcf\xa1OF\xc0;\xf3\xf2\xe9\xbez"\xaf\xd3\xd4\xa4\xddG\xb0]ro\xf7\x82\xfc\x1a\xf1\xed\xb92$\xcbd%j\x98\xcbd\x7f\x1b!\xc6l\xd2<\x9d8\x97\xe5\xa0\xac\xc7G\xb9\xda\x90\xce~\xb1\xc1\xab\xe2\xcd\xef\x8d\xf8g\xd1I\x02\x03\x01\x00\x01\x02\x82\x02\x00\x0e!7\xf8\xfc8\x1c\xbf\x8a4Y<\xa8}\xce1\x06e\xb3\t\xda\x16\xa6\x7f\xc4=A:)\x15\xef\xc1u\xc8\x95\xa2\xcd]\x19\x9b\x97\x1d\x95\x82\xfd\x9cU\x8d\x18\xda\xa6^\x8atb\xdb\xafU\xe3\xf4[#\x1ai8\xe3\xc8o\xc2p\xd0\xc5\x9bt\xda\xeb\x9d\xd0\xc4\xe0\xff\xfdvz\x83\x96\x96\xb3a\xfb\x1f\xed[\'\xb7\x93RJS\xb8H\x95.K\xbdq\x17~\'\xfb\xd7-\x1c~|p\xf3x\xbc:\xe5\xcc\xd1~\xb9\xc4\xc5\xd5g\xf4\x17\x0b\xf9\xff!\xf5\xf2c\x05\t\xdd\xa1e\xf86R5\x8dO[\xfe\xb6\xcb\r\x1e\xc4\x17\xb5\xe7\xfej\x83\xf3\xab[\x8f\xfb\x1d\xa7?+\x7fWA\x06\x19\xf0\xe5\x15\x7f\xd49\xaf\xcb\xe2\x7f\x08\x81!H\x07\xc8|\t\x91\xa3\xf5\x86.\xed\xc7\x92Ov\x9bS\x8c\x14N\xda\x1e\xd3rQ;\xc6\x06\x82\xa4b1K\tQZ\x17\x05V\x85|\xc6\x87\x0bo\xce\x80\x8f\xdf\x17\xb8!+\x02\xfbV\x91\xf9\x04\x1c\xed\x9f\xd7\xcd\x12\x80B\xf5\xe1\xff\xb7 \xb9\xe19\xa8>\xe0,\xd9U\x92\xd9r\x9aU\xc5\xa5\xe7U\x0b\x87\xd7\xa3-\xdb\xd0\xeeH`\xdbrJ\xc1\xfc^\xe6\\\xea\t\x14\x8e\x15\x01\xb1\xe4\xa9he\xac\xa7;\xf6\xc5\xc6\xa7X,\xcb"\xe3\x98\x94eOs\xab\x91\x0c&/\xa8\xfd}\xc1O\xa8MA\xef\xb2B\x95\xffP\xfff\xed\x1b\xdd+"\xac\xbd\x98\x0b{\x02\xab\x0eh\x9d"}\xa8\xe3\xc46E\x0ex\xc2\xe9\xea:\xaa\xe4\x89\x0f\x01\xfd\xb3^\xfb\x85\xb3\xa1?IZ]\x15\x14lv>7\x96\xeb\xc4\xc6\x0b.\r\xac@-.\xb2\xb3\xc7\n\x0f6\x97.\xe2\xce\xff\x90\x86\xd8s\xb3\x18\xebVA\x82\xc8\x1d;\xdf"\xfc#\x7f\x98`\x1e\xc2\xeb%\x97W\xae\x99H\x90\x9a\xe2\xf3\x0c\xca\xc9\xa5\x9c\xdb?V\xe5\xa5\xaf\xe4\xe0\x0f\xfcZj\xab\x0e\xf1\x02\x82\x01\x01\x00\x88\xd8\xda:\x97\x1c\x1e\x1b3o\xbe\x01\x00\xdc\x84\xa48\xd12\xed\x0e\x972\x96\xc9\x02<\xc3\xf1\xd5\x98\xcf\x8e\xf8\xe0\xb4\xf0C\x92\x14\xedq\xf8\r#\xe5$[\x1a\x14\x17\xdd\xdd\x9d!\xb1\x82\xc1\xa1\\\xa0\xa9\xad\x9d(\xe4\xb7\xfd\xb5\xbd\x98\xb0n\xf4g\xb4$\x11\xc0\xd8;\x122\xfa\t\r^B\x1c\x94\xd1\x97Y\xd0\x96\xd1\xa9@\x14Q\x8f\x15\xa9\xb2\xf5:~o\xf2/Qo\xd2%\xa8\xeb\x95\xec6\xb2\x00m_o\xdeF{k\x17Y\xca)\x1f\xc6\xddz\xb2\xefY;\x92\rxRI\xff\xd2\xc9\x05q\x1aHh\xaeI\xdf\xab\xc3\xc5)\xd5P\xe4\x82N\x0b\xfb\x81\x02\x82\x01\x00\x07\x9f\x0b\x02\xc5\xb4\xd2\xbdRy\xf4aq\xa3\xf5\xce\x17\r\xb6\x13\xf9\xed}\xbc\xf9\xfe\\\xb2\x8f\xee\x1f\xf4\xbb\xbe\x8d\xee:\xb4\xeb%\xbf2ya\x9f\x87\x88\xe0]\xa1\x9a{\xdd\xb5\x04,4V\xe8\xd1\xfd\'I\xc18\xedG\x88\xe1<\xd7\xda\x1b\x19\xef\xad\xc2{\x9e\x13\xdb\xc3%b\xe5\x12CJ\xc0F\xd1\xbd\xd4\xcd|\xff2I;mp\xaa\x05X\xf8\xedNI\x93\xca\x91\xd9\x83\x8e\x04\xe2|\xf5\xa1O\xfbq~;\xb0o\xb0-\x03\xca\x1a\xc25is\xb0F\xc0L\xe5U\xb20!g&c\xb9\x19\xc6[o8{\x87a\xfe<\xfb\x8c\xc4U\x18Bz\xe8D\xdfd9\x88\xe9\xfa\x9f|\x8f\x1f#U\xad\xbf\xe2\x17\x12\xd4\xff\x05\x83FV=\xab\x06x\xc6\xe4>?\x9aMFg\x85]K\xc2\xd4\x02\x88J\x87\x89`\x1a\xac\xcb\xa9\x03\x05\xcb^\xf5i\x00\xce%\x00H, \xa9~\xdd\x8e\x9b{,\x82\x04Z\x94\xd7\xd2\xbe\xd7\x94b\x1bJ*yP\x8c\xe76\xd4' + + +SET_ENCRYPTION_KEYS_ENABLE = False +SET_AES_KEY = b"00000000000000000000000000000000" +SET_IV_KEY = b"00000000000000000000000000000000" + DEFAULT_AES_KEYSIZE = 32 ALLOWED_AES_KEYSIZES = [16,24,32] - DEFAULT_RSA_KEYSIZE = 2048 +ENCRYPTION_USE_PRESHARED_KEYS = False +AUTO_GENERATE_FALLBACK = False +CERTIFICATES = { + "AATC":[ + { + "ServerName":"AATC", + "NotBefore":1, + "NotAfter":1000000000, + "PublicKey":b'0\x82\x02"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\x9a`\xfa\xdf\x0e%\x8bv\x82\x94v\xe1gt\xafK\'\xa1\x87l\xef\xaeV\xc5\x9e\xfb\x8e\x00\xbal1u\xab\xbe\x92"\xd6\t\xad\x12\xdbx4\x0c\x9d\xdb\xf9\xcf\x08\x8au+\xa8[n\x1b\x86i\xb76N~\x82\xcf\xdd\xd0\xa1c\xb7\xbf\xbcT\x93\x9fT\x1c\xbb\x85\xf2\xd5\xa6\xfbx,\xf1i\xecv{\x85\x92\xd6\xc5a\x168\x93.\xa4t`\x06D\xbd\x969\xba\xec\xda<&\xaf\x8d\xb0\xc6\x99\xb6k\x86\x96\x0c\x19\x0b\x1a\x82T\x1c\xcbI\xe4P\x00\xd0\x0f\x9eP\x1cw\x06\xc1\x18\x1b\xc46g\xe2\xd8iSy\xc2?\tP\xef\xd1jlf\x97C?\xfa*\x92\x1c\xd8\xf0l\x02\xd3\xc2W7\xc4\xd8\xb2\xd2\xa5\x00?\xe9K\xce\x0e\xc0\xa3\x8c\xc7\xee\xd8\x9aq\xe0\xe2n6~\xd9-_OE]Ui9w#\x7f\xf9\x11QE\xb9^/\xdc0=\x9d\x12+nU\xd4\xc6H\xebAK\x010)OV\xab3\x1b\x0f\xe8\xa99\xbe\x18\xab\xadE\x9cs\xd7\x1co\xa3FD\xcf\x96\x88\xb6\xcay\x02\xcb!\x97x{\x13\x80\'\xdd\\\x1awL\xd63\xb4\x85\xa3\x10\xf9\xe8s\xa6\xb6\xd5\xd8P\xba\xe1\x81\x07Az4\x8f\x94\x9aR\x89\xae\xb4\x18\x9b9Q\xfeVe\xb4\xf7\xfe\xb1\xa0\xd3j5\x89 r\x92\xc0\x06\xbd\xa4sf\xdc\xd0y:=M0\xe2Y\xeez\xe2^\xd0?\xd8\xf6\xe1\xa62\x840\x91d\x99\xf7{\x909\xf4\xe4\xcd\x8c\x02\x03{\x1e\xe7]\xe4\xc4 \x94 \xe5\xcbw4\xbf\xc7\xe7J\xba\x1a\xf9\x13\xedN\xff\x85UA\xcf%V\xa8\xfa0I\xb5\x05%\x9bo@\xae]\x82\xb1-\xe1\x87\x82z\xfb\x9bA\xd8\x991\xceNx\x91\xba\x87`\x1c\x9f\xc5Y+\x8b\x87[\xd1\xb8)\x92\xb0\xfc\xee\xb7\xd1\xcf\xa1OF\xc0;\xf3\xf2\xe9\xbez"\xaf\xd3\xd4\xa4\xddG\xb0]ro\xf7\x82\xfc\x1a\xf1\xed\xb92$\xcbd%j\x98\xcbd\x7f\x1b!\xc6l\xd2<\x9d8\x97\xe5\xa0\xac\xc7G\xb9\xda\x90\xce~\xb1\xc1\xab\xe2\xcd\xef\x8d\xf8g\xd1I\x02\x03\x01\x00\x01' + }, + ], + + + + } + + + + + DEFAULT_DRONE_BATTERY_VALUE = 100 DEFAULT_DRONE_ATWAYPOINT_SIZES = (0.001,0.001,5) DEFAULT_DRONE_COORDINATE = (0,0,0) +DRONE_BATTERY_DRAIN_MULT = 1 -DRONE_BATTERY_DRAIN_MULT = 1 +NOFLYZONE_THRESHOLD_COST = 50 diff --git a/AATC_Crypto.py b/AATC_Crypto.py index d99635d..481cbd0 100644 --- a/AATC_Crypto.py +++ b/AATC_Crypto.py @@ -1,5 +1,5 @@ #AATC crypto module -import codecs,recvall,ast,binascii,os,AATC_Config +import codecs,recvall,ast,binascii,os,AATC_Config,time from Crypto.Cipher import AES,PKCS1_OAEP from Crypto.PublicKey import RSA @@ -21,11 +21,8 @@ class Crypter: """ def __init__(self, con, mode = "CLIENT",AutoGenerate = True): self.con = con - self.SetMode(mode) - if AATC_Config.PRE_SHARED_ENCRYPTION_KEYS_ENABLE: #Allows preshared encryption keys to be used - self.SetEncryptionKeys(AATC_Config.PRE_SHARED_AES_KEY, AATC_Config.PRE_SHARED_IV_KEY) - - elif AutoGenerate: + self.SetMode(mode) + if AutoGenerate: self.GenerateKey() def SetMode(self,mode): @@ -44,33 +41,77 @@ def GenerateKey(self,key_size = AATC_Config.DEFAULT_RSA_KEYSIZE): def ClientGenerateKey(self,RSA_KeySize,AES_KeySize= AATC_Config.DEFAULT_AES_KEYSIZE): + + self.Send(("GetServerName",())) + Sucess,Message,Data = self.SplitData(self.Recv()) + if not Sucess: + raise ValueError("Server did not recognise command"+Message) + ServerName = Data[0] + + if AATC_Config.SET_ENCRYPTION_KEYS_ENABLE: #Allows preshared encryption keys to be used + self.SetEncryptionKeys(AATC_Config.SET_AES_KEY, AATC_Config.SET_IV_KEY) + + elif AATC_Config.ENCRYPTION_USE_PRESHARED_KEYS: + self.ClientPreSharedKeys(ServerName,RSA_KeySize,AES_KeySize) + + else: + self.ClientExchangeKeys(RSA_KeySize,AES_KeySize) + + + + + self.Send(("Exit",())) + Sucess,Message,Data = self.SplitData(self.Recv()) + if not Sucess: + raise Exception("Server failed to exit"+Message) + + + + def ClientPreSharedKeys(self,ServerName,RSA_KeySize,AES_KeySize): + AESKey,IV = GenerateKeys(AES_KeySize) + Certificate = GetCertificates(ServerName) + + if Certificate: + publicKey = Certificate["PublicKey"] + PKO = PKCS1_OAEP.new(RSA.import_key(publicKey)) + EncryptedAESKey = PKO.encrypt(AESKey) + EncryptedIV = PKO.encrypt(IV) + self.SetEncryptionKeys(AESKey,IV) + self.Send(("SetKey",(EncryptedAESKey,EncryptedIV))) + data = self.Recv() + + + else: + print("No Valid Certificates found") + if AATC_Config.AUTO_GENERATE_FALLBACK: + self.ClientExchangeKeys(RSA_KeySize,AES_KeySize) + else: + raise Exception("No valid certificate found. Exception raised") + + + + def ClientExchangeKeys(self,RSA_KeySize,AES_KeySize): RSAKey = RSA.generate(RSA_KeySize) privateKey = RSAKey.exportKey("DER") publicKey = RSAKey.publickey().exportKey("DER") - self.Send(("ExchangeKey",(publicKey,AES_KeySize))) #Format ("ExchangeKey",("a1b2c3.....",)) - data = self.Recv() - Sucess,Message = data[0],data[1] #Format (Sucess,("a2c3d4...")) - if Sucess == False: - raise Exception("Error occured while exchanging keys") - - self.Send(("Exit",())) - data = self.Recv() - if data[0] == False: - raise Exception("Server failed to commit to exit") + self.Send(("GenerateKey",(publicKey,AES_KeySize))) + Sucess,Message,data = self.SplitData(self.Recv()) RSAPrivateKey = RSA.import_key(privateKey) RSAPrivateObject = PKCS1_OAEP.new(RSAPrivateKey) - self.AESKey = RSAPrivateObject.decrypt(Message[0]) - self.IV = RSAPrivateObject.decrypt(Message[1]) - - self.SetEncryptionKeys(self.AESKey,self.IV) - + AESKey = RSAPrivateObject.decrypt(data[0]) + IV = RSAPrivateObject.decrypt(data[1]) + if Sucess == False: + raise Exception("Error occured while exchanging keys") + + self.SetEncryptionKeys(AESKey,IV) + ################################################################ def ServerGenerateKey(self): @@ -79,29 +120,59 @@ def ServerGenerateKey(self): data = self.Recv() Command, Arguments = data[0],data[1] - if Command == "ExchangeKey": - publicKey,AES_KeySize = Arguments[0],Arguments[1] - if AES_KeySize not in AATC_Config.ALLOWED_AES_KEYSIZES: - AES_KeySize = AATC_Config.DEFAULT_AES_KEYSIZE #If key size is not valid set size to default of AATC_Config.DEFAULT_AES_KEYSIZE - - self.AESKey = binascii.b2a_hex(os.urandom(AES_KeySize//2)) # Here to allow regeneration of AES key while still in loop if required. - self.IV = binascii.b2a_hex(os.urandom(AES_KeySize//2)) - - RSAPrivateKey = RSA.import_key(publicKey) - PublicKeyObject = PKCS1_OAEP.new(RSAPrivateKey) + if Command == "GenerateKey": + Sucess,Message,Data = self.ServerGenerateKeys(Arguments) + + elif Command == "GetServerName": + Sucess,Message,Data = self.GetServerName(Arguments) + + elif Command == "SetKey": + Sucess,Message,Data = self.ServerSetKey(Arguments) - EncryptedAESKey = PublicKeyObject.encrypt(self.AESKey) - EncryptedIV = PublicKeyObject.encrypt(self.IV) - self.Send((True,(EncryptedAESKey,EncryptedIV))) elif Command == "Exit": - self.Send((True,())) + Sucess,Message,Data = True,"Exiting",[] Exit = True else: - self.Send((False,("Command does not exist",))) + Sucess,Message,Data = False,"Command does not exist",[] - self.SetEncryptionKeys(self.AESKey,self.IV) + self.Send((Sucess,Message,Data)) + + + + + def ServerGenerateKeys(self,Arguments): + publicKey,AES_KeySize = Arguments[0],Arguments[1] + + if AES_KeySize not in AATC_Config.ALLOWED_AES_KEYSIZES: + AES_KeySize = AATC_Config.DEFAULT_AES_KEYSIZE #If key size is not valid set size to default of AATC_Config.DEFAULT_AES_KEYSIZE + + AESKey,IV = GenerateKeys(AES_KeySize) + + PublicKeyObject = PKCS1_OAEP.new( RSA.import_key(publicKey)) + + EncryptedAESKey = PublicKeyObject.encrypt(AESKey) + EncryptedIV = PublicKeyObject.encrypt(IV) + + self.SetEncryptionKeys(AESKey,IV) + return True,"Instated encryption keys",[EncryptedAESKey,EncryptedIV] + + def GetServerName(self,Arguments = None): + return True,"Server Name",[AATC_Config.SERVER_NAME] + + def ServerSetKey(self,Arguments): + PKO = PKCS1_OAEP.new(RSA.import_key(AATC_Config.SERVER_PRIVATE_KEY)) + AESKey,IV = Arguments[0],Arguments[1] + AESKey,IV = PKO.decrypt(AESKey),PKO.decrypt(IV) + self.SetEncryptionKeys(AESKey,IV) + return True,"Keys set",[] + + + + + + ############################################### def SetEncryptionKeys(self,AESKey,IV): @@ -116,16 +187,29 @@ def SetEncryptionKeys(self,AESKey,IV): + + + + + + + + + + + + + + + + + def Encrypt(self,data): -## pad_size = 16-len(data)%16 -## data += b" "*pad_size return self.EncryptAES.encrypt(data) def Decrypt(self,data): -## pad_size = 16-len(data)%16 # - should not be nessesary as data will come in 16 size blocks and change in message would thwart decryption. -## data += b" "*pad_size return self.DecryptAES.decrypt(data) @@ -136,6 +220,38 @@ def Send(self,data): def Recv(self): data = recvall.recvall(self.con) data = ast.literal_eval(codecs.decode(data)) - # (Command,Arguments) return data + def SplitData(self,data): + return data[0],data[1],data[2] + + + + + +def GenerateKeys(AES_KeySize): + AESKey = binascii.b2a_hex(os.urandom(AES_KeySize//2)) # Here to allow regeneration of AES key while still in loop if required. + IV = binascii.b2a_hex(os.urandom(AES_KeySize//2)) + return AESKey,IV + +def GetCertificates(ServerName): + Certificates = AATC_Config.CERTIFICATES.get(ServerName) + if Certificates == None: + return False + + found = False + for Certificate in Certificates: + if Validate(Certificate): + found = True + break + + if not found: + return False + + return Certificate + +def Validate(Certificate): + if Certificate["NotBefore"] <= time.time() and Certificate["NotAfter"] >= time.time(): + return True + else: + return False