Exemplo n.º 1
0
class Node:
    def __init__(self, node_id):
        self.node_id = node_id
        self.authorised_users = []
        self.transaction_history = []

        # Set up crypto
        self.diffie = DiffieHellman()
        self.exchange_keys()

        self.sync()

        print("Node Established.")

    def sync(self):
        conn = socket.socket()
        conn.connect((SERVER_IP, SERVER_PORT))
        conn.send(self.crypt(b"SYNC"))

    def update_authorised_users(self):
        pass

    def send_transactions(self):
        pass

    def main_loop(self):
        pass

    def exchange_keys(self):
        self.diffie.generate_public_key()
        conn = socket.socket()
        conn.connect((SERVER_IP, SERVER_PORT))
        conn.send(self.crypt(self.node_id.zfill(8).encode()))
        conn.send(b"KEYX")
        key_len = str(len(str(self.diffie.public_key))).zfill(4).encode()
        conn.send(key_len)
        conn.send(str(self.diffie.public_key).encode())

        server_key_len = int(conn.recv(4))
        server_key = int(conn.recv(server_key_len))

        self.diffie.generate_shared_secret(server_key)
        conn.close()

    def crypt(self, text):
        key = self.diffie.shared_key
        if type(text) == str:
            text = text.encode()
        if type(key) == str:
            key = key.encode()
        assert type(text) == type(key) == bytes
        output_values = []
        for i, b in enumerate(text):
            output_values.append(b ^ key[i % len(key)])
        return bytes(output_values)
Exemplo n.º 2
0
class MessangerClient(asyncore.dispatcher):

    def __init__(self, host, port, login, password):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))
        self.login = login
        self.password = password
        self.Key = DiffieHellman()
        self.Key.generate_public_key()
        self.buffer = json.dumps({'action': 'handshake', 'data': {'pubkey': int_to_base_str(self.Key.public_key)}}).encode()
        self.cipher = None

    def handle_connect(self):
        pass

    def handle_close(self):
        self.close()

    def handle_read(self):
        data = self.recv(4024).decode('utf-8')
        if data:
            if self.cipher is not None:
                j = json.loads(self.cipher.decrypt(data))
            else:
                j = json.loads(data)
            print(j)

            if j["action"] == "handshake":
                tmp = base_str_to_int(j["data"]["pubkey"])
                h = SHA.new(j["data"]["pubkey"].encode()).digest()
                self.Key.generate_shared_secret(tmp)
                SignR = int(j["data"]["SignR"])
                SignS = int(j["data"]["SignS"])

                if not ElGamalKey.verify(h, (SignR, SignS)):
                    raise("BAD SIGNATURE")

                self.cipher = AESCipher(str(self.Key.shared_key).encode())
                self.buffer = json.dumps({'action': 'auth', 'data': {'login': login, 'pass': password}}).encode('utf-8')

    def writable(self):
        return len(self.buffer) > 0

    def handle_write(self):
        if self.cipher is not None:
            sent = self.send(self.cipher.encrypt(self.buffer.decode()))
            self.buffer = self.buffer[sent:]
        else:
            sent = self.send(self.buffer)
            self.buffer = self.buffer[sent:]
Exemplo n.º 3
0
def main():
    """Main loop

    See vpn.md for details
    """
    # Create the socket
    server_sckt = socket(AF_INET, SOCK_STREAM)
    server_sckt.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    server_sckt.bind((HOST, PORT))
    server_sckt.listen()
    print(f"Listening on {HOST}:{PORT}")
    conn, client = server_sckt.accept()
    print(f"New client: {client[0]}:{client[1]}")

    # Negotiating the cipher
    print("Negotiating the cipher")
    msg_in = conn.recv(4096).decode('utf-8')
    proposed = parse_proposal(msg_in)
    cipher_name, key_size = select_cipher(SUPPORTED_CIPHERS, proposed)
    print(f"We are going to use {cipher_name}{key_size}")
    msg_out = generate_cipher_response(cipher_name, key_size)
    conn.send(msg_out.encode())

    # Negotiating the key
    print("Negotiating the key")
    dh = DiffieHellman()
    dh.generate_public_key()
    msg_in = conn.recv(4096).decode('utf-8')
    client_public_key = parse_dhm_request(msg_in)
    dh.generate_shared_secret(client_public_key)
    msg_out = generate_dhm_response(dh.public_key)
    conn.send(msg_out.encode())
    cipher, key, iv = get_key_and_iv(dh.shared_key, cipher_name, key_size)
    print("The key has been established")

    print("Initializing cryptosystem")
    crypto = cipher.new(key, cipher.MODE_CBC, iv)
    hashing = HMAC.new(key, digestmod=SHA256)
    print("All systems ready")

    while True:
        msg_in = conn.recv(4096)
        if len(msg_in) < 1:
            conn.close()
            break
        msg, hmac = read_message(msg_in, crypto)
        validate_hmac(msg_in, hmac, hashing)
        print(f"Received: {msg}")
        msg_out = f"Server says: {msg[::-1]}"
        conn.send(msg_out.encode())
Exemplo n.º 4
0
class client:
    def __init__(self,socet,ip_port,s):
        self.alice = DiffieHellman()
        self.key = None
        self.socet = socet
        self.ip = ip_port[0]
        self.port = ip_port[1]
        self.alice.generate_public_key() 
        #self.ip = ip
    def df(self):
        m_df = {["alice":self.alice.public_key]}        
        self.socet.send(json.dumps(m_df))
        data = self.socet.recv(json.dumps(m_df))
        if data: 
Exemplo n.º 5
0
def main():
    """Main event loop

    See vpn.md for details
    """

    # Start the server
    client_sckt = socket(AF_INET, SOCK_STREAM)
    client_sckt.connect((HOST, PORT))
    print(f"Connected to {HOST}:{PORT}")

    # Negotiating the cipher
    print("Negotiating the cipher")
    # Send proposal to the server
    msg_out = generate_cipher_proposal(SUPPORTED_CIPHERS)
    client_sckt.send(msg_out.encode())
    msg_in = client_sckt.recv(4096).decode('utf-8')
    cipher_name, key_size = parse_cipher_selection(msg_in)
    print(f"We are going to use {cipher_name}{key_size}")

    # Negotiating the key
    print("Negotiating the key")
    dh = DiffieHellman()
    dh.generate_public_key()
    msg_out = generate_dhm_request(dh.public_key)
    client_sckt.send(msg_out.encode())
    msg_in = client_sckt.recv(4096).decode('utf-8')
    server_public_key = parse_dhm_response(msg_in)
    dh.generate_shared_secret(server_public_key)
    cipher, key, iv = get_key_and_iv(dh.shared_key, cipher_name, key_size)
    print("The key has been established")

    # Initialize Cryptosystem
    print("Initializing cryptosystem")
    crypto = cipher.new(key, cipher.MODE_CBC, iv)
    hashing = HMAC.new(key, digestmod=SHA256)
    print("All systems ready")

    while True:
        msg = input("Enter message: ")
        if msg == "\\quit":
            client_sckt.close()
            break
        ciph_out, hmac_out = encrypt_message(msg, crypto, hashing)
        client_sckt.send(ciph_out + hmac_out.encode())
        msg_in = client_sckt.recv(4096)
        print(msg_in.decode("utf-8"))
Exemplo n.º 6
0
    def key_exchange(self, conn, addr):
        diffie = DiffieHellman()
        diffie.generate_public_key()
        public_key = diffie.public_key
        key_to_send = str(public_key).encode()
        key_len = str(len(key_to_send)).zfill(4).encode()

        client_key_len = int(conn.recv(4))
        client_key = int(conn.recv(client_key_len))
        conn.send(key_len)
        conn.send(key_to_send)

        diffie.generate_shared_secret(client_key)

        client_id = crypt(conn.recv(8), diffie.shared_key).decode()
        conn.close()

        self.store_node(client_id, addr, diffie.shared_key)
Exemplo n.º 7
0
    def session(self):
        alice = DiffieHellman(group=5, key_length=200)
        alice.generate_public_key()
        self.Message_send.message = str(alice.public_key)
        # send puzzle answer and ga mod p
        self.send_message()

        # receive the session key of server
        self.receive_message()

        alice.generate_shared_secret(int(self.Message_rec.gb_mod_p))
        # set up the session key Kas
        self.Kas = str(alice.shared_secret)[:16].encode()
        self.iv = self.Message_rec.iv
        # print("Shared secret is:", int.from_bytes(self.Kas, sys.byteorder))

        # Decryption
        plain_text = self.decryption_with_timestamp()

        # Verify signature
        correct_message = str(
            alice.public_key) + "|" + self.Message_rec.gb_mod_p
        correct_message = correct_message.encode()

        ## load public key
        with open("public_key.der", "rb") as key_file:
            public_key = serialization.load_der_public_key(
                key_file.read(), backend=default_backend())

        ##  verify the signature
        try:
            public_key.verify(
                plain_text, correct_message,
                paddings.PSS(mgf=paddings.MGF1(hashes.SHA256()),
                             salt_length=paddings.PSS.MAX_LENGTH),
                hashes.SHA256())
            # print("Signature verify success!")
        except:
            print('Error in verifying the signature!')
            sys.exit(1)
Exemplo n.º 8
0
 def _createAndSaveKeyHandler(self):
     keyHandler = DiffieHellman(key_length=200, group=5)
     keyHandler.generate_public_key()
     self._insertKeyHandlerIntoDb(keyHandler)
     return keyHandler
