From a59319996c3318fe88692b4383be5dc4e900da2b Mon Sep 17 00:00:00 2001 From: lionel Date: Tue, 30 Aug 2016 15:36:53 +0200 Subject: [PATCH] Romulus + secured HeartBeat (to be improved) client : used to simulated HB on Remus key : cipher example --- another.py | 51 -- client | 29 + key | 17 + .../daemon/__pycache__/runner.cpython-34.pyc | Bin 9875 -> 9860 bytes modules/daemon/runner.py | 2 +- .../pydes/__pycache__/pyDes.cpython-34.pyc | Bin 0 -> 24421 bytes modules/pydes/pyDes.py | 852 ++++++++++++++++++ remus | 95 ++ romulus | 129 +++ 9 files changed, 1123 insertions(+), 52 deletions(-) delete mode 100755 another.py create mode 100755 client create mode 100755 key create mode 100644 modules/pydes/__pycache__/pyDes.cpython-34.pyc create mode 100644 modules/pydes/pyDes.py create mode 100755 remus create mode 100755 romulus diff --git a/another.py b/another.py deleted file mode 100755 index 317d8cf..0000000 --- a/another.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python3 -# -*- coding:Utf-8 -*- - -import os,sys,inspect # for the following -cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"modules"))) -if cmd_subfolder not in sys.path: - sys.path.insert(0, cmd_subfolder) - -import lockfile # daemonization -from daemon import runner # daemonization - - -from multiprocessing import Process - -def start(): - with context: - pidfile = open(Config.WDIR+scriptname+".pid",'w') - pidfile.write(str(getpid())) - pidfile.close() - feed_the_db() - -def stop(pid): - try: - kill(int(pid),15) - except ProcessLookupError: - print("Nothing to kill… (No process with PID "+pid+")") - -if __name__ == "__main__": - scriptname = sys.argv[0] - context = daemon.DaemonContext( - working_directory=Config.WDIR, - pidfile=lockfile.FileLock(Config.WDIR+scriptname), - stdout=sys.stdout, - stderr=sys.stderr) - try: - if sys.argv[1] == 'start': - start() - elif sys.argv[1] == 'stop': - try: - pidfile = open(Config.WDIR+scriptname+".pid",'r') - pid = pidfile.read() - pidfile.close() - remove(name+".pid") - print(name+" (PID "+pid+")") - stop(pid) - except FileNotFoundError: - print("Nothing to kill… ("+scriptname+".pid not found)") - else: - print("\nUnknown option : "+sys.argv[1]+"\n\nUsage "+sys.argv[0]+" \n") - except IndexError: - print("\nUsage "+sys.argv[0]+" \n") diff --git a/client b/client new file mode 100755 index 0000000..e9e342a --- /dev/null +++ b/client @@ -0,0 +1,29 @@ +#!/usr/bin/python3 + +import socket +import os,sys,inspect # for the following +cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"modules"))) +if cmd_subfolder not in sys.path: + sys.path.insert(0, cmd_subfolder) + +from pydes import pyDes # DES encryption + +TCP_IP = '127.0.0.1' +TCP_PORT = 5005 +BUFFER_SIZE = 1024 +MESSAGE = bytes("HB", 'UTF-8') + +k = pyDes.des(b"DEADJACK", pyDes.CBC, b"\2\2\2\2\2\2\2\2", pad=None, padmode=2) +MESSAGE = k.encrypt(MESSAGE) + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect((TCP_IP, TCP_PORT)) +s.send(MESSAGE) +data = s.recv(BUFFER_SIZE) +#data = s.recv(BUFFER_SIZE).decode('UTF-8') +s.close() + +data = k.decrypt(data).decode('UTF-8') + +print("sent data:", MESSAGE) +print("received data:", data) diff --git a/key b/key new file mode 100755 index 0000000..9217585 --- /dev/null +++ b/key @@ -0,0 +1,17 @@ +#!/usr/bin/python3 +# -*- coding:Utf-8 -*- + +import os,sys,inspect # for the following +cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"modules"))) +if cmd_subfolder not in sys.path: + sys.path.insert(0, cmd_subfolder) + +from pydes import pyDes + +data = b"Please encrypt my data" +k = pyDes.des(b"DEADJACK", pyDes.CBC, b"\2\2\2\2\2\2\2\2", pad=None, padmode=2) +d = k.encrypt(data) +print("Encrypted: %r" % d) +print("Decrypted: %r" % k.decrypt(d)) +assert k.decrypt(d, padmode=2) == data + diff --git a/modules/daemon/__pycache__/runner.cpython-34.pyc b/modules/daemon/__pycache__/runner.cpython-34.pyc index bd5010132f5a4e0bd2eb0aa764668082841c6154..f72b4fcf57f4164607bdd3b4000afb03b54f5f08 100644 GIT binary patch delta 967 zcmYLHOHUI~7@a%Q>AR&`h2qGg)K-SjF{B`<)JAzI0m=f55g&EZ8Nxtkinr4kB2g1v z>c+b;VWmI7L^4~q?2K;Mc%%LR7cNX(;L7{m7G3o8eD^!w@%dutXEYWb()MqD z*$Y)Abe`B!&Tr_ZU3a`!(p`U85(Ht2{TlDcVd!4wnJDZC!iFSN!h#_IuSA3$By2<> z+zbhLmply*%aX9H`nwhHF?(WlMM0smwWzu)liKZJqgB0Y5Y`{(r~< zEVKDEx@8$_R?Tds61Kj{sAbgZ)lE329Y=ZBvQ5@k6>*%^;a&#hgfBtf#}#za`xp<1 zXxKYQd=f7XLEgte4d5~0;|!=&GaY;Z!T^MRz3N(Z2am8om0CT=$=75L>hb<0&x%?f zNc%w={I^W(N)4O3vAw{yGYxzSBn5yxS?W|Wqd;LXD&eN1`gm6=v%A(Yo`mECd8;J7 zH=PurN%APApgehTi(*mf_R#Xf26*nJPlcm3ar7VDv;w-i@+`eEHF57hL@3` z^1@$+)Qq>Ql*Pg&P{{nc7&r~io7*#dvu=>_6S6%g)*fIp0I&__!h8(l*ln(5)G0-CXEI?HS+-_uE9C4z7A}T{63RL^Q0@Qp;@jj zlGSVm70KgldW_$Li|0UmAE3g3hRV8aa+_(qTzBW}t(s|@j?2Ddi5z6d(H#=aVa;3kA|MNHi delta 887 zcmX|A&rcIU6rS1bmUjCCun}mhlv1|3L<*!3D2@D(peBF^6(So$Q@dMPC|jJiF(kyq z=)tq^=EWb;n-|@y9!b35AFu~6CR~gr-t=JNyeWFvZ@>5EoA=GUefxM7R)asn5p^^E zcK!HWup-k@*p;*HGx@e(RR|%A{AsvP)lJ=$iRmMcBzi!|woFPYF%`mjDMSt^*$!j4 z6C~^fJX9|z3b~>C-S_Ia+~o!Dw5nB$+0I=?c{%tR8PyH7(KKzRv{!C!d5Yjhh`;Ks zW;^F^2L=?QacaO?G?g$q_iVFj*Q`?0-nF<=mspe+WGUz#h{4Nfk|y1c(GH28cMrQh zOEXzq^l{KT*f{b$2T!h94x7ZV14Dng(zNRi8{vU2w+rUsD0Y_iyWe8xq}%{X(XjWlfDu`!F{^CuukeIrvII&-5proVSE)Cwv^#^b`5gbUdRl5*_hxVKZf`mL!5iceP%Z;Vecu`TC1_e z%~0j>5#UYUWv8%$fEY4tZj=vFBftrf!Zb|dl#PLr{!NGB=HOze{UuO446g>WXNEa7 zI?I)NEt~xx9yW`DB90E#;MZW9YHlL)fp#rmUPriuun5OPX}SafEl1~tx&X^sh8Cc% mrB91{2r>RCYy;sIywOs$2#4AfU4uVbHYDaj!?gl$#QI;|$jsFM diff --git a/modules/daemon/runner.py b/modules/daemon/runner.py index f49909a..9090b6a 100644 --- a/modules/daemon/runner.py +++ b/modules/daemon/runner.py @@ -110,7 +110,7 @@ class DaemonRunner: self.daemon_context.stdin = open(app.stdin_path, 'rt') self.daemon_context.stdout = open(app.stdout_path, 'w+t') self.daemon_context.stderr = open( - app.stderr_path, 'w+t', buffering=0) + app.stderr_path, 'w+t') self.pidfile = None if app.pidfile_path is not None: diff --git a/modules/pydes/__pycache__/pyDes.cpython-34.pyc b/modules/pydes/__pycache__/pyDes.cpython-34.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b9b9f0e538f836f834a0b69fcdf3d42443cf565 GIT binary patch literal 24421 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 literal 0 HcmV?d00001 diff --git a/modules/pydes/pyDes.py b/modules/pydes/pyDes.py new file mode 100644 index 0000000..d1a1cce --- /dev/null +++ b/modules/pydes/pyDes.py @@ -0,0 +1,852 @@ +############################################################################# +# Documentation # +############################################################################# + +# Author: Todd Whiteman +# Date: 16th March, 2009 +# Verion: 2.0.0 +# License: MIT +# Homepage: http://twhiteman.netfirms.com/des.html +# +# This is a pure python implementation of the DES encryption algorithm. +# It's pure python to avoid portability issues, since most DES +# implementations are programmed in C (for performance reasons). +# +# Triple DES class is also implemented, utilising the DES base. Triple DES +# is either DES-EDE3 with a 24 byte key, or DES-EDE2 with a 16 byte key. +# +# See the README.txt that should come with this python module for the +# implementation methods used. +# +# Thanks to: +# * David Broadwell for ideas, comments and suggestions. +# * Mario Wolff for pointing out and debugging some triple des CBC errors. +# * Santiago Palladino for providing the PKCS5 padding technique. +# * Shaya for correcting the PAD_PKCS5 triple des CBC errors. +# +"""A pure python implementation of the DES and TRIPLE DES encryption algorithms. + +Class initialization +-------------------- +pyDes.des(key, [mode], [IV], [pad], [padmode]) +pyDes.triple_des(key, [mode], [IV], [pad], [padmode]) + +key -> Bytes containing the encryption key. 8 bytes for DES, 16 or 24 bytes + for Triple DES +mode -> Optional argument for encryption type, can be either + pyDes.ECB (Electronic Code Book) or pyDes.CBC (Cypher Block Chaining) +IV -> Optional Initial Value bytes, must be supplied if using CBC mode. + Length must be 8 bytes. +pad -> Optional argument, set the pad character (PAD_NORMAL) to use during + all encrypt/decrpt operations done with this instance. +padmode -> Optional argument, set the padding mode (PAD_NORMAL or PAD_PKCS5) + to use during all encrypt/decrpt operations done with this instance. + +I recommend to use PAD_PKCS5 padding, as then you never need to worry about any +padding issues, as the padding can be removed unambiguously upon decrypting +data that was encrypted using PAD_PKCS5 padmode. + +Common methods +-------------- +encrypt(data, [pad], [padmode]) +decrypt(data, [pad], [padmode]) + +data -> Bytes to be encrypted/decrypted +pad -> Optional argument. Only when using padmode of PAD_NORMAL. For + encryption, adds this characters to the end of the data block when + data is not a multiple of 8 bytes. For decryption, will remove the + trailing characters that match this pad character from the last 8 + bytes of the unencrypted data block. +padmode -> Optional argument, set the padding mode, must be one of PAD_NORMAL + or PAD_PKCS5). Defaults to PAD_NORMAL. + + +Example +------- +from pyDes import * + +data = "Please encrypt my data" +k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5) +# For Python3, you'll need to use bytes, i.e.: +# data = b"Please encrypt my data" +# k = des(b"DESCRYPT", CBC, b"\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5) +d = k.encrypt(data) +print "Encrypted: %r" % d +print "Decrypted: %r" % k.decrypt(d) +assert k.decrypt(d, padmode=PAD_PKCS5) == data + + +See the module source (pyDes.py) for more examples of use. +You can also run the pyDes.py file without and arguments to see a simple test. + +Note: This code was not written for high-end systems needing a fast + implementation, but rather a handy portable solution with small usage. + +""" + +import sys + +# _pythonMajorVersion is used to handle Python2 and Python3 differences. +_pythonMajorVersion = sys.version_info[0] + +# Modes of crypting / cyphering +ECB = 0 +CBC = 1 + +# Modes of padding +PAD_NORMAL = 1 +PAD_PKCS5 = 2 + +# PAD_PKCS5: is a method that will unambiguously remove all padding +# characters after decryption, when originally encrypted with +# this padding mode. +# For a good description of the PKCS5 padding technique, see: +# http://www.faqs.org/rfcs/rfc1423.html + +# The base class shared by des and triple des. +class _baseDes(object): + def __init__(self, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL): + if IV: + IV = self._guardAgainstUnicode(IV) + if pad: + pad = self._guardAgainstUnicode(pad) + self.block_size = 8 + # Sanity checking of arguments. + if pad and padmode == PAD_PKCS5: + raise ValueError("Cannot use a pad character with PAD_PKCS5") + if IV and len(IV) != self.block_size: + raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes") + + # Set the passed in variables + self._mode = mode + self._iv = IV + self._padding = pad + self._padmode = padmode + + def getKey(self): + """getKey() -> bytes""" + return self.__key + + def setKey(self, key): + """Will set the crypting key for this object.""" + key = self._guardAgainstUnicode(key) + self.__key = key + + def getMode(self): + """getMode() -> pyDes.ECB or pyDes.CBC""" + return self._mode + + def setMode(self, mode): + """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC""" + self._mode = mode + + def getPadding(self): + """getPadding() -> bytes of length 1. Padding character.""" + return self._padding + + def setPadding(self, pad): + """setPadding() -> bytes of length 1. Padding character.""" + if pad is not None: + pad = self._guardAgainstUnicode(pad) + self._padding = pad + + def getPadMode(self): + """getPadMode() -> pyDes.PAD_NORMAL or pyDes.PAD_PKCS5""" + return self._padmode + + def setPadMode(self, mode): + """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5""" + self._padmode = mode + + def getIV(self): + """getIV() -> bytes""" + return self._iv + + def setIV(self, IV): + """Will set the Initial Value, used in conjunction with CBC mode""" + if not IV or len(IV) != self.block_size: + raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes") + IV = self._guardAgainstUnicode(IV) + self._iv = IV + + def _padData(self, data, pad, padmode): + # Pad data depending on the mode + if padmode is None: + # Get the default padding mode. + padmode = self.getPadMode() + if pad and padmode == PAD_PKCS5: + raise ValueError("Cannot use a pad character with PAD_PKCS5") + + if padmode == PAD_NORMAL: + if len(data) % self.block_size == 0: + # No padding required. + return data + + if not pad: + # Get the default padding. + pad = self.getPadding() + if not pad: + raise ValueError("Data must be a multiple of " + str(self.block_size) + " bytes in length. Use padmode=PAD_PKCS5 or set the pad character.") + data += (self.block_size - (len(data) % self.block_size)) * pad + + elif padmode == PAD_PKCS5: + pad_len = 8 - (len(data) % self.block_size) + if _pythonMajorVersion < 3: + data += pad_len * chr(pad_len) + else: + data += bytes([pad_len] * pad_len) + + return data + + def _unpadData(self, data, pad, padmode): + # Unpad data depending on the mode. + if not data: + return data + if pad and padmode == PAD_PKCS5: + raise ValueError("Cannot use a pad character with PAD_PKCS5") + if padmode is None: + # Get the default padding mode. + padmode = self.getPadMode() + + if padmode == PAD_NORMAL: + if not pad: + # Get the default padding. + pad = self.getPadding() + if pad: + data = data[:-self.block_size] + \ + data[-self.block_size:].rstrip(pad) + + elif padmode == PAD_PKCS5: + if _pythonMajorVersion < 3: + pad_len = ord(data[-1]) + else: + pad_len = data[-1] + data = data[:-pad_len] + + return data + + def _guardAgainstUnicode(self, data): + # Only accept byte strings or ascii unicode values, otherwise + # there is no way to correctly decode the data into bytes. + if _pythonMajorVersion < 3: + if isinstance(data, unicode): + raise ValueError("pyDes can only work with bytes, not Unicode strings.") + else: + if isinstance(data, str): + # Only accept ascii unicode values. + try: + return data.encode('ascii') + except UnicodeEncodeError: + pass + raise ValueError("pyDes can only work with encoded strings, not Unicode.") + return data + +############################################################################# +# DES # +############################################################################# +class des(_baseDes): + """DES encryption/decrytpion class + + Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes. + + pyDes.des(key,[mode], [IV]) + + key -> Bytes containing the encryption key, must be exactly 8 bytes + mode -> Optional argument for encryption type, can be either pyDes.ECB + (Electronic Code Book), pyDes.CBC (Cypher Block Chaining) + IV -> Optional Initial Value bytes, must be supplied if using CBC mode. + Must be 8 bytes in length. + pad -> Optional argument, set the pad character (PAD_NORMAL) to use + during all encrypt/decrpt operations done with this instance. + padmode -> Optional argument, set the padding mode (PAD_NORMAL or + PAD_PKCS5) to use during all encrypt/decrpt operations done + with this instance. + """ + + + # Permutation and translation tables for DES + __pc1 = [56, 48, 40, 32, 24, 16, 8, + 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, + 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, + 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, + 20, 12, 4, 27, 19, 11, 3 + ] + + # number left rotations of pc1 + __left_rotations = [ + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 + ] + + # permuted choice key (table 2) + __pc2 = [ + 13, 16, 10, 23, 0, 4, + 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, + 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, + 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, + 45, 41, 49, 35, 28, 31 + ] + + # initial permutation IP + __ip = [57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7, + 56, 48, 40, 32, 24, 16, 8, 0, + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6 + ] + + # Expansion table for turning 32 bit blocks into 48 bits + __expansion_table = [ + 31, 0, 1, 2, 3, 4, + 3, 4, 5, 6, 7, 8, + 7, 8, 9, 10, 11, 12, + 11, 12, 13, 14, 15, 16, + 15, 16, 17, 18, 19, 20, + 19, 20, 21, 22, 23, 24, + 23, 24, 25, 26, 27, 28, + 27, 28, 29, 30, 31, 0 + ] + + # The (in)famous S-boxes + __sbox = [ + # S1 + [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13], + + # S2 + [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9], + + # S3 + [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12], + + # S4 + [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14], + + # S5 + [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3], + + # S6 + [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13], + + # S7 + [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12], + + # S8 + [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11], + ] + + + # 32-bit permutation function P used on the output of the S-boxes + __p = [ + 15, 6, 19, 20, 28, 11, + 27, 16, 0, 14, 22, 25, + 4, 17, 30, 9, 1, 7, + 23,13, 31, 26, 2, 8, + 18, 12, 29, 5, 21, 10, + 3, 24 + ] + + # final permutation IP^-1 + __fp = [ + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25, + 32, 0, 40, 8, 48, 16, 56, 24 + ] + + # Type of crypting being done + ENCRYPT = 0x00 + DECRYPT = 0x01 + + # Initialisation + def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL): + # Sanity checking of arguments. + if len(key) != 8: + raise ValueError("Invalid DES key size. Key must be exactly 8 bytes long.") + _baseDes.__init__(self, mode, IV, pad, padmode) + self.key_size = 8 + + self.L = [] + self.R = [] + self.Kn = [ [0] * 48 ] * 16 # 16 48-bit keys (K1 - K16) + self.final = [] + + self.setKey(key) + + def setKey(self, key): + """Will set the crypting key for this object. Must be 8 bytes.""" + _baseDes.setKey(self, key) + self.__create_sub_keys() + + def __String_to_BitList(self, data): + """Turn the string data, into a list of bits (1, 0)'s""" + if _pythonMajorVersion < 3: + # Turn the strings into integers. Python 3 uses a bytes + # class, which already has this behaviour. + data = [ord(c) for c in data] + l = len(data) * 8 + result = [0] * l + pos = 0 + for ch in data: + i = 7 + while i >= 0: + if ch & (1 << i) != 0: + result[pos] = 1 + else: + result[pos] = 0 + pos += 1 + i -= 1 + + return result + + def __BitList_to_String(self, data): + """Turn the list of bits -> data, into a string""" + result = [] + pos = 0 + c = 0 + while pos < len(data): + c += data[pos] << (7 - (pos % 8)) + if (pos % 8) == 7: + result.append(c) + c = 0 + pos += 1 + + if _pythonMajorVersion < 3: + return ''.join([ chr(c) for c in result ]) + else: + return bytes(result) + + def __permutate(self, table, block): + """Permutate this block with the specified table""" + return list(map(lambda x: block[x], table)) + + # Transform the secret key, so that it is ready for data processing + # Create the 16 subkeys, K[1] - K[16] + def __create_sub_keys(self): + """Create the 16 subkeys K[1] to K[16] from the given key""" + key = self.__permutate(des.__pc1, self.__String_to_BitList(self.getKey())) + i = 0 + # Split into Left and Right sections + self.L = key[:28] + self.R = key[28:] + while i < 16: + j = 0 + # Perform circular left shifts + while j < des.__left_rotations[i]: + self.L.append(self.L[0]) + del self.L[0] + + self.R.append(self.R[0]) + del self.R[0] + + j += 1 + + # Create one of the 16 subkeys through pc2 permutation + self.Kn[i] = self.__permutate(des.__pc2, self.L + self.R) + + i += 1 + + # Main part of the encryption algorithm, the number cruncher :) + def __des_crypt(self, block, crypt_type): + """Crypt the block of data through DES bit-manipulation""" + block = self.__permutate(des.__ip, block) + self.L = block[:32] + self.R = block[32:] + + # Encryption starts from Kn[1] through to Kn[16] + if crypt_type == des.ENCRYPT: + iteration = 0 + iteration_adjustment = 1 + # Decryption starts from Kn[16] down to Kn[1] + else: + iteration = 15 + iteration_adjustment = -1 + + i = 0 + while i < 16: + # Make a copy of R[i-1], this will later become L[i] + tempR = self.R[:] + + # Permutate R[i - 1] to start creating R[i] + self.R = self.__permutate(des.__expansion_table, self.R) + + # Exclusive or R[i - 1] with K[i], create B[1] to B[8] whilst here + self.R = list(map(lambda x, y: x ^ y, self.R, self.Kn[iteration])) + B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]] + # Optimization: Replaced below commented code with above + #j = 0 + #B = [] + #while j < len(self.R): + # self.R[j] = self.R[j] ^ self.Kn[iteration][j] + # j += 1 + # if j % 6 == 0: + # B.append(self.R[j-6:j]) + + # Permutate B[1] to B[8] using the S-Boxes + j = 0 + Bn = [0] * 32 + pos = 0 + while j < 8: + # Work out the offsets + m = (B[j][0] << 1) + B[j][5] + n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4] + + # Find the permutation value + v = des.__sbox[j][(m << 4) + n] + + # Turn value into bits, add it to result: Bn + Bn[pos] = (v & 8) >> 3 + Bn[pos + 1] = (v & 4) >> 2 + Bn[pos + 2] = (v & 2) >> 1 + Bn[pos + 3] = v & 1 + + pos += 4 + j += 1 + + # Permutate the concatination of B[1] to B[8] (Bn) + self.R = self.__permutate(des.__p, Bn) + + # Xor with L[i - 1] + self.R = list(map(lambda x, y: x ^ y, self.R, self.L)) + # Optimization: This now replaces the below commented code + #j = 0 + #while j < len(self.R): + # self.R[j] = self.R[j] ^ self.L[j] + # j += 1 + + # L[i] becomes R[i - 1] + self.L = tempR + + i += 1 + iteration += iteration_adjustment + + # Final permutation of R[16]L[16] + self.final = self.__permutate(des.__fp, self.R + self.L) + return self.final + + + # Data to be encrypted/decrypted + def crypt(self, data, crypt_type): + """Crypt the data in blocks, running it through des_crypt()""" + + # Error check the data + if not data: + return '' + if len(data) % self.block_size != 0: + if crypt_type == des.DECRYPT: # Decryption must work on 8 byte blocks + raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.") + if not self.getPadding(): + raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character") + else: + data += (self.block_size - (len(data) % self.block_size)) * self.getPadding() + # print "Len of data: %f" % (len(data) / self.block_size) + + if self.getMode() == CBC: + if self.getIV(): + iv = self.__String_to_BitList(self.getIV()) + else: + raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering") + + # Split the data into blocks, crypting each one seperately + i = 0 + dict = {} + result = [] + #cached = 0 + #lines = 0 + while i < len(data): + # Test code for caching encryption results + #lines += 1 + #if dict.has_key(data[i:i+8]): + #print "Cached result for: %s" % data[i:i+8] + # cached += 1 + # result.append(dict[data[i:i+8]]) + # i += 8 + # continue + + block = self.__String_to_BitList(data[i:i+8]) + + # Xor with IV if using CBC mode + if self.getMode() == CBC: + if crypt_type == des.ENCRYPT: + block = list(map(lambda x, y: x ^ y, block, iv)) + #j = 0 + #while j < len(block): + # block[j] = block[j] ^ iv[j] + # j += 1 + + processed_block = self.__des_crypt(block, crypt_type) + + if crypt_type == des.DECRYPT: + processed_block = list(map(lambda x, y: x ^ y, processed_block, iv)) + #j = 0 + #while j < len(processed_block): + # processed_block[j] = processed_block[j] ^ iv[j] + # j += 1 + iv = block + else: + iv = processed_block + else: + processed_block = self.__des_crypt(block, crypt_type) + + + # Add the resulting crypted block to our list + #d = self.__BitList_to_String(processed_block) + #result.append(d) + result.append(self.__BitList_to_String(processed_block)) + #dict[data[i:i+8]] = d + i += 8 + + # print "Lines: %d, cached: %d" % (lines, cached) + + # Return the full crypted string + if _pythonMajorVersion < 3: + return ''.join(result) + else: + return bytes.fromhex('').join(result) + + def encrypt(self, data, pad=None, padmode=None): + """encrypt(data, [pad], [padmode]) -> bytes + + data : Bytes to be encrypted + pad : Optional argument for encryption padding. Must only be one byte + padmode : Optional argument for overriding the padding mode. + + The data must be a multiple of 8 bytes and will be encrypted + with the already specified key. Data does not have to be a + multiple of 8 bytes if the padding character is supplied, or + the padmode is set to PAD_PKCS5, as bytes will then added to + ensure the be padded data is a multiple of 8 bytes. + """ + data = self._guardAgainstUnicode(data) + if pad is not None: + pad = self._guardAgainstUnicode(pad) + data = self._padData(data, pad, padmode) + return self.crypt(data, des.ENCRYPT) + + def decrypt(self, data, pad=None, padmode=None): + """decrypt(data, [pad], [padmode]) -> bytes + + data : Bytes to be encrypted + pad : Optional argument for decryption padding. Must only be one byte + padmode : Optional argument for overriding the padding mode. + + The data must be a multiple of 8 bytes and will be decrypted + with the already specified key. In PAD_NORMAL mode, if the + optional padding character is supplied, then the un-encrypted + data will have the padding characters removed from the end of + the bytes. This pad removal only occurs on the last 8 bytes of + the data (last data block). In PAD_PKCS5 mode, the special + padding end markers will be removed from the data after decrypting. + """ + data = self._guardAgainstUnicode(data) + if pad is not None: + pad = self._guardAgainstUnicode(pad) + data = self.crypt(data, des.DECRYPT) + return self._unpadData(data, pad, padmode) + + + +############################################################################# +# Triple DES # +############################################################################# +class triple_des(_baseDes): + """Triple DES encryption/decrytpion class + + This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or + the DES-EDE2 (when a 16 byte key is supplied) encryption methods. + Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes. + + pyDes.des(key, [mode], [IV]) + + key -> Bytes containing the encryption key, must be either 16 or + 24 bytes long + mode -> Optional argument for encryption type, can be either pyDes.ECB + (Electronic Code Book), pyDes.CBC (Cypher Block Chaining) + IV -> Optional Initial Value bytes, must be supplied if using CBC mode. + Must be 8 bytes in length. + pad -> Optional argument, set the pad character (PAD_NORMAL) to use + during all encrypt/decrpt operations done with this instance. + padmode -> Optional argument, set the padding mode (PAD_NORMAL or + PAD_PKCS5) to use during all encrypt/decrpt operations done + with this instance. + """ + def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL): + _baseDes.__init__(self, mode, IV, pad, padmode) + self.setKey(key) + + def setKey(self, key): + """Will set the crypting key for this object. Either 16 or 24 bytes long.""" + self.key_size = 24 # Use DES-EDE3 mode + if len(key) != self.key_size: + if len(key) == 16: # Use DES-EDE2 mode + self.key_size = 16 + else: + raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long") + if self.getMode() == CBC: + if not self.getIV(): + # Use the first 8 bytes of the key + self._iv = key[:self.block_size] + if len(self.getIV()) != self.block_size: + raise ValueError("Invalid IV, must be 8 bytes in length") + self.__key1 = des(key[:8], self._mode, self._iv, + self._padding, self._padmode) + self.__key2 = des(key[8:16], self._mode, self._iv, + self._padding, self._padmode) + if self.key_size == 16: + self.__key3 = self.__key1 + else: + self.__key3 = des(key[16:], self._mode, self._iv, + self._padding, self._padmode) + _baseDes.setKey(self, key) + + # Override setter methods to work on all 3 keys. + + def setMode(self, mode): + """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC""" + _baseDes.setMode(self, mode) + for key in (self.__key1, self.__key2, self.__key3): + key.setMode(mode) + + def setPadding(self, pad): + """setPadding() -> bytes of length 1. Padding character.""" + _baseDes.setPadding(self, pad) + for key in (self.__key1, self.__key2, self.__key3): + key.setPadding(pad) + + def setPadMode(self, mode): + """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5""" + _baseDes.setPadMode(self, mode) + for key in (self.__key1, self.__key2, self.__key3): + key.setPadMode(mode) + + def setIV(self, IV): + """Will set the Initial Value, used in conjunction with CBC mode""" + _baseDes.setIV(self, IV) + for key in (self.__key1, self.__key2, self.__key3): + key.setIV(IV) + + def encrypt(self, data, pad=None, padmode=None): + """encrypt(data, [pad], [padmode]) -> bytes + + data : bytes to be encrypted + pad : Optional argument for encryption padding. Must only be one byte + padmode : Optional argument for overriding the padding mode. + + The data must be a multiple of 8 bytes and will be encrypted + with the already specified key. Data does not have to be a + multiple of 8 bytes if the padding character is supplied, or + the padmode is set to PAD_PKCS5, as bytes will then added to + ensure the be padded data is a multiple of 8 bytes. + """ + ENCRYPT = des.ENCRYPT + DECRYPT = des.DECRYPT + data = self._guardAgainstUnicode(data) + if pad is not None: + pad = self._guardAgainstUnicode(pad) + # Pad the data accordingly. + data = self._padData(data, pad, padmode) + if self.getMode() == CBC: + self.__key1.setIV(self.getIV()) + self.__key2.setIV(self.getIV()) + self.__key3.setIV(self.getIV()) + i = 0 + result = [] + while i < len(data): + block = self.__key1.crypt(data[i:i+8], ENCRYPT) + block = self.__key2.crypt(block, DECRYPT) + block = self.__key3.crypt(block, ENCRYPT) + self.__key1.setIV(block) + self.__key2.setIV(block) + self.__key3.setIV(block) + result.append(block) + i += 8 + if _pythonMajorVersion < 3: + return ''.join(result) + else: + return bytes.fromhex('').join(result) + else: + data = self.__key1.crypt(data, ENCRYPT) + data = self.__key2.crypt(data, DECRYPT) + return self.__key3.crypt(data, ENCRYPT) + + def decrypt(self, data, pad=None, padmode=None): + """decrypt(data, [pad], [padmode]) -> bytes + + data : bytes to be encrypted + pad : Optional argument for decryption padding. Must only be one byte + padmode : Optional argument for overriding the padding mode. + + The data must be a multiple of 8 bytes and will be decrypted + with the already specified key. In PAD_NORMAL mode, if the + optional padding character is supplied, then the un-encrypted + data will have the padding characters removed from the end of + the bytes. This pad removal only occurs on the last 8 bytes of + the data (last data block). In PAD_PKCS5 mode, the special + padding end markers will be removed from the data after + decrypting, no pad character is required for PAD_PKCS5. + """ + ENCRYPT = des.ENCRYPT + DECRYPT = des.DECRYPT + data = self._guardAgainstUnicode(data) + if pad is not None: + pad = self._guardAgainstUnicode(pad) + if self.getMode() == CBC: + self.__key1.setIV(self.getIV()) + self.__key2.setIV(self.getIV()) + self.__key3.setIV(self.getIV()) + i = 0 + result = [] + while i < len(data): + iv = data[i:i+8] + block = self.__key3.crypt(iv, DECRYPT) + block = self.__key2.crypt(block, ENCRYPT) + block = self.__key1.crypt(block, DECRYPT) + self.__key1.setIV(iv) + self.__key2.setIV(iv) + self.__key3.setIV(iv) + result.append(block) + i += 8 + if _pythonMajorVersion < 3: + data = ''.join(result) + else: + data = bytes.fromhex('').join(result) + else: + data = self.__key3.crypt(data, DECRYPT) + data = self.__key2.crypt(data, ENCRYPT) + data = self.__key1.crypt(data, DECRYPT) + return self._unpadData(data, pad, padmode) diff --git a/remus b/remus new file mode 100755 index 0000000..c086a06 --- /dev/null +++ b/remus @@ -0,0 +1,95 @@ +#!/usr/bin/python3 +# -*- coding:Utf-8 -*- + +# Remus is meant to run on Stargate + +import logging # Logs +import time # sleep +import string # split strings + +import os,sys,inspect # for the following +cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"modules"))) +if cmd_subfolder not in sys.path: + sys.path.insert(0, cmd_subfolder) + +import lockfile # daemonization +from daemon import runner # daemonization + +from multiprocessing import Process +#import subprocess +#import shlex + +# logger.debug("Debug message") +# logger.info("Info message") +# logger.warn("Warning message") +# logger.error("Error message") + +class App(): + + def __init__(self): + self.stdin_path = "/dev/null" + self.stdout_path = "/home/lionel/work/python/rome/log/stdout.log" + self.stderr_path = "/home/lionel/work/python/rome/log/stderr.log" + self.pidfile_path = "/home/lionel/work/python/rome/pid/horusd.pid" + self.pidfile_timeout = 5 + + def run(self): +# We must put all functions before the 'if __name__ blabla' + + def heartbeat(min): + seconds = int(min) * 60 + while True: + logger.info("HB : alive") + time.sleep(seconds) + return False + + +# All functions definitions took place above + if __name__ == '__main__': + logger.info("Rome test started") + + ''' + Launching the heartbeat function + ''' + p = Process(target=heartbeat, args=(2,)) + p.daemon = True + p.start() + heartbeat_pid = p.pid + logger.info("heartbeat loop launched (pid " + str(heartbeat_pid) + ")") + + ''' + Entering infinite loop + ''' + + try: + while True: + time.sleep(30) + except: + logger.error("While loop interrupted : aborting") + # Faut arrêter les Process ... + +# Invocation of the daemon part +# Means : if it's working : DON'T TOUCH ANYTHING +if __name__ == "__main__": + app = App() + logger = logging.getLogger("horusd") + loglevel = "debug" + if (loglevel=="DEBUG") or (loglevel=="debug"): + logger.setLevel(logging.DEBUG) + elif (loglevel=="INFO") or (loglevel=="info"): + logger.setLevel(logging.INFO) + elif (loglevel=="WARN") or (loglevel=="warn"): + logger.setLevel(logging.WARN) + elif (loglevel=="ERROR") or (loglevel=="error"): + logger.setLevel(logging.ERROR) + else: + logger.setLevel(logging.DEBUG) + formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + handler = logging.FileHandler("log/horusd.log") + handler.setFormatter(formatter) + logger.addHandler(handler) + + daemon_runner = runner.DaemonRunner(app) + #This ensures that the logger file handle does not get closed during daemonization + daemon_runner.daemon_context.files_preserve=[handler.stream] + daemon_runner.do_action() diff --git a/romulus b/romulus new file mode 100755 index 0000000..4dc2751 --- /dev/null +++ b/romulus @@ -0,0 +1,129 @@ +#!/usr/bin/python3 +# -*- coding:Utf-8 -*- + +# Romulus is meant to run on Horus + +import logging # Logs +import time # sleep +import string # split strings +import socket # client/server TCP networking + +import os,sys,inspect # for the following +cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"modules"))) +if cmd_subfolder not in sys.path: + sys.path.insert(0, cmd_subfolder) + +import lockfile # daemonization +from daemon import runner # daemonization +from pydes import pyDes # DES encryption + +from multiprocessing import Process +#import subprocess +#import shlex + +# logger.debug("Debug message") +# logger.warn("Warning message") +# logger.error("Error message") +# logger.info("Info message") + +class App(): + + def __init__(self): + self.stdin_path = "/dev/null" + self.stdout_path = "/home/lionel/work/python/rome/log/stdout.log" + self.stderr_path = "/home/lionel/work/python/rome/log/stderr.log" + self.pidfile_path = "/home/lionel/work/python/rome/pid/romulus.pid" + self.pidfile_timeout = 5 + + def run(self): +# We must put all functions before the 'if __name__ blabla' + + def heartbeat(void): +# Heartbeat is also responsible of verifying the network link between the two + #seconds = int(min) * 60 + MY_TCP_IP = '127.0.0.1' + MY_TCP_PORT = 5005 + MY_BUFFER_SIZE = 1024 + + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((MY_TCP_IP, MY_TCP_PORT)) + s.listen(1) + while True: + time.sleep(1) + conn, addr = s.accept() + if not conn: break + data = conn.recv(MY_BUFFER_SIZE) + if not data: break + logger.info("Received HB from " + str(addr) + " : " + str(data)) + k = pyDes.des(b"DEADJACK", pyDes.CBC, b"\2\2\2\2\2\2\2\2", pad=None, padmode=2) + try: + logger.info("HB packet content is : " + str(data)) + logger.info("decrypting") + data = k.decrypt(data) + logger.info("HB packet content is : " + str(data)) + data = data.decode('UTF-8') + logger.info("decode from UTF-8") + logger.info("HB packet content is : " + str(data)) + if data == "HB": + logger.info("sending HB packet back : Received") + DEST_MESSAGE = bytes("Received", 'UTF-8') + DEST_MESSAGE = k.encrypt(DEST_MESSAGE) + # Sending + conn.send(DEST_MESSAGE) + conn.close() + except: + logger.info("Received an invalid HB packet") + time.sleep(1) + logger.error("I am out of the infinit HB loop !") + return False + + +# All functions definitions took place above + if __name__ == '__main__': + logger.info("Romulus (test version) started") + + ''' + Launching the heartbeat function + ''' + p = Process(target=heartbeat, args=(False,)) + p.daemon = True + p.start() + heartbeat_pid = p.pid + logger.info("heartbeat loop launched (pid " + str(heartbeat_pid) + ")") + + ''' + Entering infinite loop + ''' + + try: + while True: + time.sleep(30) + except: + logger.error("While loop interrupted : aborting") + # Faut arrêter les Process ... + +# Invocation of the daemon part +# Means : if it's working : DON'T TOUCH ANYTHING +if __name__ == "__main__": + app = App() + logger = logging.getLogger("romulus") + loglevel = "debug" + if (loglevel=="DEBUG") or (loglevel=="debug"): + logger.setLevel(logging.DEBUG) + elif (loglevel=="INFO") or (loglevel=="info"): + logger.setLevel(logging.INFO) + elif (loglevel=="WARN") or (loglevel=="warn"): + logger.setLevel(logging.WARN) + elif (loglevel=="ERROR") or (loglevel=="error"): + logger.setLevel(logging.ERROR) + else: + logger.setLevel(logging.DEBUG) + formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + handler = logging.FileHandler("log/romulus.log") + handler.setFormatter(formatter) + logger.addHandler(handler) + + daemon_runner = runner.DaemonRunner(app) + #This ensures that the logger file handle does not get closed during daemonization + daemon_runner.daemon_context.files_preserve=[handler.stream] + daemon_runner.do_action() -- 2.39.2