Exemplo n.º 9
0
class Client:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    mujAES = None
    cli = None
    cislo = 0

    def __init__(self, adress):

        self.sock.connect((adress, 9876))
        if os.path.isfile('User.private.pem') == False or os.path.isfile(
                'client1.cert.pem') == False:
            createCSR('User', 'heslo', {'CN': 'USER_FQDN'})
            self.poslatCertReq()
            print("ZADAM SI CERTIFIKAT")

        else:
            print("NACITAM ZE SLOZKY JAK BOSSs")
            self.cert = OpenSSL.crypto.load_certificate(
                crypto.FILETYPE_PEM,
                open('client1.cert.pem').read())
            self.poslatCert()

        self.cli = DiffieHellman()
        self.cli.generate_public_key()
        #presunout do runu
        self.vyzadatKlic()

        iThread = threading.Thread(target=self.sendMessage)
        iThread.daemon = True
        iThread.start()
        self.run()

    def run(self):

        while True:
            data = self.sock.recv(BUFSIZE)
            #misto na hrani si s daty
            if not data:
                #ukonceni komunikace
                break
            elif data[0:1] == b"\x66":
                with open('client1.cert.pem', 'wb') as cert:
                    cert.write(data[1:])
                self.nastavitCert(data[1:])
                #self.cert=OpenSSL.crypto.load_certificate(crypto.FILETYPE_PEM,data[1:])
            elif data[0:1] == b"\x11":
                #kdyz prijde ridici znak x11-posleme na vyzadani klic
                self.poslatKlic()
            elif data[0:1] == b"\x98":
                createCSR('User', 'heslo', {'CN': 'USER_FQDN'})
                self.poslatCertReq()

            elif data[0:1] == b"\x12":
                #kdyz prijde ridici znak x12 tak si nastavime klic ktery nasleduje po tomto bytu
                self.nastavitKlic(data[1:])

            elif data[0:1] == b"\x13":
                #nezasifrovana komunikace
                print(data.decode())
                #vynuceni DH pokud prijde nezasifrovana zprava
                #self.sock.send(b'\x11')
            elif data[0:1] == b"\x14":
                #nastaveni klice v pripade ze byl vyzadan nebo tak neco
                self.jinenastaveniklice(data[1:])
            elif data[0:1] == b'\x20':
                self.nastavitCert(data[1:])
            else:
                #vychozi stav- prijdou data bez ridiciho znaku-> predpokladame ze jsou zasifrovana AESem podle dohodnuteho hesla
                data = self.mujAES.decrypt(data)
                try:
                    print("client " + str(self.cislo) + ":" + data.decode())
                except:
                    continue

    def vyzadatCert(self):
        self.sock.send(b'\x65')

    def nastavitCert(self, data):
        #self.cert=OpenSSL.crypto.load_certificate_request(crypto.FILETYPE_PEM, data)
        self.cert = OpenSSL.crypto.load_certificate(crypto.FILETYPE_PEM, data)

    def poslatCert(self):
        text = OpenSSL.crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert)
        self.sock.send(b'\x33' + text)

    def poslatCertReq(self):
        #posle certifikat na podepsani¨
        with open('User.CSR.pem') as cert:
            certificate = OpenSSL.crypto.load_certificate_request(
                crypto.FILETYPE_PEM, cert.read())
            certext = OpenSSL.crypto.dump_certificate_request(
                crypto.FILETYPE_PEM, certificate)
            print(certext)
            self.sock.send(b'\x15' + certext)

    def poslatKlic(self):
        #posle ridici znak nasledovany klicem
        self.sock.send(b'\x12' + str(self.cli.public_key).encode())

    def jinenastaveniklice(self, data):
        #dela zajimave veci, ale jen v urcitem pripade
        self.cli.generate_shared_secret(int(data.decode()),
                                        echo_return_key=True)
        superklic = str(self.cli.shared_secret)
        xy = hashlib.sha256(superklic.encode()).hexdigest()[:32]
        print("2222222222222222222222222222")
        self.cislo = 2
        print(xy)
        self.mujAES = Encryptor.Encryptor(xy)

    def nastavitKlic(self, data):
        #nastavuje klic na zaklade dat ktere dostane
        self.cli.generate_shared_secret(int(data.decode()),
                                        echo_return_key=True)
        superklic = str(self.cli.shared_secret)
        xy = hashlib.sha256(superklic.encode()).hexdigest()[:32]
        print("111111111111111111111")
        self.cislo = 1
        print(xy)
        self.mujAES = Encryptor.Encryptor(xy)
        self.sock.send(b'\x14' + str(self.cli.public_key).encode())

    def vyzadatKlic(self):
        #nemam klic ale chci, poslu ridici znak
        self.sock.send(b'\x11')

    def sendMessage(self):
        #hlavni chatova smycka

        while True:
            msg = str(input(""))

            if self.mujAES is not None:
                msg = self.mujAES.encrypt(msg.encode())
                self.sock.send(msg)
            else:
                msg = msg.encode()
                self.sock.send(b'\x13' + msg)
Exemplo n.º 10
0
class MessageHandler(asyncore.dispatcher_with_send):
    def __init__(self, sock):
        asyncore.dispatcher_with_send.__init__(self, sock)
        self.name = 0
        self.Key = DiffieHellman()
        self.Key.generate_public_key()
        self.cipher = None

    def handle_read(self):
        data = self.recv(4096).decode()
        print("data: ", data)
        if data:
            if self.cipher is not None:
                j = json.loads(self.cipher.decrypt(data))
            else:
                j = json.loads(data)
            print("loginfo: " + json.dumps(j))
            if j["action"] == "register" and self.cipher:
                try:
                    if not j["data"]["login"] in users.keys():
                            users[j["data"]["login"]] = j["data"]["pass"]
                            self.name = j["data"]["login"]
                            clients[self.name] = self
                            self.send(self.cipher.encrypt(json.dumps({"action": "register", "status": "AUTH_OK"})))
                    else:
                        self.send(self.cipher.encrypt(json.dumps({"action": "register", "status": "AUTH_ERR"})))
                        self.close()
                except Exception:
                    self.send(self.cipher.encrypt(json.dumps({"action": "register", "status": "AUTH_ERR"})))
                    self.close()

            elif j["action"] == "auth" and self.cipher:
                try:
                    if users[j["data"]["login"]] == j["data"]["pass"]:
                        self.name = j["data"]["login"]
                        clients[self.name] = self
                        self.send(self.cipher.encrypt(json.dumps({"action": "auth", "status": "AUTH_OK"})))
                    else:
                        self.send(self.cipher.encrypt(json.dumps({"action": "auth", "status": "AUTH_ERR"})))
                        self.close()
                except Exception:
                    self.send(self.cipher.encrypt(json.dumps({"action": "auth", "status": "AUTH_ERR"})))
                    self.close()

            elif j["action"] == "test":
                s = j["data"].encode()
                print(s)
            elif j["action"] == "message" and self.cipher:
                try:
                    chel = clients[j["data"]["to"]]
                    chel.send(chel.cipher.encrypt(json.dumps({"action": "message", "data": {"from": self.name, "message": j["data"]["message"]}})))
                except Exception:
                    self.send(self.cipher.encrypt(json.dumps({"action": "message", "status": "MESSAGE_ERR"})))

            elif j["action"] == "handshake":
                try:
                    h = SHA.new(int_to_base_str(self.Key.public_key).encode()).digest()
                    while 1:
                        k = random.StrongRandom().randint(1, ElGamalObjKey.p-1)
                        if GCD(k, ElGamalObjKey.p-1) == 1:
                            break
                    (SignR, SignS) = ElGamalObjKey.sign(h, k)
                    self.send(json.dumps({"action": "handshake", "status": "HANDSHAKE_OK", "data": {"pubkey": int_to_base_str(self.Key.public_key), "SignR": SignR, "SignS": SignS}}).encode())
                    print("pubkey: " + str(base_str_to_int(j["data"]["pubkey"])))
                    self.Key.generate_shared_secret(base_str_to_int(j["data"]["pubkey"]))
                    self.cipher = AESCipher(str(self.Key.shared_key).encode())
                except Exception as e:
                    print("ERROR: ", e)
                    self.send(json.dumps({"action": "handshake", "status": "HANDSHAKE_ERR"}).encode())
            else:
                print("WATAFA")
Exemplo n.º 11
0
def requestHandler(conn, addr):
    '''
		This method handles a new download request
	'''

    # First generate a public-private key pair
    dh = DiffieHellman()
    dh.generate_public_key()
    publicKey = dh.public_key

    # Next, send the public key using KEY_EXCHANGE. The segment size is 2479.
    conn.sendall(('KEY_EXCHANGE\n' + str(publicKey)).encode('utf-8',
                                                            errors='ignore'))

    # Receive a similar segment from client. This segment contains the client's public key.
    data = receiveData(conn, 2479)

    messageType = data.decode('utf-8', errors='ignore').split('\n')[0]
    if messageType != 'KEY_EXCHANGE':
        print("The client sent an illegal response. Closing connection..")
        conn.close()
        return

    clientPublicKey = int(data.decode('utf-8', errors='ignore').split('\n')[1])
    sharedKey = ''

    # Generate the shared key using Diffie Hellman algorithm and the public key of client and server
    try:
        dh.generate_shared_secret(clientPublicKey)
        sharedKey = bytes.fromhex(dh.shared_key)
    except Exception as e:
        print("The client sent an illegal response. Closing connection..")
        conn.close()
        return

    print('Key exchange successful: ' + dh.shared_key)

    print('Generating Ciphers..')

    # Generate a cipher which will use the shared key to encrypt all outgoing data

    cipher = AES.new(sharedKey, AES.MODE_CBC,
                     'jdirlfhixhtkwlif'.encode('utf-8'))

    print('Encrypting File list..')

    # Encrypt the file list with the cipher

    sharedFilesList = []

    for i in sharedFiles:
        sharedFilesList.append(i)

    fileList = ('\n'.join(sharedFilesList)).encode('utf-8')
    encryptedFileList = cipher.encrypt(pad(fileList, AES.block_size))
    requiredSize = len(encryptedFileList)

    # Send the file list size. We use FILELIST to send the file list size
    print('Sending File List..')

    conn.sendall(
        ('FILELIST\n' + padInteger(requiredSize, 20)).encode('utf-8',
                                                             errors='ignore'))

    # Wait till the server doesn't receive READY signal indicating that the client is ready to take the data
    data = receiveData(conn, 5).decode('utf-8', errors='ignore')

    if data != 'READY':
        print('Client is not ready to receive file list..')
        conn.close()
        return

    # Send the encrypted file list now. The segments contain only body and no header
    conn.sendall(encryptedFileList)

    # Wait for acknowloedgement
    data = receiveData(conn, 3).decode('utf-8', errors='ignore')
    if data == 'ACK':
        print('File list was received successfully by client..')
    else:
        print('No Acknowledgement received..')
        conn.close()
        return

    # Wait for a file request
    print('Waiting for request..')

    data = receiveData(conn, 28).decode('utf-8', errors='ignore').split('\n')
    idx = int(data[1])
    if data[0] != 'REQUEST':
        print('The client sent an illegal response. Closing connection..')
        conn.close()
    else:
        if idx < 0 or idx >= len(sharedFilesList):
            print(
                '\n\nThe client sent an illegal response. Closing connection..'
            )
            conn.close()
            return
        else:
            # Open the requested file. Encrypt it with the cipher and send it.
            fileName = sharedFilesList[idx].split('/')
            fileName = fileName[len(fileName) - 1]
            file = open(sharedFilesList[idx], 'rb')
            unencryptedData = file.read()
            file.close()
            cipher = AES.new(sharedKey, AES.MODE_CBC,
                             'jdirlfhixhtkwlif'.encode('utf-8'))
            encryptedData = cipher.encrypt(pad(unencryptedData,
                                               AES.block_size))
            requiredPackets = len(encryptedData)

            # Send the file size. We use FILE to send the file size
            conn.sendall(('FILE\n' + padInteger(requiredPackets, 20)).encode(
                'utf-8', errors='ignore'))

            # Wait for the ready signal
            data = receiveData(conn, 5).decode('utf-8', errors='ignore')
            if data != 'READY':
                print('Client is not ready to receive the file..')
                conn.close()
                return
            print("Sending the file '" + fileName + "'.")

            # Sent the encrypted file
            conn.sendall(encryptedData)
            print("Sent! Awaiting Acknowledgement..")

            # Wait for acknowledgement
            data = receiveData(conn, 3).decode('utf-8', errors='ignore')
            if data == 'ACK':
                print('Client received the file successfully')
                conn.close()
            else:
                print('An unknown error occured in file transfer')
                conn.close()
Exemplo n.º 12
0
class Client:

    def __init__(self, node_table):
        self.next_node = ""
        self.id = "client"
        self.node_table = node_table
        self.send_ops = {
            OP.CREATE: self.get_create_packet,
            OP.EXTEND: self.get_extend_packet
        }
        self.setup_keys()
        self.connect_to_signals()

    def setup_keys(self):
        self.aes_keys = {}
        self.dhke = DiffieHellman()
        self.dhke.generate_public_key()
        self.dh_pub = str(self.dhke.public_key).encode('utf8')
        self.__dh_sharedkey = None

    def connect_to_signals(self):
        dispatcher.connect(self.handle_created, signal=OP.CREATED, sender=dispatcher.Any)
        dispatcher.connect(self.handle_extended, signal=OP.EXTENDED, sender=dispatcher.Any)
        dispatcher.connect(self.handle_extended, signal=OP.EXTEND, sender=dispatcher.Any)

    def get_create_packet(self, receivers):
        iniciopKp=time.time()
        receiver = self.node_table[receivers[0]]
        msg = self.dh_pub
        enc_msg = rsa.encrypt(msg, receiver.pubkey)
        packet = Packet(src_id="client", op=OP.CREATE,
                        dest=receiver.id, payload=(enc_msg, None))
        print("client: Sending CREATE packet to {}".format(receiver))
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')
        return packet

    def send_message(self, receivers, op):
        iniciopKp=time.time()
        receivers = receivers.split()
        self.next_node = receivers[len(receivers) - 1]
        packet = self.send_ops[op](receivers)
        dispatcher.send(signal=op, sender=self, packet=packet)
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')

    def handle_created(self, packet):
        if packet.dest != self.id:
            return
        iniciopKp=time.time()
        print("client: Handling CREATED packet from {}".format(packet.src))
        (other_key, key_hash) = packet.msg
        # Generate the shared key
        self.dhke.generate_shared_secret(other_key)
        shared = self.dhke.shared_key
        m_key_hash = hashlib.sha1(str(shared).encode("utf-8")).hexdigest()

        if m_key_hash == key_hash:
            print("{}: DH Hash Comparison from {} SUCCESS".format(self.id, packet.src))
            self.__dh_sharedkey = shared
            self.aes_keys[packet.src] = shared
            print("client: Entry node is now set to: ", self.next_node)
            finpKp=time.time()
            print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')
            return
        print("{}: DH Hash Comparison from {} FAIL".format(self.id, packet.src))
        

    def handle_extended(self, packet):
        if packet.dest != self.id:
            return
        iniciopKp=time.time()
        print("client: Handling CREATED packet from {}".format(packet.src))
        if not packet.decrypt_aes(self.aes_keys[packet.src]):
            print("{}: Decryption of EXTENDED packet from {} FAIL".format(self.id, packet.src))
            return
        print("{}: Decryption of EXTENDED packet from {} SUCCESS".format(self.id, packet.src))
        (other_key, key_hash) = tuple(packet.msg.split('|||'))
        other_key = int(other_key)
        key_hash = key_hash.strip()
        self.dhke.generate_shared_secret(other_key)
        shared = self.dhke.shared_key
        m_key_hash = hashlib.sha1(str(shared).encode("utf-8")).hexdigest()

        if m_key_hash == key_hash:  # Only go through if hash matches
            print("{}: DH Hash Comparison from {} SUCCESS".format(self.id, packet.src))
            self.__dh_sharedkey = shared
            self.aes_keys[packet.src] = shared
            print("client: Connection established with {}".format(self.next_node))
            finpKp=time.time()
            print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')
            return

        print("{}: DH Hash Comparison from {} FAIL".format(self.id, packet.src))
        

    # Extend always gets wrapped with everything in the the AES Keys list
    def get_extend_packet(self, receivers):
        msg = "Type:     Extend"
        iniciopKp=time.time()
        extend_messages = {}
        for j in range(len(receivers) - 1):
            extend_messages[receivers[j]] = aes_encrypt(msg, self.aes_keys[receivers[j]])

        def recursive_extend(recs, node_index):
            if node_index == len(recs) - 1:
                create_packet = self.get_create_packet(recs[node_index:])
                create_packet.src = recs[node_index - 1]
                return create_packet
            return Packet(src_id="client", op=OP.EXTEND, dest=recs[0],
                          payload=(extend_messages[recs[node_index]], recursive_extend(recs, node_index + 1)))

        packet = recursive_extend(receivers, 0)
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')
        return packet
Exemplo n.º 13
0
class Sender:
    def __init__(self):
        self._sock_to_receiver = socket.socket(socket.AF_INET,
                                               socket.SOCK_STREAM)
        self._sock_to_mb = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self._df = DiffieHellman()
        self._df.generate_private_key()
        self._df.generate_public_key()

        self._session_key = None
        self._k = None
        self._k_rand = None

    def connect(self, address):
        """
        The sender(S) in this connect method will attempt to connect
        to the receiver(R) by a regular sock connection. If the
        connection is set up successfully, S and R will execute a key
        exchange protocol then both of them will get a shared secret
        key. After that three keys (a session key Kssl, a key K used in our
        detection protocol, and a key Krand used as a seed) will be derived
        from this secret key. Then, S will try to connect to the middle-
        box by another regular sock connection. If the connection is
        set up successfully, S will execute a secure computation with MB
        so that MB can obtain rules encrypted with key K without knowing K.
        :param address: the receiver's address
        :return:
        """
        try:
            self._sock_to_receiver.connect(address)
        except socket.error as error:
            print(f'Could not connect with the receiver: {error}')
            exit(1)
        except TypeError as error:
            print(f'Type error: {error}')
            exit(1)
        else:
            self._key_exchange(self._df.public_key)
            self._derive_from_secret()
            print('session key', self._session_key)

        try:
            self._sock_to_mb.connect(BLINDBOX_ADDRESS)
        except socket.error as error:
            print(f'Could not connect with blindBox: {error}')
            exit(1)
        except TypeError as error:
            print(f'Type error: {error}')
            exit(1)
        else:
            self._rule_preparation()

    def _key_exchange(self, public_key):
        """
        After a key exchange using Diffie-Hellman algorithm,
        the sender will agree on a shared secret with the receiver.
        :param public_key: The sender's public key for key exchange.
        :return: None
        """
        key_to_bytes = str(public_key).encode()
        self._sock_to_receiver.sendall(key_to_bytes)

        data = self._sock_to_receiver.recv(20480)
        print(f'data received from the receiver {data}')

        try:
            pk_from_receiver = int(data)
        except ValueError:
            print('Invalid data type!')
        else:
            if self._df.verify_public_key(pk_from_receiver):
                self._df.generate_shared_secret(pk_from_receiver)
                print('I got the shared key:', self._df.shared_key)
            else:
                raise ValueError('Invalid public key from the sender!')

    def _derive_from_secret(self):
        """
        Use the shared key to derive three keys by using a pseudorandom
        generator.
        _session_key: used to encrypt the traffic in the socket.
        _k: used in the detection protocol
        _k_rand: used as a seed for randomness. Since both end-points have the same seed,
                 they will generate the same randomness.
        :return: None
        """
        key_to_bytes = str(self._df.shared_key).encode()

        randoms = Randoms()
        self._session_key = derive_key(key_to_bytes, randoms.random1)
        self._k = derive_key(key_to_bytes, randoms.random2)
        self._k_rand = derive_key(key_to_bytes, randoms.random3)

    def _rule_preparation(self):
        """
        Sender will use garbled circuits to compute AES(r,k) with the BlindBox while
        the sender do not know the rule and the BlindBox do not know the key k.
        :return:
        """
        key_numbers = int(self._sock_to_mb.recv(1024))
        for i in range(key_numbers):
            output = subprocess.getoutput(OBLIVC_AES_PATH + "/a.out 1235 -- " +
                                          self._k.decode())
            while output == "TCP accept failed":
                output = subprocess.getoutput(OBLIVC_AES_PATH +
                                              "/a.out 1235 -- " +
                                              self._k.decode())

    def send(self, data):
        encrypted_data = aes_encrypt(data.encode(), self._session_key)

        self._sock_to_mb.sendall(encrypted_data)
        sleep(0.4)

        tokens = nltk.word_tokenize(data)
        encrypted_tokens = b''
        for token in tokens:
            encrypted_tokens += dpi_encrypt(token.encode(), self._session_key)
            encrypted_tokens += b' '

        self._sock_to_mb.sendall(encrypted_tokens)
Exemplo n.º 14
0
    def login_proto(self):
        print("something")
        Message = COMM_MESSAGE()

        data, temp = self.connection_from_client.recvfrom(4096)
        print(temp)
        Message.ParseFromString(data)

        if Message.type == Message.TYPE.LOGIN:
            N1 = os.urandom(16)
            N1 = N1.hex()
            print(N1)

            digest = sha256()
            digest.update(N1.encode())
            Message.N1_hash = digest.hexdigest()
            Message.message = N1[5:]
            self.connection_from_client.sendall(Message.SerializeToString())

            data, temp = self.connection_from_client.recvfrom(4096)
            print(temp)
            Message.ParseFromString(data)

            if Message.N1 == N1:
                print("Puzzle figured out!")
            else:
                print("Wrong!")

            bob = DiffieHellman(group=5, key_length=200)
            bob.generate_public_key()
            Message.gb_mod_p = str(bob.public_key)
            bob.generate_shared_secret(int(Message.message))
            Kas = str(bob.shared_secret)[:16].encode()
            # Kas = (bob.shared_secret).to_bytes(16,sys.byteorder)
            print("Shared secret is:", int.from_bytes(Kas, sys.byteorder))
            Message.gb_mod_p = str(bob.public_key)

            #### loading private key
            with open("private_key.pem", "rb") as key_file:
                private_key = serialization.load_pem_private_key(
                    key_file.read(), password=None, backend=default_backend())

            #### encryption
            plain_text_sign = Message.message + "|" + Message.gb_mod_p
            plain_text_sign = plain_text_sign.encode()
            ### sign the text
            signature = private_key.sign(
                plain_text_sign,
                paddings.PSS(mgf=paddings.MGF1(hashes.SHA256()),
                             salt_length=paddings.PSS.MAX_LENGTH),
                hashes.SHA256())
            #### Timestamp
            timestamp = str(int(time.time()))
            timestamp = timestamp.encode()
            plain_text = signature + timestamp

            iv = os.urandom(16)
            Message.iv = iv
            padder = padding.PKCS7(128).padder()
            padded_data = padder.update(plain_text)
            padded_data += padder.finalize()
            plain_text_padded = padded_data

            authenticate_data = b'Final Project'
            # self.Message.authenticate_data = authenticate_data

            # GCM Mode, we also need an IV
            # encrypt
            cipher = Cipher(algorithms.AES(Kas),
                            modes.GCM(iv),
                            backend=default_backend())
            encryptor = cipher.encryptor()
            encryptor.authenticate_additional_data(authenticate_data)
            cipher_text = encryptor.update(
                plain_text_padded) + encryptor.finalize()
            Message.cipher_text = cipher_text
            Message.tag = encryptor.tag

            self.connection_from_client.sendall(Message.SerializeToString())

            ### Decrypt and verify the client:
            data = self.connection_from_client.recv(4096)
            Message.ParseFromString(data)
            #  AES  decryption
            decryptor = Cipher(algorithms.AES(Kas),
                               modes.GCM(iv, Message.tag),
                               backend=default_backend()).decryptor()
            decryptor.authenticate_additional_data(authenticate_data)
            decrypted_plain_text = decryptor.update(
                Message.cipher_text) + decryptor.finalize()

            # unpad
            unpadder = padding.PKCS7(128).unpadder()
            plain_text = unpadder.update(
                decrypted_plain_text) + unpadder.finalize()

            # Verify timestamp
            plain_text_timestamp = plain_text[-10:]
            message_timestamp = int(plain_text_timestamp)
            if ((int(time.time()) - message_timestamp) < 60):
                print("Timestamp verified")
            else:
                print("Timestamp failed!")

            ###
            plain_text = plain_text[0:len(plain_text) - 10]
            plain_text = plain_text.decode()
            username = plain_text.split("|")[0]
            password = plain_text.split("|")[1]
            #if username == "Yushen" and password == "123":
            #    verify = "Success"
            #else:
            #   verify = "Fail"
            verify = "Fail"
            if username in self.identities.keys():
                pass_digest = sha256()
                pass_digest.update(password.encode())
                pass_digest.update(self.identities[username]["salt"].encode())
                pass_hash = pass_digest.hexdigest()
                print(pass_hash, "is the passhash")
                if pass_hash == self.identities[username]["passhash"]:
                    verify = "Success"
            ####
            plain_text = verify.encode()
            timestamp = str(int(time.time()))
            timestamp = timestamp.encode()
            plain_text = plain_text + timestamp

            padder = padding.PKCS7(128).padder()
            padded_data = padder.update(plain_text)
            padded_data += padder.finalize()
            plain_text_padded = padded_data

            cipher = Cipher(algorithms.AES(Kas),
                            modes.GCM(iv),
                            backend=default_backend())
            encryptor = cipher.encryptor()
            encryptor.authenticate_additional_data(authenticate_data)
            cipher_text = encryptor.update(
                plain_text_padded) + encryptor.finalize()
            Message.cipher_text = cipher_text
            Message.tag = encryptor.tag

            self.connection_from_client.sendall(Message.SerializeToString())
            # connection_from_client.shutdown(0)
            # self.socket_from_client.shutdown(0)
            self.connection_from_client.close()
            self.socket_from_client.close()
Exemplo n.º 15
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-


from diffiehellman.diffiehellman import DiffieHellman

alice = DiffieHellman(group=18, key_length=1024)
bob = DiffieHellman(group=18, key_length=1024)

alice.generate_public_key()  # automatically generates private key
bob.generate_public_key()

alice.generate_shared_secret(bob.public_key, echo_return_key=True)
bob.generate_shared_secret(alice.public_key, echo_return_key=True)
a = alice.shared_key
b = bob.shared_key
Exemplo n.º 16
0
class Client:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    mujAES = None
    cli = None

    def __init__(self, adress='127.0.0.1'):

        self.sock.connect((adress, 9876))

        self.cli = DiffieHellman()
        self.cli.generate_public_key()
        self.vyzadatKlic()

        iThread = threading.Thread(target=self.sendMessage)
        iThread.daemon = True
        iThread.start()
        self.run()

    def run(self):
        while True:
            data = self.sock.recv(BUFSIZE)
            #misto na hrani si s daty
            if not data:
                #ukonceni komunikace
                break
            elif data[0:1] == b"\x11":
                #kdyz prijde ridici znak x11-posleme na vyzadani klic
                self.poslatKlic()
            elif data[0:1] == b"\x12":
                #kdyz prijde ridici znak x12 tak si nastavime klic ktery nasleduje po tomto bytu
                self.nastavitKlic(data[1:])

            elif data[0:1] == b"\x13":
                #nezasifrovana komunikace
                print(data.decode())
            elif data[0:1] == b"\x14":
                #nastaveni klice v pripade ze byl vyzadan nebo tak neco
                self.jinenastaveniklice(data[1:])
            else:
                #vychozi stav- prijdou data bez ridiciho znaku-> predpokladame ze jsou zasifrovana AESem podle dohodnuteho hesla
                data = self.mujAES.decrypt(data)
                print(data.decode())

    def poslatKlic(self):
        #posle ridici znak nasledovany klicem
        self.sock.send(b'\x12' + str(self.cli.public_key).encode())

    def jinenastaveniklice(self, data):
        #dela zajimave veci, ale jen v urcitem pripade
        self.cli.generate_shared_secret(int(data.decode()),
                                        echo_return_key=True)
        superklic = str(self.cli.shared_secret)
        xy = hashlib.sha256(superklic.encode()).hexdigest()[:32]
        print("2222222222222222222222222222")
        print(xy)
        self.mujAES = Encryptor(xy)

    def nastavitKlic(self, data):
        #nastavuje klic na zaklade dat ktere dostane
        self.cli.generate_shared_secret(int(data.decode()),
                                        echo_return_key=True)
        superklic = str(self.cli.shared_secret)
        xy = hashlib.sha256(superklic.encode()).hexdigest()[:32]
        print("111111111111111111111")
        print(xy)
        self.mujAES = Encryptor(xy)
        self.sock.send(b'\x14' + str(self.cli.public_key).encode())

    def vyzadatKlic(self):
        #nemam klic ale chci, poslu ridici znak
        self.sock.send(b'\x11')

    def sendMessage(self):
        #hlavni chatova smycka
        while True:
            msg = str(input(""))

            if self.mujAES is not None:
                msg = self.mujAES.encrypt(msg.encode())
                self.sock.send(msg)
            else:
                msg = msg.encode()
                self.sock.send(b'\x13' + msg)
Exemplo n.º 17
0
import socket
from Crypto.Cipher import AES
from Crypto.Hash import SHA256
from Crypto import Random
import base64
import random
from diffiehellman.diffiehellman import DiffieHellman


#testar mig fram
alice = DiffieHellman()
alice.generate_public_key()
UDP_IP = "127.0.0.1"
UDP_PORT = 5005


print("UDP target IP:",UDP_IP)
print("UDP target port:",UDP_PORT)
print("Public key: ", alice.public_key)

# Code stolen from: https://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256
#--------------------------------------------------------------------------------------------------------
BS=16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)

def encrypt(raw):
    raw = pad(raw)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(hash, AES.MODE_CBC, iv)
    return base64.b64encode(iv + cipher.encrypt(raw.encode("utf8")))
#--------------------------------------------------------------------------------------------------------
Exemplo n.º 18
0
class Receiver:
    def __init__(self):
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._sock_to_mb = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self._sock.bind(ADDRESS)
        self._sock.listen(10)

        self._df = DiffieHellman()
        self._df.generate_private_key()
        self._df.generate_public_key()

        self._session_key = None
        self._k = None
        self._k_rand = None

    def connection_setup(self):
        while True:
            # Wait for a connection
            connection, address = self._sock.accept()
            self._key_exchange(connection, self._df.public_key)
            print('My shared key:', self._df.shared_key)
            self._derive_from_secret()
            print('session key', self._session_key)

            try:
                self._sock_to_mb.connect(BLINDBOX_ADDRESS)
            except socket.error as error:
                print(f'Could not connect with blindBox: {error}')
                exit(1)
            except TypeError as error:
                print(f'Type error: {error}')
                exit(1)
            else:
                self._rule_preparation()

    def _key_exchange(self, connection, public_key):
        """
        After a key exchange using Diffie-Hellman algorithm,
        the sender will agree on a shared secret with the receiver.
        :param public_key: The sender's public key for key exchange.
        :return: None
        """
        data = connection.recv(20480)
        print(f'data received from the sender: {data}')

        try:
            pk_from_sender = int(data)
        except ValueError:
            print('Invalid data type!')
        else:
            if self._df.verify_public_key(pk_from_sender):
                self._df.generate_shared_secret(pk_from_sender)
                print('I got the shared key:', self._df.shared_key)
                connection.sendall(str(public_key).encode())
            else:
                raise ValueError('Invalid public key from the sender!')

    def _derive_from_secret(self):
        """
        Use the shared secret to derive three keys by using a pseudorandom
        generator.
        _session_key: used to encrypt the traffic in the socket.
        _k: used in our detection protocol
        _k_rand: used as a seed for randomness. Since both end-points have the same seed,
                 they will generate the same randomness.
        :return: None
        """
        key_to_bytes = str(self._df.shared_key).encode()

        randoms = Randoms()
        self._session_key = derive_key(key_to_bytes, randoms.random1)
        self._k = derive_key(key_to_bytes, randoms.random2)
        self._k_rand = derive_key(key_to_bytes, randoms.random3)

    def _rule_preparation(self):
        """
        Sender will use garbled circuits to compute AES(r,k) with the BlindBox while
        the sender do not know the rule and the BlindBox do not know the key k.
        :return:
        """
        key_numbers = int(self._sock_to_mb.recv(1024))
        for i in range(key_numbers):
            output = subprocess.getoutput(OBLIVC_AES_PATH + "/a.out 5321 -- " +
                                          self._k.decode())
            while output == "TCP accept failed":
                output = subprocess.getoutput(OBLIVC_AES_PATH +
                                              "/a.out 5321 -- " +
                                              self._k.decode())

    def receive(self):
        encrypted_traffic = self._sock_to_mb.recv(20480)
        encrypted_tokens = self._sock_to_mb.recv(20480)

        traffic = aes_decrypt(encrypted_traffic)

        self.check_tokens(traffic, encrypted_tokens)

    def check_tokens(self, traffic, encrypted_tokens):
        pass
class TestDiffieHellman(unittest.TestCase):
    def setUp(self):
        self.alice = DiffieHellman()
        self.bob = DiffieHellman()

    def test_equality_of_keys(self):
        self.alice.generate_public_key()
        self.bob.generate_public_key()

        alices_shared_key = self.alice.generate_shared_secret(self.bob.public_key)
        bobs_shared_key = self.bob.generate_shared_secret(self.alice.public_key)

        self.assertEqual(alices_shared_key, bobs_shared_key,
                         "There is a mismatch between two shared secrets. Both shared secrets should be the same. This is bad.")

    def test_decorators_private_key(self):
        self.alice.generate_public_key()
        self.assertIn("_DiffieHellman__private_key", self.alice.__dict__)

    def test_generate_private_key(self):
        self.alice.generate_private_key()
        self.assertIn("_DiffieHellman__private_key", self.alice.__dict__)

    def test_generate_public_key(self):
        self.alice.generate_public_key()
        self.assertIn("public_key", self.alice.__dict__)

    def test_verify_public_key(self):
        self.alice.generate_public_key()
        self.bob.generate_public_key()
        self.assertTrue(self.alice.verify_public_key(self.bob.public_key))
        self.assertFalse(self.alice.verify_public_key(2))
        self.assertFalse(self.alice.verify_public_key(self.alice.prime - 1))
Exemplo n.º 20
0
class ClientCipher:
    def __init__(self, mode, hmac_hash_type):
        self.mode = mode
        self.hmac_hash_type = hmac_hash_type

        # store client app keys
        self.client_app_keys = self.generate_keys()

        # load server pub. key
        self.server_pub_key = serialization.load_pem_public_key(
            open(SERVER_PUB_KEY, "rb").read(), backend=default_backend())

        # Diffie Hellman
        self.client_dh = None

        # save session key
        self.session_key = None

        # warrant nounces
        self.warrant_nounces = {}

        # how many requests were made to the server
        self.request_to_server = 1

    def generate_keys(self):
        private_key = rsa.generate_private_key(public_exponent=65537,
                                               key_size=2048,
                                               backend=default_backend())

        public_key = private_key.public_key()

        return private_key, public_key

    """
    ASYMMETRIC CIPHER
    """

    def asym_cipher(self, pub_key, raw_data):
        pickle_dumps = pickle.dumps(raw_data)
        return pub_key.encrypt(
            pickle_dumps,
            _aspaadding.OAEP(mgf=_aspaadding.MGF1(algorithm=hashes.SHA256()),
                             algorithm=hashes.SHA256(),
                             label=None))

    def asym_decipher(self, private_key, ciphered_data):
        data = private_key.decrypt(
            ciphered_data,
            _aspaadding.OAEP(mgf=_aspaadding.MGF1(algorithm=hashes.SHA256()),
                             algorithm=hashes.SHA256(),
                             label=None))
        return pickle.loads(data)

    def asym_sign(self, private_key, data):
        return private_key.sign(
            data,
            _aspaadding.PSS(mgf=_aspaadding.MGF1(hashes.SHA256()),
                            salt_length=_aspaadding.PSS.MAX_LENGTH),
            hashes.SHA256())

    def asym_validate_sign(self, data, sign_data, public_key):
        verifier = public_key.verifier(
            sign_data,
            _aspaadding.PSS(mgf=_aspaadding.MGF1(hashes.SHA256()),
                            salt_length=_aspaadding.PSS.MAX_LENGTH),
            hashes.SHA256())

        verifier.update(data)
        return verifier.verify()

    """
    SYMMETRIC KEY CIPHER
    """

    def sym_cipher(self, obj, ks, iv=os.urandom(16), mode=None):
        """

        :param iv: key to cipher the object
        :param obj: object to be ciphered
        :param ks: key to cipher the object
        :param mode:
        """
        if mode is None:
            mode = modes.CTR

        cipher = Cipher(algorithms.AES(ks),
                        mode(iv),
                        backend=default_backend())

        # pickle makes the serialization of the object
        pickle_dumps = pickle.dumps(
            [obj, os.urandom(RANDOM_ENTROPY_GENERATOR_SIZE)])

        # encrypt obj dumped data
        encryptor = cipher.encryptor()
        ciphered_obj = encryptor.update(pickle_dumps) + encryptor.finalize()

        return iv, ciphered_obj

    def sym_decipher(self, obj, ks, iv, mode=None):
        """

        :param obj:
        :param ks:
        :param iv:
        :param mode:
        :return:
        """
        if mode is None:
            mode = modes.CTR

        cipher = Cipher(algorithms.AES(ks),
                        mode(iv),
                        backend=default_backend())

        decryptor = cipher.decryptor()
        deciphered_data = decryptor.update(obj) + decryptor.finalize()
        data, random = pickle.loads(deciphered_data)
        return data

    """
    HYBRID A-SYMMETRIC KEY CIPHER
    """

    def hybrid_decipher(self, obj, private_key, ks=None):
        obj, random_pickle = pickle.loads(base64.b64decode(obj))

        # decipher using rsa private key
        if ks is None:
            ks = self.asym_decipher(private_key, base64.b64decode(obj["key"]))

        # decipher using rsa private key
        iv = self.asym_decipher(private_key, base64.b64decode(obj["iv"]))

        # decipher using symmetric AES CTR
        return self.sym_decipher(base64.b64decode(obj["obj"]), ks, iv)

    def hybrid_cipher(self,
                      obj,
                      public_key,
                      ks=os.urandom(32),
                      cipher_key=True):
        # cipher using symmetric cipher AES CTR
        # returns the ciphered obj with the IV

        iv, ciphered_obj = self.sym_cipher(obj, ks)

        # iv ciphered with the public key
        iv_encrypted = self.asym_cipher(public_key, iv)

        # key ciphered with the public_key
        if cipher_key:
            # send ks to the server
            key_encrypted = self.asym_cipher(public_key, ks)

            pickle_dumps = pickle.dumps(
                [{
                    "obj": base64.b64encode(ciphered_obj).decode(),
                    "iv": base64.b64encode(iv_encrypted).decode(),
                    "key": base64.b64encode(key_encrypted).decode()
                },
                 os.urandom(RANDOM_ENTROPY_GENERATOR_SIZE)])
            return base64.b64encode(pickle_dumps)
        else:
            pickle_dumps = pickle.dumps(
                [{
                    "obj": base64.b64encode(ciphered_obj).decode(),
                    "iv": base64.b64encode(iv_encrypted).decode()
                },
                 os.urandom(RANDOM_ENTROPY_GENERATOR_SIZE)])
            return base64.b64encode(pickle_dumps)

    """
    KEY DERIVATION FUNCTION GIVEN THE MASTER KEY
    """

    def key_derivation(self,
                       masterkey,
                       salt=os.urandom(32),
                       iterations=100000):
        kdf = PBKDF2HMAC(algorithm=hashes.SHA512(),
                         length=32,
                         salt=salt,
                         iterations=iterations,
                         backend=default_backend())

        return kdf.derive(masterkey), salt

    """
    HMAC - create
    """

    def hmac_update_finalize(self, key, data):
        if not isinstance(key, bytes) and isinstance(key, str):
            key = key.encode()

        if not isinstance(data, bytes):
            data = pickle.dumps(data)

        h = hmac.HMAC(key, self.hmac_hash_type(), backend=default_backend())
        h.update(data)
        return h.finalize()

    """
    HMAC - verify
    """

    def hmac_verify(self, key, hmac_data, data):
        if not isinstance(key, bytes) and isinstance(key, str):
            key = key.encode()

        if not isinstance(data, bytes):
            data = pickle.dumps(data)

        h = hmac.HMAC(key, self.hmac_hash_type(), backend=default_backend())
        h.update(data)
        return h.verify(hmac_data)

    """
    SECURE LAYER ENCAPSULATION
    """

    def secure_layer_encrypt(self, msg: bytes):
        # generate a nounce that will be a warrant of the message
        # the nounce will be stored with the respective session key iteration
        # after retrieved it will be deleted and then the message exchanged between
        # the server and the client will be never deciphered again
        nounce = sha256(json.dumps(msg).encode() +
                        os.urandom(32)).hexdigest().encode()
        key, salt = self.key_derivation(self.session_key,
                                        iterations=self.request_to_server)
        iv = os.urandom(16)

        # saving the iterations ans salt used for the given nounce
        self.warrant_nounces[nounce] = {
            "iterations": self.request_to_server,
            "salt": salt,
            "seq": self.request_to_server
        }

        # salt (the salt used to the KDF), nounce (the genuineness warrant), iv (used in the cipher)
        sec_data = pickle.dumps({
            "salt": salt,
            "nounce": nounce,
            "iv": iv,
            "seq": self.request_to_server
        })

        # sec_data ciphered
        sec_data_ciphered = self.hybrid_cipher(sec_data, self.server_pub_key)

        # HMAC
        hmac_key = sha256(key).hexdigest()
        hmac_data = self.hmac_update_finalize(hmac_key, msg)

        msg = [msg, hmac_data]
        pickle_dumps = pickle.dumps(msg)

        # cipher with symmetric cipher the message content
        iv, ciphered_obj = self.sym_cipher(pickle_dumps,
                                           key,
                                           iv=iv,
                                           mode=self.mode)

        # message to be signed and sent to the server
        return_message = {
            "data": base64.b64encode(ciphered_obj).decode(),
            "sec_data": base64.b64encode(sec_data_ciphered).decode()
        }

        self.request_to_server += 1

        # dump the return message
        pickle_dumps = pickle.dumps(return_message)

        return base64.b64encode(pickle_dumps)

    def secure_layer_decrypt(self, msg: bytes):
        msg = pickle.loads(base64.b64decode(msg))

        # get sec_data content
        sec_data = pickle.loads(
            self.hybrid_decipher(base64.b64decode(msg["sec_data"]),
                                 self.client_app_keys[0]))

        nounce = sec_data["nounce"]

        if nounce not in self.warrant_nounces:
            print(
                "Something went wrong with the nounce in the secure layer decrypt."
            )
            exit(1)

        if sec_data["seq"] != (self.warrant_nounces[nounce]["seq"] + 1):
            print("Received wrong sequence number by the server")
            exit(1)

        # the nounce warrant allow us to retrieve the iterations and the salt used to derive the key
        iterations = self.warrant_nounces[nounce]["iterations"]
        salt = self.warrant_nounces[nounce]["salt"]

        # now it can be deleted
        del self.warrant_nounces[nounce]

        key, salt = self.key_derivation(self.session_key,
                                        iterations=iterations,
                                        salt=salt)

        raw_msg = pickle.loads(
            self.sym_decipher(base64.b64decode(msg["data"]),
                              ks=key,
                              iv=sec_data["iv"],
                              mode=self.mode))

        # verify hmac
        hmac_key = sha256(key).hexdigest()
        self.hmac_verify(hmac_key, raw_msg[1], raw_msg[0])

        return raw_msg[0]

    """
    CLIENT SERVER SESSION KEY NEGOTIATION
    """

    def negotiate_session_key(self, phase, val=None):
        """
        First the Application loads the server public key that is distributed into the client application.
        It's ok to publicly distribute the Public Key but it must be verified if the public key
        of the server is still the same. If not, it must be updated. Another way is to request the public key
        of the server and ask for the user fingerprint verification. {verification missing}

        After that, the client app generate DH values (private and public) to exchange with the server in order to
        get the shared secret session key.

        Phase 1: [CLIENT]: send generated DH public key to the server (signed) and the app client rsa public key (signed too).
        The sent values will be ciphered with a random key and signed.

        Phase 2: [SERVER]: the server generates the private and public DH pair. Then using the server private key, the
        server decipher the DH public received encrypted value. Using again the server private key, the server deciphers
        the client public key and loads it into memory.
        Then, using the client public key, validates the signature made for the DH public value and public key received.
        Using the received client public key, the server will make a hybrid cipher (AES and RSA) of the DH server
        generated public key. After the cipher, the server will sign with the server private key the data ciphered.

        Phase 3: [CLIENT]: using the stored server public key the client will validate the signature received. After
        that using the client private key, the client will decipher the DH public value received from the server. Then
        using the DH public value, the client will generate the DH shared secret and using PBKDF2HMAC will use a key
        derivation function. The master key will be the secret DH shared value and will have 100 000 iterations. The
        salt is random and so, it will be ciphered and sent to the server.
        The session key has been generated.

        Phase 4: [SERVER]: Using the client public key it will be verified the signature of the received value. Using
        the server private key and a hybrid cipher the PBKDF2 salt will be deciphered. Using the key derivation
        function the session key will be obtained in the server.

        Then, there is a secure channel between the server and the client.

        :param val: value sent by the server
        :param phase: 1, 2, 3 or 4
        :return: value to send to the server
        """
        if phase == 1:
            # client generate DH private and public key
            self.client_dh = DiffieHellman(key_length=256)
            self.client_dh.generate_public_key()

            # cipher DH public key with server pub. key
            # cipher the client DH public key
            client_dh_ciphered = self.hybrid_cipher(self.client_dh.public_key,
                                                    self.server_pub_key)

            # cipher the client public key

            pem = self.client_app_keys[1].public_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PublicFormat.SubjectPublicKeyInfo)

            client_public_key_ciphered = self.hybrid_cipher(
                pem, self.server_pub_key)

            return {
                "data":
                client_dh_ciphered.decode(),
                "data_signature":
                base64.b64encode(
                    self.asym_sign(self.client_app_keys[0],
                                   client_dh_ciphered)).decode(),
                "public_key":
                client_public_key_ciphered.decode(),
                "public_key_signature":
                base64.b64encode(
                    self.asym_sign(self.client_app_keys[0],
                                   client_public_key_ciphered)).decode(),
                "phase":
                2,
                "cipher":
                "AES&RSA",
                "mode":
                self.mode.name,
                "hmac_hash":
                self.hmac_hash_type.name
            }
        elif phase == 3:
            # validate the DH received value
            self.asym_validate_sign(
                val["data"].encode(),
                base64.b64decode(val["data_signature"].encode()),
                self.server_pub_key)

            # decipher the received DH value
            server_dh_pub = self.hybrid_decipher(val["data"],
                                                 self.client_app_keys[0])

            # generate shared secret (client session key)
            self.client_dh.generate_shared_secret(server_dh_pub)

            # save the session key
            self.session_key, salt = self.key_derivation(
                str(self.client_dh.shared_secret).encode())

            salt_ciphered = self.hybrid_cipher(salt, self.server_pub_key)

            return {
                "phase":
                4,
                "data":
                salt_ciphered.decode(),
                "data_signature":
                base64.b64encode(
                    self.asym_sign(self.client_app_keys[0],
                                   salt_ciphered)).decode()
            }
Exemplo n.º 21
0
class TestDiffieHellman(unittest.TestCase):
    def setUp(self):
        self.alice = DiffieHellman()
        self.bob = DiffieHellman()

    def test_equality_of_keys(self):
        self.alice.generate_public_key()
        self.bob.generate_public_key()

        alices_shared_key = self.alice.generate_shared_secret(
            self.bob.public_key)
        bobs_shared_key = self.bob.generate_shared_secret(
            self.alice.public_key)

        self.assertEqual(
            alices_shared_key, bobs_shared_key,
            "There is a mismatch between two shared secrets. Both shared secrets should be the same. This is bad."
        )

    def test_decorators_private_key(self):
        self.alice.generate_public_key()
        self.assertIn("_DiffieHellman__private_key", self.alice.__dict__)

    def test_generate_private_key(self):
        self.alice.generate_private_key()
        self.assertIn("_DiffieHellman__private_key", self.alice.__dict__)

    def test_generate_public_key(self):
        self.alice.generate_public_key()
        self.assertIn("public_key", self.alice.__dict__)

    def test_verify_public_key(self):
        self.alice.generate_public_key()
        self.bob.generate_public_key()
        self.assertTrue(self.alice.verify_public_key(self.bob.public_key))
        self.assertFalse(self.alice.verify_public_key(2))
        self.assertFalse(self.alice.verify_public_key(self.alice.prime - 1))
Exemplo n.º 22
0
    def handle_sock(self, sock, addr):  # sock 的流程
        ##############################
        #### Handle a new request#####
        ####                     #####
        ##############################
        while True:
            data = sock.recv(4096)
            # print ("I have received a new message!")
            MessageRec = COMM_MESSAGE()
            MessageRec.ParseFromString(data)

            if (MessageRec.type == COMM_MESSAGE.TYPE.LOGOUT):
                plain_text = self.decryption_with_timestamp_in_client(
                    MessageRec, self.socket_from_list[src][1],
                    self.socket_from_list[src][2])
                plain_text = plain_text.decode()
                print("I received log out request_1")
                print(plain_text)
                if (plain_text == "log out"):
                    MessageSend = COMM_MESSAGE()
                    MessageSend.type = COMM_MESSAGE.TYPE.CONFIRM
                    plain_text = 'log out confirmed'.encode() + str(
                        int(time.time())).encode()
                    MessageSend = self.encryption_in_client(
                        MessageSend, self.socket_from_list[src][1],
                        self.socket_from_list[src][2], plain_text)
                    self.socket_from_list[src][0].sendall(
                        MessageSend.SerializeToString())
                    self.socket_from_list[src][0].close()

                    del self.socket_from_list[src]
                    del self.user_online[src]

            if (MessageRec.type == COMM_MESSAGE.TYPE.CLIENT_TO_CLIENT):
                plain_text = self.decryption_of_ticket_with_timestamp(
                    MessageRec.ticket, MessageRec.ticket_tag)
                plain_text = plain_text.decode()
                src = plain_text.split(" ")[0]
                # self.socket_from_list[src] = []
                # self.socket_from_list[src].append (sock)
                kab_temp = plain_text.split(" ")[1].encode()
                iv_temp = plain_text.split(" ")[2].encode()
                plain_text = self.decryption_with_timestamp_in_client(
                    MessageRec, kab_temp, iv_temp)
                plain_text = plain_text.decode()

                N1 = int(plain_text)
                y = os.urandom(8)
                x = y.hex()
                N2 = int(x, 16)
                plain_text = (str(N1 - 1) + " " + str(N2)).encode() + str(
                    int(time.time())).encode()
                # .encode() + " ".encode + str(N2).encode()

                MessageSend = COMM_MESSAGE()

                bob = DiffieHellman(group=5, key_length=200)
                bob.generate_public_key()
                MessageSend.gb_mod_p = str(bob.public_key)
                MessageSend = self.encryption_in_client(
                    MessageSend, kab_temp, iv_temp, plain_text)
                sock.sendall(MessageSend.SerializeToString())

                MessageRec = COMM_MESSAGE()
                data = sock.recv(4096)
                MessageRec.ParseFromString(data)

                plain_text = self.decryption_with_timestamp_in_client(
                    MessageRec, kab_temp, iv_temp)
                N2_rec = int(plain_text.decode())
                if N2 - 1 == N2_rec:
                    bob.generate_shared_secret(int(MessageRec.message))
                    kas = str(bob.shared_secret)[:16].encode()
                    # self.socket_list[src].append(str(bob.shared_secret)[:16].encode())
                    temp = os.urandom(16)
                    iv = temp.hex()[:16].encode()
                    # self.socket_list[src].append(iv)

                    plain_text = ("Confirm " +
                                  self.client_name).encode() + str(
                                      int(time.time())).encode()
                    MessageSend = COMM_MESSAGE()
                    MessageSend.iv = iv
                    MessageSend = self.encryption_in_client(
                        MessageSend, kas, iv, plain_text)
                    sock.sendall(MessageSend.SerializeToString())

                    MessageRec = COMM_MESSAGE()
                    data = sock.recv(4096)
                    MessageRec.ParseFromString(data)

                    plain_text = self.decryption_with_timestamp_in_client(
                        MessageRec, kas, iv)
                    plain_text = plain_text.decode()
                    if plain_text.split(
                            " ")[0] == "Confirm" and plain_text.split(
                                " ")[1] == src:
                        client_sk = socket.socket()
                        client_sk.connect(('127.0.0.1', addr[1]))
                        # print ("I will use this socket to talk to",src,":", client_sk)
                        self.socket_from_list[src] = []
                        self.socket_from_list[src].append(client_sk)
                        self.socket_from_list[src].append(kas)
                        self.socket_from_list[src].append(iv)
                        # print("I have succeed in setting up connection with", src, "with session key:", kas)
                        # print("We use this socket to chatting:", sock)
                    else:
                        print("The adversary modify the CONFIRM message")
                else:
                    print("N2 puzzle wrong!")
                    sys.exit(1)
            else:
                plain_text = self.decryption_with_timestamp_in_client(
                    MessageRec, self.socket_from_list[src][1],
                    self.socket_from_list[src][2])
                plain_text = plain_text.decode()
                print("From", src, ":", plain_text)
Exemplo n.º 23
0
class EncryptionPacket:
    PACKET_MAGIC_CODE = struct.pack('>BBBB', 0x43, 0x52, 0x59, 0x54)
    FUNCTION_INITIALIZE_HANDSHAKE = 0x00
    FUNCTION_SECURE_COMMUNICATION = 0x02

    def __init__(self, device, other):
        self.device = device
        self.other = other
        self._user = None

    def generate_key(self):
        self._user = DiffieHellman()
        self._user.generate_public_key()

    def send_complete_public_data(self):
        data = bytearray(EncryptionPacket.PACKET_MAGIC_CODE) + struct.pack(
            ">BB", EncryptionPacket.FUNCTION_INITIALIZE_HANDSHAKE, 0x55)
        self.other.send(data)

    def recv_public_data(self, data):
        hash_length = data[0]
        hash_value = data[1:hash_length + 1]
        hash_str = str()
        for i in range(0, len(hash_value)):
            hash_str += '{:02x}'.format(int(hex(hash_value[i]), 16))
        print("Digest: {}".format(hash_str))
        public_key_data = data[hash_length + 1:]
        public_key = str()
        for i in range(0, len(public_key_data)):
            public_key += '{:02X}'.format(int(hex(public_key_data[i]), 16))

        m = hashlib.sha256()
        m.update(public_key.encode('utf-8'))
        other_hash_value = m.hexdigest()

        print("Calculated digest: {}".format(other_hash_value))

        # the public key is not matched
        if hash_str != other_hash_value:
            return -1

        # Convert str to big-integer
        received_public_key = int(public_key)
        self._user.generate_shared_secret(received_public_key)
        print("Shared key: {}".format(self._user.shared_key))
        return 0

    def init_encryption_data(self, generated=True, mode=0):
        if generated:
            self.generate_key()
        if self.other is None:
            raise ConnectionError("You need to connect the other deivce!")
        else:
            print("Initializing encryption handshake ...", end='')
            key = str(self._user.public_key)
            key_array = bytearray()
            for i in range(0, len(key), 2):
                hex_number = key[i:i + 2]
                hex_number = '0x' + str(hex_number)
                key_array += struct.pack(">B", int(hex_number, base=16))

            print("Generated public key -> len=[{}]".format(len(key_array)))
            print("Sending the public key ...")

            m = hashlib.sha256()
            m.update(key.encode('utf-8'))
            result_hash = m.hexdigest()
            result_hash_array = bytearray()
            for i in range(0, len(result_hash), 2):
                hex_number = result_hash[i:i + 2]
                hex_number = '0x' + str(hex_number)
                result_hash_array += struct.pack(">B", int(hex_number,
                                                           base=16))
            fih = struct.pack(">B",
                              EncryptionPacket.FUNCTION_INITIALIZE_HANDSHAKE)
            hash_str_length = struct.pack(">B", len(result_hash_array))
            self.other.send(EncryptionPacket.PACKET_MAGIC_CODE + fih +
                            struct.pack(">B", mode) + hash_str_length +
                            result_hash_array + key_array)
            if mode == 0:
                print("Awaiting the received public key ...")
Exemplo n.º 24
0
    def client_setup_connection(self, dest):
        client_sk = socket.socket()
        client_sk.connect(('127.0.0.1', int(self.user_online[dest][1])))
        self.socket_list[dest] = []
        self.socket_list[dest].append(client_sk)

        port = client_sk.getsockname()[1]
        # print ("Port is:", port)
        server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server.bind(("127.0.0.1", port))

        #########################
        ### Set up         ######
        ### the connection ######
        #########################
        MessageSend = COMM_MESSAGE()
        MessageRec = COMM_MESSAGE()
        MessageSend.type = COMM_MESSAGE.TYPE.CLIENT_TO_CLIENT
        MessageSend.ticket = self.user_online[dest][4]
        MessageSend.ticket_tag = self.user_online[dest][5]
        kabtemp = self.user_online[dest][2].encode()
        ivtemp = self.user_online[dest][3].encode()
        y = os.urandom(8)
        x = y.hex()
        N1 = int(x, 16)
        plain_text = str(N1).encode() + str(int(time.time())).encode()
        MessageSend = self.encryption_in_client(MessageSend, kabtemp, ivtemp,
                                                plain_text)

        self.socket_list[dest][0].sendall(MessageSend.SerializeToString())

        data = self.socket_list[dest][0].recv(4096)
        MessageRec.ParseFromString(data)

        plain_text = self.decryption_with_timestamp_in_client(
            MessageRec, kabtemp, ivtemp)
        plain_text = plain_text.decode()
        N1_rec = int(plain_text.split(" ")[0])
        if N1 - 1 == N1_rec:
            MessageSend = COMM_MESSAGE()
            MessageSend.type = COMM_MESSAGE.TYPE.CLIENT_TO_CLIENT
            ### Set up the new Kab ###
            alice = DiffieHellman(group=5, key_length=200)
            alice.generate_public_key()
            MessageSend.message = str(alice.public_key)
            alice.generate_shared_secret(int(MessageRec.gb_mod_p))
            # set up the session key Kas
            self.socket_list[dest].append(
                str(alice.shared_secret)[:16].encode())
            N2_rec = int(plain_text.split(" ")[1])
            N2_send = N2_rec - 1
            plain_text = str(N2_send).encode() + str(int(time.time())).encode()
            MessageSend.iv = self.user_online[dest][3].encode()
            MessageSend = self.encryption_in_client(MessageSend, kabtemp,
                                                    ivtemp, plain_text)

            self.socket_list[dest][0].sendall(MessageSend.SerializeToString())

            data = self.socket_list[dest][0].recv(4096)
            MessageRec.ParseFromString(data)

            plain_text = self.decryption_with_timestamp_in_client(
                MessageRec, self.socket_list[dest][1], MessageRec.iv)
            plain_text = plain_text.decode()
            if plain_text.split(" ")[0] == "Confirm" and plain_text.split(
                    " ")[1] == dest:
                self.socket_list[dest].append(MessageRec.iv)
                plain_text = ("Confirm " + self.client_name).encode() + str(
                    int(time.time())).encode()
                MessageSend = COMM_MESSAGE()
                MessageSend.type = COMM_MESSAGE.TYPE.CLIENT_TO_CLIENT
                MessageSend.iv = self.socket_list[dest][2]
                self.socket_list[dest].append(server)
                client_thread_listen_from_existing_connection = threading.Thread(
                    target=self.listen_from_existed_connection,
                    args=(dest, ))  # 把sock 加入线程内
                client_thread_listen_from_existing_connection.start()  # 启动线程
                MessageSend = self.encryption_in_client(
                    MessageSend, self.socket_list[dest][1],
                    self.socket_list[dest][2], plain_text)
                self.socket_list[dest][0].sendall(
                    MessageSend.SerializeToString())
                # print ("I have succeed in setting up connection with", dest)
                # print("We use this socket to chatting:", self.socket_list[dest][0])
            else:
                print("Set up connection with", dest, "failed!")
                sys.exit(1)

        else:
            print("N1 verify failed!")
            sys.exit(1)
Exemplo n.º 25
0
import sys
import crypto
import time

from diffiehellman.diffiehellman import DiffieHellman

host = 'localhost'
port = 501

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 501))

data = 'CRYT'.encode('utf-8')

dh = DiffieHellman()
dh.generate_public_key()

# Generate user
ep = packet.EncryptionPacket(None, sock)
ep._user = dh

# Handshake
sock.send(data + struct.pack(">B", 0x00))

time.sleep(0.3)

# receiving initialize public key
data = sock.recv(2048)
ep.recv_public_data(data[6:])
time.sleep(0.3)
Exemplo n.º 26
0
class Node:

    def __init__(self, id):
        self.setup_keys()
        self.connect_to_signals()
        self.id = id
        self.send_ops = {
            OP.CREATED: self.get_created_packet,
            OP.EXTENDED: self.get_extended_packet
        }
        self.hop_table = {1: HopPair(prev=None, next=None)}

    def setup_keys(self):
        self.dhke = DiffieHellman(key_length=1024)
        self.dhke.generate_public_key()
        self.__dh_sharedkey = None
        self.dh_pub = str(self.dhke.public_key).encode('utf8')
        (self.pubkey, self.__privkey) = rsa.newkeys(1024)

    def connect_to_signals(self):
        dispatcher.connect(self.handle_extend, signal=OP.EXTEND, sender=dispatcher.Any)
        dispatcher.connect(self.handle_create,
                           signal=OP.CREATE, sender=dispatcher.Any)
        dispatcher.connect(self.handle_created, signal=OP.CREATED, sender=dispatcher.Any)

    def handle_extend(self, packet):
        if packet.dest != self.id:
            return None
        iniciopKp=time.time()
        print("{}: Handling EXTEND packet from {}".format(self.id, packet.src))
        if packet.decrypt_aes(self.__dh_sharedkey):
            print("{}: Decryption of EXTEND packet from {} SUCCESS".format(self.id, packet.src))
            forward_packet = packet.payload
            self.hop_table[1].next = packet.dest
            dispatcher.send(signal=forward_packet.op, sender=self, packet=forward_packet)
            return
        print("{}: Decryption of EXTEND packet from {} FAIL".format(self.id, packet.src))
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')

    def handle_create(self, packet):
        if packet.dest != self.id:
            return None
        iniciopKp=time.time()
        print("{}: Handling CREATE packet from {}".format(self.id, packet.src))
        if not packet.decrypt_rsa(self.__privkey):
            print("{}: Decryption of CREATE packet from {} FAIL".format(self.id, packet.src))
            return
        print("{}: Decryption of CREATE packet from {} SUCCESS".format(self.id, packet.src))
        other_key = int(packet.payload)
        self.dhke.generate_shared_secret(other_key)
        self.__dh_sharedkey = self.dhke.shared_key
        self.hop_table[1].prev = packet.src
        self.send_packet(self.hop_table[1].prev, OP.CREATED)
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')

    def send_packet(self, receiver, op, payload=None):
        iniciopKp=time.time()
        packet = self.send_ops[op](receiver, payload)
        dispatcher.send(signal=op, sender=self, packet=packet)
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')

    def get_created_packet(self, receiver, payload=None):
        iniciopKp=time.time()
        key_hash = hashlib.sha1(
            str(self.__dh_sharedkey).encode("utf-8")).hexdigest()
        msg = (self.dhke.public_key, key_hash)
        packet = Packet(src_id=self.id, op=OP.CREATED,
                        dest=receiver, payload=(msg, None))
        print("{}: Sending CREATED packet to {}".format(self.id, receiver))
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')
        return packet

    def get_extended_packet(self, receiver, payload):
        iniciopKp=time.time()
        packet = Packet(self.id, OP.EXTENDED, receiver, payload)
        print("{}: Sending EXTENDED packet to {}".format(self.id, receiver))
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')
        return packet

    def handle_created(self, packet):
        if packet.dest != self.id:
            return None
        iniciopKp=time.time()
        print("{}: Handling CREATE packet from {}".format(self.id, packet.src))
        dh_pub_key, key_hash = packet.msg
        encrypted_dh_pair = aes_encrypt("{}|||{}".format(dh_pub_key, key_hash), self.__dh_sharedkey)
        self.send_packet(self.hop_table[1].prev, OP.EXTENDED, (encrypted_dh_pair, None))
        finpKp=time.time()
        print('########## Tiempo ##########:',(finpKp-iniciopKp), 'segundos')

    def __str__(self):
        return self.id
Exemplo n.º 27
0
from diffiehellman.diffiehellman import DiffieHellman

CERT = os.getcwd()+'/certs/cert.pem'

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server = ssl.wrap_socket(server,cert_reqs=ssl.CERT_REQUIRED, ca_certs = CERT)
server.settimeout(5)



IP_address = '192.168.168.184'
Port = 8202
server.connect((IP_address, Port))
bob = DiffieHellman()
bob.generate_public_key()
x = {"bob":bob.public_key}
server.send(json.dumps(x).encode("utf-8"))
total_data=""
# ########################################## REC #############################################
while True:
    try:        
        message = ""
        message = server.recv(100)
        while message is not "":             
            total_data+=message.decode("utf-8")
            message = "" 
            message = server.recv(100)
        else:
            break
    except socket.error as ex:
Exemplo n.º 28
0
class ServerCipher:
    def __init__(self):
        # load server pub. key
        self.server_pub_key = serialization.load_pem_public_key(
            open(SERVER_PUB_KEY, "rb").read(), backend=default_backend())
        # load server priv. key
        self.server_priv_key = serialization.load_pem_private_key(
            open(SERVER_PRIV_KEY, "rb").read(),
            password=None,
            backend=default_backend())
        # Diffie Hellman
        self.server_dh = None

        # session key
        self.session_key = None

        # client public key
        self.client_public_key = None

        # number of requests received
        self.requests_received = 1

        # load cc libraries
        self.cc = CitizenCard()

        # mode CTR, CFB, OFB
        self.mode = None

    """
    ASYMMETRIC CIPHER
    """

    def asym_cipher(self, pub_key, raw_data):
        pickle_dumps = pickle.dumps(raw_data)
        return pub_key.encrypt(
            pickle_dumps,
            _aspaadding.OAEP(mgf=_aspaadding.MGF1(algorithm=hashes.SHA256()),
                             algorithm=hashes.SHA256(),
                             label=None))

    def asym_decipher(self, private_key, ciphered_data):
        data = private_key.decrypt(
            ciphered_data,
            _aspaadding.OAEP(mgf=_aspaadding.MGF1(algorithm=hashes.SHA256()),
                             algorithm=hashes.SHA256(),
                             label=None))
        return pickle.loads(data)

    def asym_sign(self, private_key, data):
        return private_key.sign(
            data,
            _aspaadding.PSS(mgf=_aspaadding.MGF1(hashes.SHA256()),
                            salt_length=_aspaadding.PSS.MAX_LENGTH),
            hashes.SHA256())

    def asym_validate_sign(self, data, sign_data, public_key):
        verifier = public_key.verifier(
            sign_data,
            _aspaadding.PSS(mgf=_aspaadding.MGF1(hashes.SHA256()),
                            salt_length=_aspaadding.PSS.MAX_LENGTH),
            hashes.SHA256())

        verifier.update(data)
        return verifier.verify()

    """
    SYMMETRIC KEY CIPHER
    """

    def sym_cipher(self, obj, ks, iv=os.urandom(16), mode=None):
        """

        :param iv: key to cipher the object
        :param obj: object to be ciphered
        :param ks: key to cipher the object
        """
        if mode is None:
            mode = modes.CTR

        cipher = Cipher(algorithms.AES(ks),
                        mode(iv),
                        backend=default_backend())

        # pickle makes the serialization of the object
        pickle_dumps = pickle.dumps(
            [obj, os.urandom(RANDOM_ENTROPY_GENERATOR_SIZE)])

        # encrypt obj dumped data
        encryptor = cipher.encryptor()
        ciphered_obj = encryptor.update(pickle_dumps) + encryptor.finalize()

        return iv, ciphered_obj

    def sym_decipher(self, obj, ks, iv, mode=None):
        """

        :param obj:
        :param ks:
        :param iv:
        :return:
        """
        if mode is None:
            mode = modes.CTR

        cipher = Cipher(algorithms.AES(ks),
                        mode(iv),
                        backend=default_backend())
        decryptor = cipher.decryptor()
        deciphered_data = decryptor.update(obj) + decryptor.finalize()
        data, random = pickle.loads(deciphered_data)
        return data

    """
    HYBRID A-SYMMETRIC KEY CIPHER
    """

    def hybrid_decipher(self, obj, private_key, ks=None):
        obj, random_pickle = pickle.loads(base64.b64decode(obj))

        # decipher using rsa private key
        if ks is None:
            ks = self.asym_decipher(private_key, base64.b64decode(obj["key"]))

        # decipher using rsa private key
        iv = self.asym_decipher(private_key, base64.b64decode(obj["iv"]))

        # decipher using symmetric AES CTR
        return self.sym_decipher(base64.b64decode(obj["obj"]), ks, iv)

    def hybrid_cipher(self,
                      obj,
                      public_key,
                      ks=os.urandom(32),
                      cipher_key=True):
        # cipher using symmetric cipher AES CTR
        # returns the ciphered obj with the IV
        iv, ciphered_obj = self.sym_cipher(obj, ks)

        # iv ciphered with the public key
        iv_encrypted = self.asym_cipher(public_key, iv)

        # key ciphered with the public_key
        if cipher_key:
            # send ks to the server
            key_encrypted = self.asym_cipher(public_key, ks)

            pickle_dumps = pickle.dumps(
                [{
                    "obj": base64.b64encode(ciphered_obj).decode(),
                    "iv": base64.b64encode(iv_encrypted).decode(),
                    "key": base64.b64encode(key_encrypted).decode()
                },
                 os.urandom(RANDOM_ENTROPY_GENERATOR_SIZE)])
            return base64.b64encode(pickle_dumps)
        else:
            pickle_dumps = pickle.dumps(
                [{
                    "obj": base64.b64encode(ciphered_obj).decode(),
                    "iv": base64.b64encode(iv_encrypted).decode()
                },
                 os.urandom(RANDOM_ENTROPY_GENERATOR_SIZE)])
            return base64.b64encode(pickle_dumps)

    """
    KEY DERIVATION FUNCTION GIVEN THE MASTER KEY
    """

    def key_derivation(self,
                       masterkey,
                       salt=os.urandom(32),
                       iterations=100000):
        kdf = PBKDF2HMAC(algorithm=hashes.SHA512(),
                         length=32,
                         salt=salt,
                         iterations=iterations,
                         backend=default_backend())

        return kdf.derive(masterkey), salt

    """
    HMAC - create
    """

    def hmac_update_finalize(self, key, data):
        if not isinstance(key, bytes):
            key = key.encode()

        if not isinstance(data, bytes):
            data = pickle.dumps(data)

        h = hmac.HMAC(key, self.hmac_hash(), backend=default_backend())
        h.update(data)
        return h.finalize()

    """
    HMAC - verify
    """

    def hmac_verify(self, key, hmac_data, data):
        if not isinstance(key, bytes):
            key = key.encode()

        if not isinstance(data, bytes):
            data = pickle.dumps(data)

        h = hmac.HMAC(key, self.hmac_hash(), backend=default_backend())
        h.update(data)
        return h.verify(hmac_data)

    """
    SECURE LAYER ENCAPSULATION
    """

    def secure_layer_encrypt(self, msg: bytes, sec_data: dict):
        # the nounce has been already generated by the client
        # the iterations number will be the number of requests received by the server for that client
        # the number that counts is the decrypt number
        key, salt = self.key_derivation(masterkey=self.session_key,
                                        salt=sec_data["salt"],
                                        iterations=sec_data["iterations"])

        # HMAC
        hmac_key = sha256(key).hexdigest()
        hmac_data = self.hmac_update_finalize(hmac_key, msg)

        pickle_dumps = pickle.dumps([msg, hmac_data])

        iv, ciphered_msg = self.sym_cipher(pickle_dumps,
                                           ks=key,
                                           mode=self.mode)

        sec_data = pickle.dumps({
            "nounce": sec_data["nounce"],
            "seq": sec_data["seq"],
            "iv": iv
        })

        # sec_data ciphered
        sec_data_ciphered = self.hybrid_cipher(sec_data,
                                               self.client_public_key)

        return_message = {
            "data": base64.b64encode(ciphered_msg).decode(),
            "sec_data": base64.b64encode(sec_data_ciphered).decode()
        }

        # dump the return message
        pickle_dumps = pickle.dumps(return_message)

        return base64.b64encode(pickle_dumps)

    def secure_layer_decrypt(self, msg: bytes):
        msg = pickle.loads(base64.b64decode(msg))

        data = msg["data"].encode()
        sec_data = base64.b64decode(msg["sec_data"])

        iterations = self.requests_received
        self.requests_received += 1

        # decipher the sec_data
        sec_data = pickle.loads(
            self.hybrid_decipher(sec_data, self.server_priv_key))

        salt = sec_data["salt"]
        nounce = sec_data["nounce"]
        iv = sec_data["iv"]

        key, salt = self.key_derivation(self.session_key,
                                        iterations=iterations,
                                        salt=salt)

        raw_msg = pickle.loads(
            self.sym_decipher(base64.b64decode(data), key, iv, self.mode))

        # verify hmac
        hmac_key = sha256(key).hexdigest()
        self.hmac_verify(hmac_key, raw_msg[1], raw_msg[0])

        data = {
            "nounce": nounce,
            "salt": salt,
            "iterations": iterations,
            "seq": sec_data["seq"] + 1
        }

        return raw_msg[0], data

    """
    CLIENT SERVER SESSION KEY NEGOTIATION
    """

    def negotiate_session_key(self, phase, val=None):
        """
        First the Application loads the server public key that is distributed into the client application.
        It's ok to publicly distribute the Public Key but it must be verified if the public key
        of the server is still the same. If not, it must be updated. Another way is to request the public key
        of the server and ask for the user fingerprint verification. {verification missing}

        After that, the client app generate DH values (private and public) to exchange with the server in order to
        get the shared secret session key.

        Phase 1: [CLIENT]: send generated DH public key to the server (signed) and the app client rsa public key (signed too).
        The sent values will be ciphered with a random key and signed.

        Phase 2: [SERVER]: the server generates the private and public DH pair. Then using the server private key, the
        server decipher the DH public received encrypted value. Using again the server private key, the server deciphers
        the client public key and loads it into memory.
        Then, using the client public key, validates the signature made for the DH public value and public key received.
        Using the received client public key, the server will make a hybrid cipher (AES and RSA) of the DH server
        generated values. After the cipher, the server will sign with the server private key the data ciphered.

        Phase 3: [CLIENT]: using the stored server public key the client will validate the signature received. After
        that using the client private key, the client will decipher the DH public value received from the server. Then
        using the DH public value, the client will generate the DH shared secret and using PBKDF2HMAC will use a key
        derivation function. The master key will be the secret DH shared value and will have 100 000 iterations. The
        salt is random and so, it will be ciphered and sent to the server.
        The session key has been generated.

        Phase 4: [SERVER]: Using the client public key it will be verified the signature of the received value. Using
        the server private key and a hybrid cipher the PBKDF2 salt will be deciphered. Using the key derivation
        function the session key will be retrieved in the server.

        Then, there is a secure channel between the server and the client.


        :param phase: negotiation phase
        :param val: value sent by the client
        :return: value to send to the client
        """
        if phase == 2:
            # server generate DH private and public key, 1024 para cima ou curva elipticas
            self.server_dh = DiffieHellman(key_length=256)
            self.server_dh.generate_public_key()

            # get mode
            if val["mode"] == "CTR":
                self.mode = modes.CTR
            elif val["mode"] == "CFB":
                self.mode = modes.CFB
            elif val["mode"] == "OFB":
                self.mode = modes.OFB
            else:
                print("Wrong input!")
                exit(1)

            if val["hmac_hash"] == "sha256":
                self.hmac_hash = hashes.SHA256
            elif val["hmac_hash"] == "sha512":
                self.hmac_hash = hashes.SHA512

            # decipher the received DH value
            client_dh_pub = self.hybrid_decipher(val["data"],
                                                 self.server_priv_key)

            # decipher client public key PEM format
            client_public_key_pem = self.hybrid_decipher(
                val["public_key"], self.server_priv_key)

            # load the client public key
            self.client_public_key = serialization.load_pem_public_key(
                client_public_key_pem, backend=default_backend())

            # validate signed data [data = dh value]
            self.asym_validate_sign(
                val["data"].encode(),
                base64.b64decode(val["data_signature"].encode()),
                self.client_public_key)

            # validate signature of client public key
            self.asym_validate_sign(
                val["public_key"].encode(),
                base64.b64decode(val["public_key_signature"].encode()),
                self.client_public_key)

            # cipher the server DH public key with the client public key
            server_dh_ciphered = self.hybrid_cipher(self.server_dh.public_key,
                                                    self.client_public_key)

            # generate the DH shared secret (client session key)
            self.server_dh.generate_shared_secret(client_dh_pub)

            return {
                "data":
                server_dh_ciphered.decode(),
                "data_signature":
                base64.b64encode(
                    self.asym_sign(self.server_priv_key,
                                   server_dh_ciphered)).decode(),
                "phase":
                3
            }
        elif phase == 4:
            # validate signature of the received salt
            self.asym_validate_sign(
                val["data"].encode(),
                base64.b64decode(val["data_signature"].encode()),
                self.client_public_key)

            # decipher the salt for PBKDF2
            pbkdf2_salt = self.hybrid_decipher(val["data"],
                                               self.server_priv_key)

            # save the session key
            self.session_key, salt = self.key_derivation(
                str(self.server_dh.shared_secret).encode(), pbkdf2_salt)