Browse Source

Handhsake part 1 done and AES GCM part1 Done

Shayan 4 years ago
parent
commit
f90fef5c5b

+ 12 - 2
.gitignore

@@ -14,7 +14,6 @@ dist/
 downloads/
 downloads/
 eggs/
 eggs/
 .eggs/
 .eggs/
-lib/
 lib64/
 lib64/
 parts/
 parts/
 sdist/
 sdist/
@@ -137,4 +136,15 @@ dmypy.json
 # Cython debug symbols
 # Cython debug symbols
 cython_debug/
 cython_debug/
 
 
-MP-SPDZ/
+MP-SPDZ/
+MP-SPDZ
+Programs/
+local/
+logs/
+Player-Data/
+Programs
+.logs
+Player-Data
+local
+
+

+ 41 - 23
command.py

@@ -3,28 +3,28 @@ import os
 
 
 
 
 def install():
 def install():
-    # print(("git submodule init"))
-    # print(os.system("git submodule init"))
-    # print(("git submodule update"))
-    # print(os.system("git submodule update"))
-    # print(("mkdir ./MP-SPDZ/Player-Data"))
-    # print(os.system("mkdir ./MP-SPDZ/Player-Data"))
-    # print(("apt-get install automake build-essential git libboost-dev libboost-thread-dev libsodium-dev libssl-dev libtool m4 python texinfo yasm"))
-    # print(os.system("apt-get install automake build-essential git libboost-dev libboost-thread-dev libsodium-dev libssl-dev libtool m4 python texinfo yasm"))
-    # print(("./MP-SPDZ/Scripts/tldr.sh"))
-    # print(os.system("./MP-SPDZ/Scripts/tldr.sh"))
-    # print(("cd MP-SPDZ && ls && make -j8 tldr"))
-    # print(os.system("cd MP-SPDZ && ls && make -j8 tldr"))
-    # print(("create Link from Player"))
-    # print(os.system("ln -s MP-SPDZ/Player-Data/ ."))
-    # print(("create Link from local"))
-    # print(os.system("ln -s MP-SPDZ/local/ ."))
-    # print(("create Link from Programs"))
-    # print(os.system("ln -s MP-SPDZ/Programs/ ."))
-    # print(("./MP-SPDZ/compile.py tutorial"))
-    # print(os.system("./MP-SPDZ/compile.py tutorial"))
-    # print(("cd MP-SPDZ && ls && make -j8 mascot-party"))
-    # print(os.system("cd MP-SPDZ && ls && make -j8 mascot"))
+    print(("git submodule init"))
+    print(os.system("git submodule init"))
+    print(("git submodule update"))
+    print(os.system("git submodule update"))
+    print(("mkdir ./MP-SPDZ/Player-Data"))
+    print(os.system("mkdir ./MP-SPDZ/Player-Data"))
+    print(("apt-get install automake build-essential git libboost-dev libboost-thread-dev libsodium-dev libssl-dev libtool m4 python texinfo yasm"))
+    print(os.system("apt-get install automake build-essential git libboost-dev libboost-thread-dev libsodium-dev libssl-dev libtool m4 python texinfo yasm"))
+    print(("./MP-SPDZ/Scripts/tldr.sh"))
+    print(os.system("./MP-SPDZ/Scripts/tldr.sh"))
+    print(("cd MP-SPDZ && ls && make -j8 tldr"))
+    print(os.system("cd MP-SPDZ && ls && make -j8 tldr"))
+    print(("create Link from Player"))
+    print(os.system("ln -s MP-SPDZ/Player-Data/ ."))
+    print(("create Link from local"))
+    print(os.system("ln -s MP-SPDZ/local/ ."))
+    print(("create Link from Programs"))
+    print(os.system("ln -s MP-SPDZ/Programs/ ."))
+    print(("./MP-SPDZ/compile.py tutorial"))
+    print(os.system("./MP-SPDZ/compile.py tutorial"))
+    print(("cd MP-SPDZ && ls && make -j8 mascot-party"))
+    print(os.system("cd MP-SPDZ && ls && make -j8 mascot"))
     print(("echo 1 2 3 4 > ./Player-Data/Input-P0-0"))
     print(("echo 1 2 3 4 > ./Player-Data/Input-P0-0"))
     print(os.system("echo 1 2 3 4 > ./Player-Data/Input-P0-0"))
     print(os.system("echo 1 2 3 4 > ./Player-Data/Input-P0-0"))
     print(("echo 1 2 3 4 > ./Player-Data/Input-P1-0"))
     print(("echo 1 2 3 4 > ./Player-Data/Input-P1-0"))
@@ -32,9 +32,27 @@ def install():
     print(("./MP-SPDZ/Scripts/mascot.sh tutorial"))
     print(("./MP-SPDZ/Scripts/mascot.sh tutorial"))
     print(os.system("./MP-SPDZ/Scripts/mascot.sh tutorial"))
     print(os.system("./MP-SPDZ/Scripts/mascot.sh tutorial"))
 
 
+    
+    print(("\n"))
+    os.system("rm -rf tls/Crypto")
+    os.system("cd tls/pycryptodome && python setup.py install")
+    a = os.popen('cd ./tls/pycryptodome/build && ls').read()
+    b = a.split("\n")
+    if b[1].startswith("lib"):
+        os.system("mv tls/pycryptodome/build/"+b[1]+"/Crypto tls/")
+
 
 
 def comp(a):
 def comp(a):
     print(("cp to Programs"))
     print(("cp to Programs"))
     print(os.system("cp ./mpc/"+a+".mpc ./Programs/Source/"))
     print(os.system("cp ./mpc/"+a+".mpc ./Programs/Source/"))
     print(("compile"))
     print(("compile"))
-    print(os.system("./MP-SPDZ/compile.py "+a))
+    print(os.system("./MP-SPDZ/compile.py "+a))
+
+def compCrypto(a):
+
+    os.system("rm -rf tls/Crypto")
+    os.system("cd tls/pycryptodome && python setup.py install")
+    a = os.popen('cd ./tls/pycryptodome/build && ls').read()
+    b = a.split("\n")
+    if b[1].startswith("lib"):
+        os.system("mv tls/pycryptodome/build/"+b[1]+"/Crypto tls/")

+ 7 - 0
config.py

@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+
+LenFunc = 5
+
+numberOfOracles = 3
+

+ 56 - 0
connection/broadcast.py

@@ -0,0 +1,56 @@
+
+import socket
+import threading
+        
+import config as cfg
+
+LenFunc = cfg.LenFunc
+class Broadcast():
+    def __init__(self,  parser, socket,child):
+        """ ,broadcast """ # TODO Broadcast
+        self.socket = socket
+        self.parser = parser
+        self.child = child
+        t1 = threading.Thread(target=self.listen)
+        t1.start()
+        print("Broadcast created")
+
+
+    def listen(self):
+        while True:
+            data, addr = self.socket.recvfrom(1024)
+            d = self.parser.toJSON(data.decode("utf-8")[LenFunc:])
+            print("\033[92m \n \treceive",d," \n\tfrom",addr,"\n\033[0m")
+            self.parser.parser(d,addr,self.child)
+
+    def send(self, message, addr):
+        self.socket.sendto(bytes(message,'utf-8'), addr )
+        print("\033[95m \n \tsended to ",addr,"\n\tdata: ",message,"\n\033[0m")
+
+
+
+
+class BroadcastServer(Broadcast):
+
+    def __init__(self,  broadcastPort, parser,id): 
+
+        """ ,broadcast """ # TODO Broadcast
+        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self.socket.bind(('', broadcastPort)) # TODO Broadcast
+        self.id = id
+        super().__init__(parser,self.socket,self) 
+
+
+        
+class BroadcastClient(Broadcast):
+
+    def __init__(self,broadcast,  broadcastPort, parser,id): 
+        self.addr = (broadcast,broadcastPort)
+        self.onlineOracles=[]
+        self.id = id
+        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+        super().__init__(parser,self.socket,self) 
+
+

+ 0 - 0
connection/broadcastClient.py


+ 0 - 0
connection/broadcastServer.py


+ 31 - 0
connection/parser.py

@@ -0,0 +1,31 @@
+import json
+import config as cfg
+LenFunc = cfg.LenFunc
+
+
+
+class Parser():
+    def __init__(self):
+        print("parser created")
+        
+    def toJSON(self, data):
+        return json.loads(data)
+
+    def toSTRING(self, data):
+        return json.dumps(data)
+
+    def toSEND(self, data):
+        j = json.dumps(data)
+        l = LenFunc - len(str(len(j)))
+        return "00000"[0:l]+str(len(j))+j
+
+    def add(self,data,k,v):
+        try:
+            data[k] = v
+            return data
+        except:
+            print("\33[41m\33[41mAn exception occurred  add\33[0m" )
+
+    def parser(self,data,addr,id):
+        data = self.toJSON(data)
+        print("Simple parser ->",data)

+ 157 - 0
connection/socket.py

@@ -0,0 +1,157 @@
+import socket
+import threading
+import config as cfg
+
+LenFunc = cfg.LenFunc
+
+class SocketHTTP(threading.Thread):
+
+    def __init__(self, HOST,PORT, parent):
+        try: 
+            self.parent = parent
+            super(SocketHTTP,self).__init__(None,None,None,None)
+            self.port = PORT
+            self.Host = HOST
+            self.history = []
+            self.socket = socket.socket()
+            self.socket.connect((HOST, PORT))
+            t = threading.Thread(target=self.receive)
+            t.start()
+            print("socket is created and Listener is created\n",(HOST, PORT))
+        except:
+            print("\33[41m\33[41mAn exception occurred  SocketHTTP\33[0m" )
+
+
+    def send(self,M):
+        try: 
+            self.socket.sendall(M)
+            self.history.append(("send",M))
+            print("\033[91m\n\t Send -> ",M,"\n\033[0m")
+        except:
+            print("\33[41m\33[41mAn exception occurred  SocketHTTP send\33[0m" )
+
+    def receive(self):
+        try: 
+            while True: 
+                data = self.socket.recv(65565)
+                # print("data",data)
+                if bytes.hex(data) == "":
+                    continue
+                self.parent.recv(bytes.hex(data))
+        except NameError:
+            print("\33[41m\33[41mAn exception occurred  SocketHTTP receiv e    NameError\33[0m",NameError )
+
+class SocketClient(threading.Thread):
+
+    def __init__(self, HOST,PORT, parser,id):
+        try: 
+            self.parser = parser
+            super(SocketClient,self).__init__(None,None,None,None)
+            self.port = PORT
+            self.Host = HOST
+            self.history = []
+            self.id = id
+            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            self.socket.connect((HOST, PORT))
+            t = threading.Thread(target=self.receive)
+            t.start()
+            print("socket is created and Listener is created\n")
+        except:
+            print("\33[41m\33[41mAn exception occurred  SocketClient\33[0m" )
+
+
+    def send(self,M):
+        try: 
+            Message=bytes(M,'utf-8')
+            self.socket.sendall(Message)
+            self.history.append(("send",Message))
+            print("\033[91m\n\t Send -> ",M,"\n\033[0m")
+        except:
+            print("\33[41m\33[41mAn exception occurred  socket Client send\33[0m" )
+
+    def receive(self):
+        try: 
+            while True: 
+                len = self.socket.recv(cfg.LenFunc)
+                if not len:
+                    break
+                data = self.socket.recv(int(len.decode("utf-8")))
+                data = self.parser.toJSON(data.decode("utf-8"))
+                print("\033[94m\n\t receive -> ",data,"\n\033[0m")
+                self.parser.parser(data,None,self)
+        except:
+            print("\33[41m\33[41mAn exception occurred  socket Client receive\33[0m" )
+
+
+
+
+class SocketServer():
+
+    def __init__(self, socketPort, parser,id):
+        try:  
+            self.parser = parser
+            self.history = []
+            self.connected = []
+            self.socketPort = socketPort 
+            self.id = id
+            t = threading.Thread(target=self.connection)
+            t.start()
+            print("socket is created and Listener is created",socketPort)
+        except:
+            print("\33[41m\33[41mAn exception occurred  SocketServer\33[0m" )
+
+    def connection(self):
+        try: 
+            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+                s.bind(("localhost", self.socketPort))
+                s.listen()
+                self.socket = s
+                while True:
+                    conn, addr = self.socket.accept()
+                    print("user connected to ",conn, "-> ",addr)
+                    u = Connection(conn, addr,self.socketPort+1,self.parser)# TODO socketprot dynamic
+                    self.connected.append(u)
+                    print(self.connected)
+        except Exception as exception:
+            print("\33[41m\33[41mAn exception occurred  SocketServer connection ",exception,"\33[0m" )
+
+class Connection():
+    def __init__(self,connection,address,oracleSocketPort, parser): 
+        try:
+            self.parser = parser
+            self.socket = connection
+            self.addr = address
+            self.history = []
+            self.type = None
+            # self.id = os.urandom(32)
+            self.oracleSocketPort = oracleSocketPort
+
+
+            t = threading.Thread(target=self.receive)
+            t.start()
+            # self.send("Connection")
+        except:
+            print("\33[41m\33[41mAn exception occurred  Connection connection\33[0m" )
+        
+    def send(self,M):
+        try:
+            Message=bytes(M,'utf-8')
+            self.socket.sendall(Message)
+            self.history.append(("send",Message))
+            print("\033[91m\n\t Send -> ",M,"\n\033[0m")
+        except:
+            print("\33[41m\33[41mAn exception occurred  Connection sebd\33[0m" )
+
+    def receive(self):
+        try:
+            while True: 
+                len = self.socket.recv(cfg.LenFunc)
+                if not len:
+                    break
+                print(int(len.decode("utf-8")))
+                data = self.socket.recv(int(len.decode("utf-8")))
+                data = self.parser.toJSON(data.decode("utf-8"))
+                print("\033[94m\n\t receive -> ",data,"\n\033[0m")
+                self.parser.parser(data,None,self)
+        except  :
+            print("\33[41m\33[41mAn exception occurred  Connection receive\33[0m" )

+ 0 - 49
connection/socketClient.py

@@ -1,49 +0,0 @@
-import socket
-import threading
-import config as cfg
-import json
-LenFunc = cfg.LenFunc
-
-class Socket(threading.Thread):
-
-    def __init__(self, HOST,PORT,data):
-
-        super(Socket,self).__init__(None,None,None,None)
-        self.port = PORT
-        self.Host = HOST
-        self.history = []
-        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.socket.connect((HOST, PORT))
-        t = threading.Thread(target=self.receive)
-        t.start()
-        print("socket is created and Listener is created\n")
-
-        self.toSEND(data)
-
-
-    def send(self,Message):
-        Message=bytes(Message,'utf-8')
-        self.socket.sendall(Message)
-        # self.history.append(("send",Message))
-        print("Send",Message)
-
-    def receive(self):
-        while True:
-            len = self.socket.recv(LenFunc)
-            if not len:
-                break
-            data = self.socket.recv(int(len))
-            print("data",data)
-            # self.history.append(("receive",data))
-
-
-    def toJSON(self, data):
-        return json.loads(data)
-    def toSTRING(self, data):
-        return json.dumps(data)
-    def toSEND(self, x):
-        j = json.dumps(x)
-        l = LenFunc - len(str(len(j)))
-        self.send("0000"[0:l]+str(len(j))+j)
-    def parser(self,data):
-        print("parser not yet implemented. ",data) 

+ 0 - 0
connection/socketServer.py


+ 5 - 0
cp

@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VuBCIEICAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/
+-----END PRIVATE KEY-----
+
+30 2e 02 01 00 30 05 06 03 2b 65 6e 04 22 04 20 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f

+ 219 - 0
gcm.py

@@ -0,0 +1,219 @@
+#!/usr/bin/env python
+
+"""
+    Copyright (C) 2013 Bo Zhu http://about.bozhu.me
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+"""
+
+from tls.Crypto.Cipher import AES
+from tls.Crypto.Util import Counter
+from tls.Crypto.Util.number import long_to_bytes, bytes_to_long
+
+
+# GF(2^128) defined by 1 + a + a^2 + a^7 + a^128
+# Please note the MSB is x0 and LSB is x127
+def gf_2_128_mul(x, y):
+    assert x < (1 << 128)
+    assert y < (1 << 128)
+    res = 0
+    for i in range(127, -1, -1):
+        res ^= x * ((y >> i) & 1)  # branchless
+        x = (x >> 1) ^ ((x & 1) * 0xE1000000000000000000000000000000)
+    assert res < 1 << 128
+    return res
+
+
+class InvalidInputException(Exception):
+    def __init__(self, msg):
+        self.msg = msg
+
+    def __str__(self):
+        return str(self.msg)
+
+
+class InvalidTagException(Exception):
+    def __str__(self):
+        return 'The authenticaiton tag is invalid.'
+
+
+# Galois/Counter Mode with AES-128 and 96-bit IV
+class AES_GCM:
+    def __init__(self, master_key):
+        self.change_key(master_key)
+
+    def change_key(self, master_key):
+        if master_key >= (1 << 128):
+            raise InvalidInputException('Master key should be 128-bit')
+
+        self.__master_key = long_to_bytes(master_key, 16)
+        self.__aes_ecb = AES.new(self.__master_key, AES.MODE_ECB)
+        self.__auth_key = bytes_to_long(self.__aes_ecb.encrypt(b'\x00' * 16))
+
+        # precompute the table for multiplication in finite field
+        table = []  # for 8-bit
+        for i in range(16):
+            row = []
+            for j in range(256):
+                row.append(gf_2_128_mul(self.__auth_key, j << (8 * i)))
+            table.append(tuple(row))
+        self.__pre_table = tuple(table)
+
+        self.prev_init_value = None  # reset
+
+    def __times_auth_key(self, val):
+        res = 0
+        for i in range(16):
+            res ^= self.__pre_table[i][val & 0xFF]
+            val >>= 8
+        return res
+
+    def __ghash(self, aad, txt):
+        len_aad = len(aad)
+        len_txt = len(txt)
+
+        # padding
+        if 0 == len_aad % 16:
+            data = aad
+        else:
+            data = aad + b'\x00' * (16 - len_aad % 16)
+        if 0 == len_txt % 16:
+            data += txt
+        else:
+            data += txt + b'\x00' * (16 - len_txt % 16)
+
+        tag = 0
+        assert len(data) % 16 == 0
+        for i in range(len(data) // 16):
+            tag ^= bytes_to_long(data[i * 16: (i + 1) * 16])
+            tag = self.__times_auth_key(tag)
+            # print 'X\t', hex(tag)
+        tag ^= ((8 * len_aad) << 64) | (8 * len_txt)
+        tag = self.__times_auth_key(tag)
+
+        return tag
+
+    def encrypt(self, init_value, plaintext, auth_data=b''):
+        if init_value >= (1 << 96):
+            raise InvalidInputException('IV should be 96-bit')
+        # a naive checking for IV reuse
+        if init_value == self.prev_init_value:
+            raise InvalidInputException('IV must not be reused!')
+        self.prev_init_value = init_value
+
+        len_plaintext = len(plaintext)
+        # len_auth_data = len(auth_data)
+
+        if len_plaintext > 0:
+            counter = Counter.new(
+                nbits=32,
+                prefix=long_to_bytes(init_value, 12),
+                initial_value=2,  # notice this
+                allow_wraparound=False)
+                
+            aes_ctr = AES.new(self.__master_key, AES.MODE_CTR, counter=counter)
+            if 0 != len_plaintext % 16:
+                padded_plaintext = plaintext + \
+                    b'\x00' * (16 - len_plaintext % 16)
+            else:
+                padded_plaintext = plaintext
+            ciphertext = aes_ctr.encrypt(padded_plaintext)[:len_plaintext]
+
+        else:
+            ciphertext = b''
+
+        auth_tag = self.__ghash(auth_data, ciphertext)
+        # print 'GHASH\t', hex(auth_tag)
+        auth_tag ^= bytes_to_long(self.__aes_ecb.encrypt(
+                                  long_to_bytes((init_value << 32) | 1, 16)))
+
+        # assert len(ciphertext) == len(plaintext)
+        assert auth_tag < (1 << 128)
+        return ciphertext, auth_tag
+
+    def decrypt(self, init_value, ciphertext, auth_tag, auth_data=b''):
+        if init_value >= (1 << 96):
+            raise InvalidInputException('IV should be 96-bit')
+        if auth_tag >= (1 << 128):
+            raise InvalidInputException('Tag should be 128-bit')
+
+        if auth_tag != self.__ghash(auth_data, ciphertext) ^ \
+                bytes_to_long(self.__aes_ecb.encrypt(
+                long_to_bytes((init_value << 32) | 1, 16))):
+            raise InvalidTagException
+
+        len_ciphertext = len(ciphertext)
+        if len_ciphertext > 0:
+            counter = Counter.new(
+                nbits=32,
+                prefix=long_to_bytes(init_value, 12),
+                initial_value=2,
+                allow_wraparound=True)
+            aes_ctr = AES.new(self.__master_key, AES.MODE_CTR, counter=counter)
+
+            if 0 != len_ciphertext % 16:
+                padded_ciphertext = ciphertext + \
+                    b'\x00' * (16 - len_ciphertext % 16)
+            else:
+                padded_ciphertext = ciphertext
+            plaintext = aes_ctr.decrypt(padded_ciphertext)[:len_ciphertext]
+
+        else:
+            plaintext = b''
+
+        return plaintext
+
+
+if __name__ == '__main__':
+    master_key = 0xfeffe9928665731c6d6a8f9467308308
+    plaintext = b'\xd9\x31\x32\x25\xf8\x84\x06\xe5' + \
+                b'\xa5\x59\x09\xc5\xaf\xf5\x26\x9a' + \
+                b'\x86\xa7\xa9\x53\x15\x34\xf7\xda' + \
+                b'\x2e\x4c\x30\x3d\x8a\x31\x8a\x72' + \
+                b'\x1c\x3c\x0c\x95\x95\x68\x09\x53' + \
+                b'\x2f\xcf\x0e\x24\x49\xa6\xb5\x25' + \
+                b'\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57' + \
+                b'\xba\x63\x7b\x39'
+    auth_data = b'\xfe\xed\xfa\xce\xde\xad\xbe\xef' + \
+                b'\xfe\xed\xfa\xce\xde\xad\xbe\xef' + \
+                b'\xab\xad\xda\xd2'
+    init_value = 0xcafebabefacedbaddecaf888
+    ciphertext = b'\x42\x83\x1e\xc2\x21\x77\x74\x24' + \
+                 b'\x4b\x72\x21\xb7\x84\xd0\xd4\x9c' + \
+                 b'\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0' + \
+                 b'\x35\xc1\x7e\x23\x29\xac\xa1\x2e' + \
+                 b'\x21\xd5\x14\xb2\x54\x66\x93\x1c' + \
+                 b'\x7d\x8f\x6a\x5a\xac\x84\xaa\x05' + \
+                 b'\x1b\xa3\x0b\x39\x6a\x0a\xac\x97' + \
+                 b'\x3d\x58\xe0\x91'
+    auth_tag = 0x5bc94fbc3221a5db94fae95ae7121a47
+
+    # print('plaintext:', hex(bytes_to_long(plaintext)))
+
+    my_gcm = AES_GCM(master_key)
+    encrypted, new_tag = my_gcm.encrypt(init_value, plaintext, auth_data)
+    # print('encrypted:', hex(bytes_to_long(encrypted)))
+    # print('auth tag: ', hex(new_tag))
+
+    try:
+        decrypted = my_gcm.decrypt(init_value, encrypted,
+                new_tag + 1, auth_data)
+    except InvalidTagException:
+        decrypted = my_gcm.decrypt(init_value, encrypted, new_tag, auth_data)
+        print('decrypted:', hex(bytes_to_long(decrypted)))

+ 33 - 0
i.py

@@ -0,0 +1,33 @@
+import os
+
+os.system("cd tls/pycryptodome && python setup.py install")
+os.system("rm -rf tls/Crypto")
+os.system("mv tls/pycryptodome/build/lib.linux-x86_64-3.7/Crypto tls/")
+
+""" 
+
+155 178 44 231 217 243 114 193 238 43 40 114 43 37 242 6 101 13 136 124 57 54 83 58 27 141 78 30 163 157 43 92 61 233 24 39 193 14 154 79 82 64 100 126 229 34 31 32 170 201 230 204 192 7 74 192 135 59 155 168 93 144 139 208
+
+155 178 44 231 217 243 114 193 238 43 40 114 43 37 242 6 101 13 136 124 57 54 83 58 27 141 78 30 163 157 43 92 61 233 24 39 193 14 154 79 82 64 100 126 229 34 31 32 170 201 230 204 192 7 74 192 135 59 155 168 93 144 139 208
+decrypted: 0xd9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+
+
+
+
+
+
+
+
+
+
+
+155 178 44 231 217 243 114 193 238 43 40 114 43 37 242 6 101 13 136 124 57 54 83 58 27 141 78 30 163 157 43 92 61 233 24 39 193 14 154 79 82 64 100 126 229 34 31 32 170 201 230 204 192 7 74 192 135 59 155 168 93 144 139 208
+
+ Counter is -->         9bb22ce7d9f372c1ee2b28722b25f206650d887c3936533a1b8d4e1ea39d2b5c3de91827c10e9a4f5240647ee5221f20aac9e6ccc0074ac0873b9ba8 5d908bd0
+ plain is -->           d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 00000000
+ res should be -->      d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+
+155 178 44 231 217 243 114 193 238 43 40 114 43 37 242 6 101 13 136 124 57 54 83 58 27 141 78 30 163 157 43 92 61 233 24 39 193 14 154 79 82 64 100 126 229 34 31 32 170 201 230 204 192 7 74 192 135 59 155 168 93 144 139 208
+decrypted: 0x9bb22ce7d9f372c1ee2b28722b25f206650d887c3936533a1b8d4e1ea39d2b5c3de91827c10e9a4f5240647ee5221f20aac9e6ccc0074ac0873b9ba8
+
+ """

+ 19 - 5
main.py

@@ -1,15 +1,21 @@
 from optparse import OptionParser
 from optparse import OptionParser
-from src.oracle import oracle
-from src.user import user
+from oracle.oracle import Oracle
+from user.user import User
+from command import install,comp,compCrypto
+import os
 def main():
 def main():
+    os.system("clear")
     parser = OptionParser()
     parser = OptionParser()
 
 
+    parser.add_option("-i", "--installation", action="store_true", dest="installation", default=False, help="installation")
     parser.add_option("-o", "--oracle", action="store_true", dest="oracle", default=False, help="if true -> orcle will be run")
     parser.add_option("-o", "--oracle", action="store_true", dest="oracle", default=False, help="if true -> orcle will be run")
     parser.add_option("-u", "--user", action="store_true", dest="user", default=False, help="if true -> user will be run")
     parser.add_option("-u", "--user", action="store_true", dest="user", default=False, help="if true -> user will be run")
     parser.add_option("-s", "--server", dest="server", default="127.0.0.1", help="destination Server for feed data to Oracles")
     parser.add_option("-s", "--server", dest="server", default="127.0.0.1", help="destination Server for feed data to Oracles")
     parser.add_option("-d", "--data", dest="data", default="", help="Data to send to destination server for response")
     parser.add_option("-d", "--data", dest="data", default="", help="Data to send to destination server for response")
     parser.add_option("-b", "--broadcast", dest="broadcast", default="255.255.255.255", help="Broad cast IP")
     parser.add_option("-b", "--broadcast", dest="broadcast", default="255.255.255.255", help="Broad cast IP")
     parser.add_option("-p", "--broadcast-port", dest="broadcastPort", default=6666, help="Broad cast Port")
     parser.add_option("-p", "--broadcast-port", dest="broadcastPort", default=6666, help="Broad cast Port")
+    parser.add_option("-c", "--compile", dest="compile",  help="file compile")
+    parser.add_option("-t", "--tls", dest="tls",  help="Crypto compile")
     # parser.add_option("-h", "--help",action="store_true", dest="help", default=False)
     # parser.add_option("-h", "--help",action="store_true", dest="help", default=False)
 
 
 
 
@@ -18,17 +24,25 @@ def main():
 
 
 
 
 
 
-    if len(args) >= 1 or options.oracle + options.user != 1:
+    if len(args) >= 1 or (options.oracle + options.user != 1 and not options.installation and not options.compile):
         print("\n\n\tWhat do you want to run? Oracle or User? \n\n\tplease use -o OR -u. \n\n\tFor more Info you can use -h or --help or i can do it for you\n \n\t~~~ GOOD LUCK :) ~~~\n")
         print("\n\n\tWhat do you want to run? Oracle or User? \n\n\tplease use -o OR -u. \n\n\tFor more Info you can use -h or --help or i can do it for you\n \n\t~~~ GOOD LUCK :) ~~~\n")
         parser.print_help()
         parser.print_help()
         return
         return
 
 
 
 
+    if(options.compile):
+        comp(options.compile)
+    if(options.tls):
+        compCrypto(options.tls)
+
+    if(options.installation):
+        install()
+
     if(options.oracle):
     if(options.oracle):
-        oracle.run(broadcast=options.broadcast, broadcastPort=options.broadcastPort)
+        Oracle(broadcast=options.broadcast, broadcastPort=options.broadcastPort)
     
     
     if(options.user):
     if(options.user):
-        user.run(data=options.data, server=options.server, broadcast=options.broadcast, broadcastPort=options.broadcastPort)
+        User(data=options.data, server=options.server, broadcast=options.broadcast, broadcastPort=options.broadcastPort).run()
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
     main()
     main()

BIN
mul


+ 902 - 0
mul.c

@@ -0,0 +1,902 @@
+/* Copyright 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * curve25519-donna: Curve25519 elliptic curve, public key function
+ *
+ * http://code.google.com/p/curve25519-donna/
+ *
+ * Adam Langley <agl@imperialviolet.org>
+ *
+ * Derived from public domain C code by Daniel J. Bernstein <djb@cr.yp.to>
+ *
+ * More information about curve25519 can be found here
+ *   http://cr.yp.to/ecdh.html
+ *
+ * djb's sample implementation of curve25519 is written in a special assembly
+ * language called qhasm and uses the floating point registers.
+ *
+ * This is, almost, a clean room reimplementation from the curve25519 paper. It
+ * uses many of the tricks described therein. Only the crecip function is taken
+ * from the sample implementation.
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef _MSC_VER
+#define inline __inline
+#endif
+
+typedef uint8_t u8;
+typedef int32_t s32;
+typedef int64_t limb;
+
+/* Field element representation:
+ *
+ * Field elements are written as an array of signed, 64-bit limbs, least
+ * significant first. The value of the field element is:
+ *   x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ...
+ *
+ * i.e. the limbs are 26, 25, 26, 25, ... bits wide.
+ */
+
+/* Sum two numbers: output += in */
+static void fsum(limb *output, const limb *in)
+{
+    unsigned i;
+    for (i = 0; i < 10; i += 2)
+    {
+        output[0 + i] = (output[0 + i] + in[0 + i]);
+        output[1 + i] = (output[1 + i] + in[1 + i]);
+    }
+}
+
+/* Find the difference of two numbers: output = in - output
+ * (note the order of the arguments!)
+ */
+static void fdifference(limb *output, const limb *in)
+{
+    unsigned i;
+    for (i = 0; i < 10; ++i)
+    {
+        output[i] = (in[i] - output[i]);
+    }
+}
+
+/* Multiply a number by a scalar: output = in * scalar */
+static void fscalar_product(limb *output, const limb *in, const limb scalar)
+{
+    unsigned i;
+    for (i = 0; i < 10; ++i)
+    {
+        output[i] = in[i] * scalar;
+    }
+}
+
+/* Multiply two numbers: output = in2 * in
+ *
+ * output must be distinct to both inputs. The inputs are reduced coefficient
+ * form, the output is not.
+ */
+static void fproduct(limb *output, const limb *in2, const limb *in)
+{
+    output[0] = ((limb)((s32)in2[0])) * ((s32)in[0]);
+    output[1] = ((limb)((s32)in2[0])) * ((s32)in[1]) +
+                ((limb)((s32)in2[1])) * ((s32)in[0]);
+    output[2] = 2 * ((limb)((s32)in2[1])) * ((s32)in[1]) +
+                ((limb)((s32)in2[0])) * ((s32)in[2]) +
+                ((limb)((s32)in2[2])) * ((s32)in[0]);
+    output[3] = ((limb)((s32)in2[1])) * ((s32)in[2]) +
+                ((limb)((s32)in2[2])) * ((s32)in[1]) +
+                ((limb)((s32)in2[0])) * ((s32)in[3]) +
+                ((limb)((s32)in2[3])) * ((s32)in[0]);
+    output[4] = ((limb)((s32)in2[2])) * ((s32)in[2]) +
+                2 * (((limb)((s32)in2[1])) * ((s32)in[3]) +
+                     ((limb)((s32)in2[3])) * ((s32)in[1])) +
+                ((limb)((s32)in2[0])) * ((s32)in[4]) +
+                ((limb)((s32)in2[4])) * ((s32)in[0]);
+    output[5] = ((limb)((s32)in2[2])) * ((s32)in[3]) +
+                ((limb)((s32)in2[3])) * ((s32)in[2]) +
+                ((limb)((s32)in2[1])) * ((s32)in[4]) +
+                ((limb)((s32)in2[4])) * ((s32)in[1]) +
+                ((limb)((s32)in2[0])) * ((s32)in[5]) +
+                ((limb)((s32)in2[5])) * ((s32)in[0]);
+    output[6] = 2 * (((limb)((s32)in2[3])) * ((s32)in[3]) +
+                     ((limb)((s32)in2[1])) * ((s32)in[5]) +
+                     ((limb)((s32)in2[5])) * ((s32)in[1])) +
+                ((limb)((s32)in2[2])) * ((s32)in[4]) +
+                ((limb)((s32)in2[4])) * ((s32)in[2]) +
+                ((limb)((s32)in2[0])) * ((s32)in[6]) +
+                ((limb)((s32)in2[6])) * ((s32)in[0]);
+    output[7] = ((limb)((s32)in2[3])) * ((s32)in[4]) +
+                ((limb)((s32)in2[4])) * ((s32)in[3]) +
+                ((limb)((s32)in2[2])) * ((s32)in[5]) +
+                ((limb)((s32)in2[5])) * ((s32)in[2]) +
+                ((limb)((s32)in2[1])) * ((s32)in[6]) +
+                ((limb)((s32)in2[6])) * ((s32)in[1]) +
+                ((limb)((s32)in2[0])) * ((s32)in[7]) +
+                ((limb)((s32)in2[7])) * ((s32)in[0]);
+    output[8] = ((limb)((s32)in2[4])) * ((s32)in[4]) +
+                2 * (((limb)((s32)in2[3])) * ((s32)in[5]) +
+                     ((limb)((s32)in2[5])) * ((s32)in[3]) +
+                     ((limb)((s32)in2[1])) * ((s32)in[7]) +
+                     ((limb)((s32)in2[7])) * ((s32)in[1])) +
+                ((limb)((s32)in2[2])) * ((s32)in[6]) +
+                ((limb)((s32)in2[6])) * ((s32)in[2]) +
+                ((limb)((s32)in2[0])) * ((s32)in[8]) +
+                ((limb)((s32)in2[8])) * ((s32)in[0]);
+    output[9] = ((limb)((s32)in2[4])) * ((s32)in[5]) +
+                ((limb)((s32)in2[5])) * ((s32)in[4]) +
+                ((limb)((s32)in2[3])) * ((s32)in[6]) +
+                ((limb)((s32)in2[6])) * ((s32)in[3]) +
+                ((limb)((s32)in2[2])) * ((s32)in[7]) +
+                ((limb)((s32)in2[7])) * ((s32)in[2]) +
+                ((limb)((s32)in2[1])) * ((s32)in[8]) +
+                ((limb)((s32)in2[8])) * ((s32)in[1]) +
+                ((limb)((s32)in2[0])) * ((s32)in[9]) +
+                ((limb)((s32)in2[9])) * ((s32)in[0]);
+    output[10] = 2 * (((limb)((s32)in2[5])) * ((s32)in[5]) +
+                      ((limb)((s32)in2[3])) * ((s32)in[7]) +
+                      ((limb)((s32)in2[7])) * ((s32)in[3]) +
+                      ((limb)((s32)in2[1])) * ((s32)in[9]) +
+                      ((limb)((s32)in2[9])) * ((s32)in[1])) +
+                 ((limb)((s32)in2[4])) * ((s32)in[6]) +
+                 ((limb)((s32)in2[6])) * ((s32)in[4]) +
+                 ((limb)((s32)in2[2])) * ((s32)in[8]) +
+                 ((limb)((s32)in2[8])) * ((s32)in[2]);
+    output[11] = ((limb)((s32)in2[5])) * ((s32)in[6]) +
+                 ((limb)((s32)in2[6])) * ((s32)in[5]) +
+                 ((limb)((s32)in2[4])) * ((s32)in[7]) +
+                 ((limb)((s32)in2[7])) * ((s32)in[4]) +
+                 ((limb)((s32)in2[3])) * ((s32)in[8]) +
+                 ((limb)((s32)in2[8])) * ((s32)in[3]) +
+                 ((limb)((s32)in2[2])) * ((s32)in[9]) +
+                 ((limb)((s32)in2[9])) * ((s32)in[2]);
+    output[12] = ((limb)((s32)in2[6])) * ((s32)in[6]) +
+                 2 * (((limb)((s32)in2[5])) * ((s32)in[7]) +
+                      ((limb)((s32)in2[7])) * ((s32)in[5]) +
+                      ((limb)((s32)in2[3])) * ((s32)in[9]) +
+                      ((limb)((s32)in2[9])) * ((s32)in[3])) +
+                 ((limb)((s32)in2[4])) * ((s32)in[8]) +
+                 ((limb)((s32)in2[8])) * ((s32)in[4]);
+    output[13] = ((limb)((s32)in2[6])) * ((s32)in[7]) +
+                 ((limb)((s32)in2[7])) * ((s32)in[6]) +
+                 ((limb)((s32)in2[5])) * ((s32)in[8]) +
+                 ((limb)((s32)in2[8])) * ((s32)in[5]) +
+                 ((limb)((s32)in2[4])) * ((s32)in[9]) +
+                 ((limb)((s32)in2[9])) * ((s32)in[4]);
+    output[14] = 2 * (((limb)((s32)in2[7])) * ((s32)in[7]) +
+                      ((limb)((s32)in2[5])) * ((s32)in[9]) +
+                      ((limb)((s32)in2[9])) * ((s32)in[5])) +
+                 ((limb)((s32)in2[6])) * ((s32)in[8]) +
+                 ((limb)((s32)in2[8])) * ((s32)in[6]);
+    output[15] = ((limb)((s32)in2[7])) * ((s32)in[8]) +
+                 ((limb)((s32)in2[8])) * ((s32)in[7]) +
+                 ((limb)((s32)in2[6])) * ((s32)in[9]) +
+                 ((limb)((s32)in2[9])) * ((s32)in[6]);
+    output[16] = ((limb)((s32)in2[8])) * ((s32)in[8]) +
+                 2 * (((limb)((s32)in2[7])) * ((s32)in[9]) +
+                      ((limb)((s32)in2[9])) * ((s32)in[7]));
+    output[17] = ((limb)((s32)in2[8])) * ((s32)in[9]) +
+                 ((limb)((s32)in2[9])) * ((s32)in[8]);
+    output[18] = 2 * ((limb)((s32)in2[9])) * ((s32)in[9]);
+}
+
+/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
+static void freduce_degree(limb *output)
+{
+    /* Each of these shifts and adds ends up multiplying the value by 19. */
+    output[8] += output[18] << 4;
+    output[8] += output[18] << 1;
+    output[8] += output[18];
+    output[7] += output[17] << 4;
+    output[7] += output[17] << 1;
+    output[7] += output[17];
+    output[6] += output[16] << 4;
+    output[6] += output[16] << 1;
+    output[6] += output[16];
+    output[5] += output[15] << 4;
+    output[5] += output[15] << 1;
+    output[5] += output[15];
+    output[4] += output[14] << 4;
+    output[4] += output[14] << 1;
+    output[4] += output[14];
+    output[3] += output[13] << 4;
+    output[3] += output[13] << 1;
+    output[3] += output[13];
+    output[2] += output[12] << 4;
+    output[2] += output[12] << 1;
+    output[2] += output[12];
+    output[1] += output[11] << 4;
+    output[1] += output[11] << 1;
+    output[1] += output[11];
+    output[0] += output[10] << 4;
+    output[0] += output[10] << 1;
+    output[0] += output[10];
+}
+
+#if (-1 & 3) != 3
+#error "This code only works on a two's complement system"
+#endif
+
+/* return v / 2^26, using only shifts and adds. */
+static inline limb
+div_by_2_26(const limb v)
+{
+    /* High word of v; no shift needed*/
+    const uint32_t highword = (uint32_t)(((uint64_t)v) >> 32);
+    /* Set to all 1s if v was negative; else set to 0s. */
+    const int32_t sign = ((int32_t)highword) >> 31;
+    /* Set to 0x3ffffff if v was negative; else set to 0. */
+    const int32_t roundoff = ((uint32_t)sign) >> 6;
+    /* Should return v / (1<<26) */
+    return (v + roundoff) >> 26;
+}
+
+/* return v / (2^25), using only shifts and adds. */
+static inline limb
+div_by_2_25(const limb v)
+{
+    /* High word of v; no shift needed*/
+    const uint32_t highword = (uint32_t)(((uint64_t)v) >> 32);
+    /* Set to all 1s if v was negative; else set to 0s. */
+    const int32_t sign = ((int32_t)highword) >> 31;
+    /* Set to 0x1ffffff if v was negative; else set to 0. */
+    const int32_t roundoff = ((uint32_t)sign) >> 7;
+    /* Should return v / (1<<25) */
+    return (v + roundoff) >> 25;
+}
+
+static inline s32
+div_s32_by_2_25(const s32 v)
+{
+    const s32 roundoff = ((uint32_t)(v >> 31)) >> 7;
+    return (v + roundoff) >> 25;
+}
+
+/* Reduce all coefficients of the short form input so that |x| < 2^26.
+ *
+ * On entry: |output[i]| < 2^62
+ */
+static void freduce_coefficients(limb *output)
+{
+    unsigned i;
+
+    output[10] = 0;
+
+    for (i = 0; i < 10; i += 2)
+    {
+        limb over = div_by_2_26(output[i]);
+        output[i] -= over << 26;
+        output[i + 1] += over;
+
+        over = div_by_2_25(output[i + 1]);
+        output[i + 1] -= over << 25;
+        output[i + 2] += over;
+    }
+    /* Now |output[10]| < 2 ^ 38 and all other coefficients are reduced. */
+    output[0] += output[10] << 4;
+    output[0] += output[10] << 1;
+    output[0] += output[10];
+
+    output[10] = 0;
+
+    /* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19 * 2^38
+   * So |over| will be no more than 77825  */
+    {
+        limb over = div_by_2_26(output[0]);
+        output[0] -= over << 26;
+        output[1] += over;
+    }
+
+    /* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 77825
+   * So |over| will be no more than 1. */
+    {
+        /* output[1] fits in 32 bits, so we can use div_s32_by_2_25 here. */
+        s32 over32 = div_s32_by_2_25((s32)output[1]);
+        output[1] -= over32 << 25;
+        output[2] += over32;
+    }
+
+    /* Finally, output[0,1,3..9] are reduced, and output[2] is "nearly reduced":
+   * we have |output[2]| <= 2^26.  This is good enough for all of our math,
+   * but it will require an extra freduce_coefficients before fcontract. */
+}
+
+/* A helpful wrapper around fproduct: output = in * in2.
+ *
+ * output must be distinct to both inputs. The output is reduced degree and
+ * reduced coefficient.
+ */
+static void
+fmul(limb *output, const limb *in, const limb *in2)
+{
+    limb t[19];
+    fproduct(t, in, in2);
+    freduce_degree(t);
+    freduce_coefficients(t);
+    memcpy(output, t, sizeof(limb) * 10);
+}
+
+static void fsquare_inner(limb *output, const limb *in)
+{
+    output[0] = ((limb)((s32)in[0])) * ((s32)in[0]);
+    output[1] = 2 * ((limb)((s32)in[0])) * ((s32)in[1]);
+    output[2] = 2 * (((limb)((s32)in[1])) * ((s32)in[1]) +
+                     ((limb)((s32)in[0])) * ((s32)in[2]));
+    output[3] = 2 * (((limb)((s32)in[1])) * ((s32)in[2]) +
+                     ((limb)((s32)in[0])) * ((s32)in[3]));
+    output[4] = ((limb)((s32)in[2])) * ((s32)in[2]) +
+                4 * ((limb)((s32)in[1])) * ((s32)in[3]) +
+                2 * ((limb)((s32)in[0])) * ((s32)in[4]);
+    output[5] = 2 * (((limb)((s32)in[2])) * ((s32)in[3]) +
+                     ((limb)((s32)in[1])) * ((s32)in[4]) +
+                     ((limb)((s32)in[0])) * ((s32)in[5]));
+    output[6] = 2 * (((limb)((s32)in[3])) * ((s32)in[3]) +
+                     ((limb)((s32)in[2])) * ((s32)in[4]) +
+                     ((limb)((s32)in[0])) * ((s32)in[6]) +
+                     2 * ((limb)((s32)in[1])) * ((s32)in[5]));
+    output[7] = 2 * (((limb)((s32)in[3])) * ((s32)in[4]) +
+                     ((limb)((s32)in[2])) * ((s32)in[5]) +
+                     ((limb)((s32)in[1])) * ((s32)in[6]) +
+                     ((limb)((s32)in[0])) * ((s32)in[7]));
+    output[8] = ((limb)((s32)in[4])) * ((s32)in[4]) +
+                2 * (((limb)((s32)in[2])) * ((s32)in[6]) +
+                     ((limb)((s32)in[0])) * ((s32)in[8]) +
+                     2 * (((limb)((s32)in[1])) * ((s32)in[7]) +
+                          ((limb)((s32)in[3])) * ((s32)in[5])));
+    output[9] = 2 * (((limb)((s32)in[4])) * ((s32)in[5]) +
+                     ((limb)((s32)in[3])) * ((s32)in[6]) +
+                     ((limb)((s32)in[2])) * ((s32)in[7]) +
+                     ((limb)((s32)in[1])) * ((s32)in[8]) +
+                     ((limb)((s32)in[0])) * ((s32)in[9]));
+    output[10] = 2 * (((limb)((s32)in[5])) * ((s32)in[5]) +
+                      ((limb)((s32)in[4])) * ((s32)in[6]) +
+                      ((limb)((s32)in[2])) * ((s32)in[8]) +
+                      2 * (((limb)((s32)in[3])) * ((s32)in[7]) +
+                           ((limb)((s32)in[1])) * ((s32)in[9])));
+    output[11] = 2 * (((limb)((s32)in[5])) * ((s32)in[6]) +
+                      ((limb)((s32)in[4])) * ((s32)in[7]) +
+                      ((limb)((s32)in[3])) * ((s32)in[8]) +
+                      ((limb)((s32)in[2])) * ((s32)in[9]));
+    output[12] = ((limb)((s32)in[6])) * ((s32)in[6]) +
+                 2 * (((limb)((s32)in[4])) * ((s32)in[8]) +
+                      2 * (((limb)((s32)in[5])) * ((s32)in[7]) +
+                           ((limb)((s32)in[3])) * ((s32)in[9])));
+    output[13] = 2 * (((limb)((s32)in[6])) * ((s32)in[7]) +
+                      ((limb)((s32)in[5])) * ((s32)in[8]) +
+                      ((limb)((s32)in[4])) * ((s32)in[9]));
+    output[14] = 2 * (((limb)((s32)in[7])) * ((s32)in[7]) +
+                      ((limb)((s32)in[6])) * ((s32)in[8]) +
+                      2 * ((limb)((s32)in[5])) * ((s32)in[9]));
+    output[15] = 2 * (((limb)((s32)in[7])) * ((s32)in[8]) +
+                      ((limb)((s32)in[6])) * ((s32)in[9]));
+    output[16] = ((limb)((s32)in[8])) * ((s32)in[8]) +
+                 4 * ((limb)((s32)in[7])) * ((s32)in[9]);
+    output[17] = 2 * ((limb)((s32)in[8])) * ((s32)in[9]);
+    output[18] = 2 * ((limb)((s32)in[9])) * ((s32)in[9]);
+}
+
+static void
+fsquare(limb *output, const limb *in)
+{
+    limb t[19];
+    fsquare_inner(t, in);
+    freduce_degree(t);
+    freduce_coefficients(t);
+    memcpy(output, t, sizeof(limb) * 10);
+}
+
+/* Take a little-endian, 32-byte number and expand it into polynomial form */
+static void
+fexpand(limb *output, const u8 *input)
+{
+#define F(n, start, shift, mask)                     \
+    output[n] = ((((limb)input[start + 0]) |         \
+                  ((limb)input[start + 1]) << 8 |    \
+                  ((limb)input[start + 2]) << 16 |   \
+                  ((limb)input[start + 3]) << 24) >> \
+                 shift) &                            \
+                mask;
+    F(0, 0, 0, 0x3ffffff);
+    F(1, 3, 2, 0x1ffffff);
+    F(2, 6, 3, 0x3ffffff);
+    F(3, 9, 5, 0x1ffffff);
+    F(4, 12, 6, 0x3ffffff);
+    F(5, 16, 0, 0x1ffffff);
+    F(6, 19, 1, 0x3ffffff);
+    F(7, 22, 3, 0x1ffffff);
+    F(8, 25, 4, 0x3ffffff);
+    F(9, 28, 6, 0x3ffffff);
+#undef F
+}
+
+#if (-32 >> 1) != -16
+#error "This code only works when >> does sign-extension on negative numbers"
+#endif
+
+/* Take a fully reduced polynomial form number and contract it into a
+ * little-endian, 32-byte array
+ */
+static void
+fcontract(u8 *output, limb *input)
+{
+    int i;
+    int j;
+
+    for (j = 0; j < 2; ++j)
+    {
+        for (i = 0; i < 9; ++i)
+        {
+            if ((i & 1) == 1)
+            {
+                /* This calculation is a time-invariant way to make input[i] positive
+           by borrowing from the next-larger limb.
+        */
+                const s32 mask = (s32)(input[i]) >> 31;
+                const s32 carry = -(((s32)(input[i]) & mask) >> 25);
+                input[i] = (s32)(input[i]) + (carry << 25);
+                input[i + 1] = (s32)(input[i + 1]) - carry;
+            }
+            else
+            {
+                const s32 mask = (s32)(input[i]) >> 31;
+                const s32 carry = -(((s32)(input[i]) & mask) >> 26);
+                input[i] = (s32)(input[i]) + (carry << 26);
+                input[i + 1] = (s32)(input[i + 1]) - carry;
+            }
+        }
+        {
+            const s32 mask = (s32)(input[9]) >> 31;
+            const s32 carry = -(((s32)(input[9]) & mask) >> 25);
+            input[9] = (s32)(input[9]) + (carry << 25);
+            input[0] = (s32)(input[0]) - (carry * 19);
+        }
+    }
+
+    /* The first borrow-propagation pass above ended with every limb
+     except (possibly) input[0] non-negative.
+
+     Since each input limb except input[0] is decreased by at most 1
+     by a borrow-propagation pass, the second borrow-propagation pass
+     could only have wrapped around to decrease input[0] again if the
+     first pass left input[0] negative *and* input[1] through input[9]
+     were all zero.  In that case, input[1] is now 2^25 - 1, and this
+     last borrow-propagation step will leave input[1] non-negative.
+  */
+    {
+        const s32 mask = (s32)(input[0]) >> 31;
+        const s32 carry = -(((s32)(input[0]) & mask) >> 26);
+        input[0] = (s32)(input[0]) + (carry << 26);
+        input[1] = (s32)(input[1]) - carry;
+    }
+
+    /* Both passes through the above loop, plus the last 0-to-1 step, are
+     necessary: if input[9] is -1 and input[0] through input[8] are 0,
+     negative values will remain in the array until the end.
+   */
+
+    input[1] <<= 2;
+    input[2] <<= 3;
+    input[3] <<= 5;
+    input[4] <<= 6;
+    input[6] <<= 1;
+    input[7] <<= 3;
+    input[8] <<= 4;
+    input[9] <<= 6;
+#define F(i, s)                              \
+    output[s + 0] |= input[i] & 0xff;        \
+    output[s + 1] = (input[i] >> 8) & 0xff;  \
+    output[s + 2] = (input[i] >> 16) & 0xff; \
+    output[s + 3] = (input[i] >> 24) & 0xff;
+    output[0] = 0;
+    output[16] = 0;
+    F(0, 0);
+    F(1, 3);
+    F(2, 6);
+    F(3, 9);
+    F(4, 12);
+    F(5, 16);
+    F(6, 19);
+    F(7, 22);
+    F(8, 25);
+    F(9, 28);
+#undef F
+}
+
+/* Input: Q, Q', Q-Q'
+ * Output: 2Q, Q+Q'
+ *
+ *   x2 z3: long form
+ *   x3 z3: long form
+ *   x z: short form, destroyed
+ *   xprime zprime: short form, destroyed
+ *   qmqp: short form, preserved
+ */
+static void fmonty(limb *x2, limb *z2,         /* output 2Q */
+                   limb *x3, limb *z3,         /* output Q + Q' */
+                   limb *x, limb *z,           /* input Q */
+                   limb *xprime, limb *zprime, /* input Q' */
+                   const limb *qmqp /* input Q - Q' */)
+{
+    limb origx[10], origxprime[10], zzz[19], xx[19], zz[19], xxprime[19],
+        zzprime[19], zzzprime[19], xxxprime[19];
+
+    memcpy(origx, x, 10 * sizeof(limb));
+    fsum(x, z);
+    fdifference(z, origx); // does x - z
+
+    memcpy(origxprime, xprime, sizeof(limb) * 10);
+    fsum(xprime, zprime);
+    fdifference(zprime, origxprime);
+    fproduct(xxprime, xprime, z);
+    fproduct(zzprime, x, zprime);
+    freduce_degree(xxprime);
+    freduce_coefficients(xxprime);
+    freduce_degree(zzprime);
+    freduce_coefficients(zzprime);
+    memcpy(origxprime, xxprime, sizeof(limb) * 10);
+    fsum(xxprime, zzprime);
+    fdifference(zzprime, origxprime);
+    fsquare(xxxprime, xxprime);
+    fsquare(zzzprime, zzprime);
+    fproduct(zzprime, zzzprime, qmqp);
+    freduce_degree(zzprime);
+    freduce_coefficients(zzprime);
+    memcpy(x3, xxxprime, sizeof(limb) * 10);
+    memcpy(z3, zzprime, sizeof(limb) * 10);
+
+    fsquare(xx, x);
+    fsquare(zz, z);
+    fproduct(x2, xx, zz);
+    freduce_degree(x2);
+    freduce_coefficients(x2);
+    fdifference(zz, xx); // does zz = xx - zz
+    memset(zzz + 10, 0, sizeof(limb) * 9);
+    fscalar_product(zzz, zz, 121665);
+    /* No need to call freduce_degree here:
+     fscalar_product doesn't increase the degree of its input. */
+    freduce_coefficients(zzz);
+    fsum(zzz, xx);
+    fproduct(z2, zz, zzz);
+    freduce_degree(z2);
+    freduce_coefficients(z2);
+}
+
+/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave
+ * them unchanged if 'iswap' is 0.  Runs in data-invariant time to avoid
+ * side-channel attacks.
+ *
+ * NOTE that this function requires that 'iswap' be 1 or 0; other values give
+ * wrong results.  Also, the two limb arrays must be in reduced-coefficient,
+ * reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped,
+ * and all all values in a[0..9],b[0..9] must have magnitude less than
+ * INT32_MAX.
+ */
+static void
+swap_conditional(limb a[19], limb b[19], limb iswap)
+{
+    unsigned i;
+    const s32 swap = (s32)-iswap;
+
+    for (i = 0; i < 10; ++i)
+    {
+        const s32 x = swap & (((s32)a[i]) ^ ((s32)b[i]));
+        a[i] = ((s32)a[i]) ^ x;
+        b[i] = ((s32)b[i]) ^ x;
+    }
+}
+
+/* Calculates nQ where Q is the x-coordinate of a point on the curve
+ *
+ *   resultx/resultz: the x coordinate of the resulting curve point (short form)
+ *   n: a little endian, 32-byte number
+ *   q: a point of the curve (short form)
+ */
+static void
+cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q)
+{
+    limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
+    limb *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t;
+    limb e[19] = {0}, f[19] = {1}, g[19] = {0}, h[19] = {1};
+    limb *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h;
+
+    unsigned i, j;
+
+    memcpy(nqpqx, q, sizeof(limb) * 10);
+
+    for (i = 0; i < 32; ++i)
+    {
+        u8 byte = n[31 - i];
+        for (j = 0; j < 8; ++j)
+        {
+            const limb bit = byte >> 7;
+
+            swap_conditional(nqx, nqpqx, bit);
+            swap_conditional(nqz, nqpqz, bit);
+            fmonty(nqx2, nqz2,
+                   nqpqx2, nqpqz2,
+                   nqx, nqz,
+                   nqpqx, nqpqz,
+                   q);
+            swap_conditional(nqx2, nqpqx2, bit);
+            swap_conditional(nqz2, nqpqz2, bit);
+
+            t = nqx;
+            nqx = nqx2;
+            nqx2 = t;
+            t = nqz;
+            nqz = nqz2;
+            nqz2 = t;
+            t = nqpqx;
+            nqpqx = nqpqx2;
+            nqpqx2 = t;
+            t = nqpqz;
+            nqpqz = nqpqz2;
+            nqpqz2 = t;
+
+            byte <<= 1;
+        }
+    }
+
+    memcpy(resultx, nqx, sizeof(limb) * 10);
+    memcpy(resultz, nqz, sizeof(limb) * 10);
+}
+
+// -----------------------------------------------------------------------------
+// Shamelessly copied from djb's code
+// -----------------------------------------------------------------------------
+static void
+crecip(limb *out, const limb *z)
+{
+    limb z2[10];
+    limb z9[10];
+    limb z11[10];
+    limb z2_5_0[10];
+    limb z2_10_0[10];
+    limb z2_20_0[10];
+    limb z2_50_0[10];
+    limb z2_100_0[10];
+    limb t0[10];
+    limb t1[10];
+    int i;
+
+    /* 2 */ fsquare(z2, z);
+    /* 4 */ fsquare(t1, z2);
+    /* 8 */ fsquare(t0, t1);
+    /* 9 */ fmul(z9, t0, z);
+    /* 11 */ fmul(z11, z9, z2);
+    /* 22 */ fsquare(t0, z11);
+    /* 2^5 - 2^0 = 31 */ fmul(z2_5_0, t0, z9);
+
+    /* 2^6 - 2^1 */ fsquare(t0, z2_5_0);
+    /* 2^7 - 2^2 */ fsquare(t1, t0);
+    /* 2^8 - 2^3 */ fsquare(t0, t1);
+    /* 2^9 - 2^4 */ fsquare(t1, t0);
+    /* 2^10 - 2^5 */ fsquare(t0, t1);
+    /* 2^10 - 2^0 */ fmul(z2_10_0, t0, z2_5_0);
+
+    /* 2^11 - 2^1 */ fsquare(t0, z2_10_0);
+    /* 2^12 - 2^2 */ fsquare(t1, t0);
+    /* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2)
+    {
+        fsquare(t0, t1);
+        fsquare(t1, t0);
+    }
+    /* 2^20 - 2^0 */ fmul(z2_20_0, t1, z2_10_0);
+
+    /* 2^21 - 2^1 */ fsquare(t0, z2_20_0);
+    /* 2^22 - 2^2 */ fsquare(t1, t0);
+    /* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2)
+    {
+        fsquare(t0, t1);
+        fsquare(t1, t0);
+    }
+    /* 2^40 - 2^0 */ fmul(t0, t1, z2_20_0);
+
+    /* 2^41 - 2^1 */ fsquare(t1, t0);
+    /* 2^42 - 2^2 */ fsquare(t0, t1);
+    /* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2)
+    {
+        fsquare(t1, t0);
+        fsquare(t0, t1);
+    }
+    /* 2^50 - 2^0 */ fmul(z2_50_0, t0, z2_10_0);
+
+    /* 2^51 - 2^1 */ fsquare(t0, z2_50_0);
+    /* 2^52 - 2^2 */ fsquare(t1, t0);
+    /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2)
+    {
+        fsquare(t0, t1);
+        fsquare(t1, t0);
+    }
+    /* 2^100 - 2^0 */ fmul(z2_100_0, t1, z2_50_0);
+
+    /* 2^101 - 2^1 */ fsquare(t1, z2_100_0);
+    /* 2^102 - 2^2 */ fsquare(t0, t1);
+    /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2)
+    {
+        fsquare(t1, t0);
+        fsquare(t0, t1);
+    }
+    /* 2^200 - 2^0 */ fmul(t1, t0, z2_100_0);
+
+    /* 2^201 - 2^1 */ fsquare(t0, t1);
+    /* 2^202 - 2^2 */ fsquare(t1, t0);
+    /* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2)
+    {
+        fsquare(t0, t1);
+        fsquare(t1, t0);
+    }
+    /* 2^250 - 2^0 */ fmul(t0, t1, z2_50_0);
+
+    /* 2^251 - 2^1 */ fsquare(t1, t0);
+    /* 2^252 - 2^2 */ fsquare(t0, t1);
+    /* 2^253 - 2^3 */ fsquare(t1, t0);
+    /* 2^254 - 2^4 */ fsquare(t0, t1);
+    /* 2^255 - 2^5 */ fsquare(t1, t0);
+    /* 2^255 - 21 */ fmul(out, t1, z11);
+}
+
+int curve25519_donna(u8 *, const u8 *, const u8 *);
+
+int curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint)
+{
+    limb bp[10], x[10], z[11], zmone[10];
+    uint8_t e[32];
+    int i;
+
+    for (i = 0; i < 32; ++i)
+        e[i] = secret[i];
+    e[0] &= 248;
+    e[31] &= 127;
+    e[31] |= 64;
+
+    fexpand(bp, basepoint);
+    cmult(x, z, e, bp);
+    crecip(zmone, z);
+    fmul(z, x, zmone);
+    freduce_coefficients(z);
+    fcontract(mypublic, z);
+    return 0;
+}
+
+/// returns 0 for '=' or unrecognized characters, not a problem since PEM is well constrained.
+static int base64_value(int c)
+{
+    if (c >= 'A' && c <= 'Z')
+        return c - 'A';
+    if (c >= 'a' && c <= 'z')
+        return 26 + c - 'a';
+    if (c >= '0' && c <= '9')
+        return 52 + c - '0';
+    if (c == '+')
+        return 62;
+    if (c == '/')
+        return 63;
+    return 0x1000;
+}
+
+/**
+ * @param[in] data the base64 encoded string
+ * @param[out] data the decoded result
+ * @param[in] len the length of base64 encoded data
+ * @param[out] len the length of decoded result
+ */
+static void base64_decode(u8 *data, int *len)
+{
+    int read = 0;
+    int write = 0;
+    int state[4];
+    while (read < *len)
+    {
+        state[read % 4] = base64_value(data[read]);
+        if (state[read % 4] == 0x1000)
+        {
+            break;
+        }
+        if ((read % 4) == 3)
+        {
+            data[write++] = state[0] << 2 | state[1] >> 4;
+            data[write++] = state[1] << 4 | state[2] >> 2;
+            data[write++] = state[2] << 6 | state[3] >> 0;
+        }
+        read++;
+    }
+    switch (read % 4)
+    {
+    case 2:
+        data[write++] = state[0] << 2 | state[1] >> 4;
+        break;
+    case 3:
+        data[write++] = state[0] << 2 | state[1] >> 4;
+        data[write++] = state[1] << 4 | state[2] >> 2;
+    }
+    *len = write;
+}
+
+/**
+ * reads the 32-byte key from a PEM file, takes advantage of the
+ * fact that the last 32 bytes of encoded DER data are the key in
+ * both the private and public key forms.
+ */
+void read_key(const char *filename, u8 *key)
+{
+    FILE *f = fopen(filename, "r");
+    if (!f)
+    {
+        fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
+        exit(1);
+    }
+    char line[512] = {};
+    fgets(line, sizeof(line), f);
+    if (strncmp(line, "-----BEGIN ", sizeof("-----BEGIN ") - 1) != 0)
+    {
+        fprintf(stderr, "File %s is not a PEM file\n", filename);
+        exit(1);
+    }
+    fgets(line, sizeof(line), f);
+    line[strcspn(line, "\r\n")] = '\0';
+    int len = strlen(line);
+    base64_decode((u8 *)line, &len);
+    if (len < 32)
+    {
+        fprintf(stderr, "Short read from %s\n", filename);
+        exit(1);
+    }
+    memcpy(key, line + (len - 32), 32);
+    fclose(f);
+    return;
+}
+
+int main(int argc, char **argv)
+{
+    u8 privkey[32];
+    u8 pubkey[32];
+    u8 result[32];
+
+    if (argc != 3)
+    {
+        fprintf(stderr, "Usage: %s [privkey] [pubkey]\n", argv[0]);
+        exit(1);
+    }
+    read_key(argv[1], privkey);
+    read_key(argv[2], pubkey);
+    curve25519_donna(result, privkey, pubkey);
+    // fwrite(result, 32, 1, stdout);
+    for (int i = 0; i < 32; i++)
+    {
+
+        printf("%d ", result[i]);
+    }
+    exit(0);
+}

+ 0 - 1
oracle/__init__.py

@@ -1 +0,0 @@
-

+ 0 - 22
oracle/broadcast.py

@@ -1,22 +0,0 @@
-
-import socket
-import threading
-
-        
-class Broadcast():
-
-    def __init__(self,  broadcastPort,socketPort): 
-        """ ,broadcast """ # TODO Broadcast
-        self.socketPort = socketPort
-        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        self.sock.bind(('', broadcastPort)) # TODO Broadcast
-        t1 = threading.Thread(target=self.listen)
-        t1.start()
-        print("Broadcast Listener is created")
-
-    def listen(self):
-        while True:
-            msg, addr = self.sock.recvfrom(1024)
-            print("\n Message",msg," from ",addr)
-            self.sock.sendto(bytes(str(self.socketPort),'utf-8'),addr)

+ 0 - 42
oracle/connection.py

@@ -1,42 +0,0 @@
-
-import socket
-import threading
-import json
-import config as cfg
-
-class Connection(threading.Thread):
-    def __init__(self,connection,address,oracleSocketPort,typee):
-        super(Connection,self).__init__(None, None, 
-			              None, None)
-        self.conn = connection
-        self.addr = address
-        self.history = []
-        self.type = typee
-        self.oracleSocketPort = oracleSocketPort
-
-
-        t = threading.Thread(target=self.receive)
-        t.start()
-        # self.send("Connection")
-
-    def toSEND(self, data):
-        j = json.dumps(x)
-        l = LenFunc - len(str(len(j)))
-        self.send("0000"[0:l]+str(len(j))+j)
-
-    def send(self,Message):
-        Message=bytes(Message,'utf-8')
-        self.conn.sendall(Message)
-        # self.history.append(("send",Message))
-
-
-    def receive(self):
-        while True: 
-            len = self.conn.recv(cfg.LenFunc)
-            if not len:
-                break
-            data = self.conn.recv(int(len))
-
-            print("data",data)
-            self.type.parser(data.decode("utf-8"),self.conn)
-            # self.history.append(("receive",data))

+ 17 - 7
oracle/oracle.py

@@ -1,9 +1,19 @@
-
-from .broadcast import Broadcast
-from .socket import Socket
+from connection.broadcast import BroadcastServer
+from connection.socket import SocketServer
+from .oracleParser import OracleParser
 import random 
 import random 
+import os 
+
+
+
+class Oracle():
+    def __init__(self,broadcast, broadcastPort):
+
+        self.id = os.urandom(32)
+        self.socketPort = int(random.random()*50000+1024)
+        self.parser = OracleParser(self) #,socketPort=socketPort
+        self.b = BroadcastServer(broadcastPort=broadcastPort , parser= self.parser,id=self.id)
+        print("Done")
+        self.s = SocketServer(self.socketPort , parser= self.parser ,  id=self.id)
 
 
-socketPort = int(random.random()*50000+1024)
-def run(broadcast, broadcastPort):
-    b = Broadcast(broadcastPort=broadcastPort,socketPort=socketPort)
-    s = Socket(socketPort)
+    

+ 88 - 0
oracle/oracleParser.py

@@ -0,0 +1,88 @@
+from connection.parser import Parser
+from .worker.cryptor import Cryptor
+from .worker.connector import Connector
+from .worker.bearer import Bearer
+
+class OracleParser(Parser):
+    def __init__(self,oracle):
+        self.socket = oracle.socketPort
+        self.oracle = oracle
+        self.type = None
+        self.id = None
+        print("createt oracle Parser")
+
+    def parser(self,data,addr,Connection):
+        try:
+            # Broadcast Parser
+            if data["type"] == "requestOracleBroadcast":
+                self.requestOracleBroadcast(data,addr) 
+            # Socket Parser
+            elif data["type"] == "socketConnecting":
+                self.socketConnecting(data)
+            elif data["type"] == "oracleInitial":
+                self.type.oracleInitial(data)
+            elif data["type"] == "keyExchange":
+                self.type.keyExchange(data)
+            elif data["type"] == "fromContoCry":
+                self.type.fromContoCry(data)
+            elif data["type"] == "fromConMPC":
+                self.type.MPC(data)
+            elif data["type"] == "fromCrytoCon":
+                self.type.fromCrytoCon(data)
+            elif data["type"] == "fromContoCryHelloCLient":
+                self.type.fromContoCryHelloCLient(data)
+        except :
+            print("\33[41m\33[41mAn exception occurred parser" ,data["type"],self.type,"\33[0m")
+
+    def requestOracleBroadcast(self,data,addr):
+        try:
+            d = {}
+            self.add(d,"type","responseUserBroadcast")
+            self.id = data["id"]
+            self.add(d,"message","Hello "+data["id"])
+            self.add(d,"socket",self.socket)
+            self.oracle.b.send(self.toSEND(d),addr)
+        except:
+            print("\33[41mAn exception occurred requestOracleBroadcast\33[0m")
+
+    def socketConnecting(self,data):
+        try:
+            if data["oracle"] == 0: 
+                self.type = Connector(self,self.socket+1)
+            elif data["oracle"] == 1: 
+                self.type = Cryptor(self)
+            elif data["oracle"] == 2: 
+                self.type = Bearer(self)
+            else:
+                print("An exception occurred socketConnecting Oracle data ")
+        except:
+            print("\33[41mAn exception occurred socketConnecting\33[0m")
+
+
+    # def fromConMPC(self,function,port,connection):
+    #     try:
+    #         d = {}
+    #         self.add(d,"type","fromConMPC")
+    #         self.add(d,"function",function)
+    #         self.add(d,"port",port)
+    #         connection.send(self.toSEND(d))
+    #     except Exception as exception:
+    #         print("\33[41mAn exception occurred Parse fromContoCryMPC ",exception,"\33[0m")
+
+    # def fromCrytoCon(self,data,connection):
+    #     try:
+    #         d = {}
+    #         self.add(d,"type","fromCrytoCon")
+    #         self.add(d,"data",data)
+    #         connection.send(self.toSEND(d))
+    #     except Exception as exception:
+    #         print("\33[41mAn exception occurred Parse fromCrytoCon ",exception,"\33[0m")
+
+    def parserSend(self,data,connection,typeO):
+        try:
+            d = {}
+            self.add(d,"type",typeO)
+            self.add(d,"data",data)
+            connection.send(self.toSEND(d))
+        except Exception as exception:
+            print("\33[41mAn exception occurred Parse ",typeO ,exception,"\33[0m")

+ 0 - 74
oracle/socket.py

@@ -1,74 +0,0 @@
-
-import socket
-import threading
-from .worker.connector import Connector
-from .worker.cryptor import Cryptor
-from .worker.bearer import Bearer       
-import config as cfg
-import json
-
-class Socket():
-
-    def __init__(self, socketPort):
-        self.socketPort = socketPort 
-        t = threading.Thread(target=self.connection)
-        t.start()
-        print("socket is created and Listener is created",socketPort)
-
-    def connection(self):
-        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
-            s.bind(("localhost", self.socketPort))
-            s.listen()
-            self.socket = s
-            while True:
-                conn, addr = self.socket.accept()
-                print(conn, addr)
-                u = threading.Thread(target=Connection,args=(conn, addr,self.socketPort+1)) # TODO socketprot dynamic
-                u.start()
-
-class Connection(threading.Thread):
-    def __init__(self,connection,address,oracleSocketPort):
-        super(Connection,self).__init__(None, None, 
-			              None, None)
-        self.conn = connection
-        self.addr = address
-        self.history = []
-        self.type = None
-        self.oracleSocketPort = oracleSocketPort
-
-
-        t = threading.Thread(target=self.receive)
-        t.start()
-        # self.send("Connection")
-
-    def toSEND(self,oracle, data):
-        j = json.dumps(x)
-        l = LenFunc - len(str(len(j)))
-        oracle.send("0000"[0:l]+str(len(j))+j)
-        
-    def send(self,Message):
-        Message=bytes(Message,'utf-8')
-        self.conn.sendall(Message)
-        # self.history.append(("send",Message))
-
-
-    def receive(self):
-        while True: 
-            len = self.conn.recv(cfg.LenFunc)
-            if not len:
-                break
-            data = self.conn.recv(int(len))
-            if not self.type:
-                d = json.loads(data)
-                if d["type"] == "user": 
-                    if d["oracle"] == 0:
-                        self.type = Connector(self) 
-                    elif d["oracle"] == 1:
-                        self.type = Cryptor(self) 
-                    elif d["oracle"] == 2:
-                        self.type = Bearer(self) 
-
-            else:    
-                print("data",data)
-                self.type.parser(data.decode("utf-8"),self.conn)
-                # self.history.append(("receive",data))

+ 23 - 18
oracle/worker/bearer.py

@@ -1,25 +1,30 @@
 import socket
 import socket
+import time
 import threading
 import threading
 import config as cfg
 import config as cfg
-from .worker import Worker
-class Bearer(Worker):
+from connection.socket import SocketClient
 
 
-    def __init__(self, parent):
-        super().__init__(self,parent)
-        print("\n\n Bearer \n\n")
+class Bearer():
 
 
-    def socketOracle(self,HOST,PORT):
-        self.connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.connector.connect((HOST, PORT))
+    def __init__(self, parser):
+        self.parser = parser
+        self.connector = None
+        self.data = None
+        print("\n\n Bearer,  \n ")
 
 
-        t = threading.Thread(target=self.receive)
-        t.start()
-        self.toSEND({
-            "type":"oracleInit",
-            "oracle":"Bearer"
-        })
-        print("socket is created and Listener is created\n")
+    def oracleInitial(self,data):
+        try:
+            time.sleep(3)
+            self.connector = SocketClient(data["connector"][0],data["connector"][1],self.parser,"Bearer")
+            self.data = data["data"]
+        except Exception as exception :
+            print("\33[41mAn exception occurred oracleInitial Bearer " ,exception,"\33[0m" )   
 
 
-    def start(self,a):
-        print("Bearer",a)
-        self.socketOracle(self.connectorIP,self.connectorPort)
+    def MPC(self,data):
+        try:
+            print("TODO") # TODO
+        except Exception as exception :
+            print("\33[41mAn exception occurred MPC Bearer " ,exception,"\33[0m" )   
+
+
+            

+ 153 - 30
oracle/worker/connector.py

@@ -1,42 +1,165 @@
 import socket
 import socket
 import threading
 import threading
+import os
 import config as cfg
 import config as cfg
-from .worker import Worker
-from src.oracle.connection import Connection
-# p = str('16 03 01 00 c1 01 00 00 bd 03 03 d1 47 a0 85 e9 cd 6d 34 cc ef b5 41 48 3f ec a1 f4 5c da e7 b0 27 c4 5d 0f 5f 65 bf d9 e8 6f a2 20 4a 71 5d 24 4a eb 65 da a9 7f b8 ec 55 32 2e 06 ff aa fc b8 77 58 a8 06 ec 19 05 67 e9 3546 eb 00 02 13 01 01 00 00 72 00 00 00 13 00 11 00 00 0e 77 77 77 2e 67 6f 6f 67 6c 65 2e 63 6f 6d 00 0b 00 04 03 00 01 02 00 0a 00 04 00 02 00  1d 00 23 00 00 00 16 00 00 00 17 00 00 00 0d 00  04 00 02 08 07 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 8a d0 24 78  1d 71 cd 22 3f 28 93 aa ff 0d 1b 4e ba 18 1f d4  4a d4 a0 80 ca 78 d9 0c a4 29 1b 3f')
-p = str('16 03 01 00 c1 01 00 00 bd 03 03 d1 47 a0 85 e9 cd 6d 34 cc ef b5 41 48 3f ec a1 f4 5c da e7 b0 27 c4 5d 0f 5f 65 bf d9 e8 6f a2 20 4a 71 5d 24 4a eb 65 da a9 7f b8 ec 55 32 2e 06 ff aa fc b8 77 58 a8 06 ec 19 05 67 e9 3546 eb 00 02 13 01 01 00 00 72 00 00 00 13 00 11 00 00 0e 77 77 77 2e 67 6f 6f 67 6c 65 2e 63 6f 6d 00 0b 00 04 03 00 01 02 00 0a 00 04 00 02 00  1d 00 23 00 00 00 16 00 00 00 17 00 00 00 0d 00  04 00 02 08 07 00 2b 00 03 02 03 04 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 8a d0 24 78  1d 71 cd 22 3f 28 93 aa ff 0d 1b 4e ba 18 1f d4  4a d4 a0 80 ca 78 d9 0c a4 29 1b 3f')
+from connection.socket import SocketServer
+from connection.socket import SocketHTTP
+from tcp import models
+import time
+from tcp import utils
+import tcp as t
+from types import SimpleNamespace
 
 
-class Connector(Worker):
+class Connector():
 
 
-    def __init__(self, parent):
-        super().__init__(self,parent)
-        self.path = None
-        print("\n\n Connector \n\n")
+    def __init__(self, parser,socket):
+        self.parser = parser
+        self.server = None
+        self.serverDomain = None
+        self.serverIP = None
+        self.s = SocketServer(socket,self.parser,"Connector")
+        self.buffer = []
+        self.handshaked = False
+        self.t = threading.Thread(target=self.tcp)
+        
+        print("\n\n Connector\n\n")
+        
 
 
-        t = threading.Thread(target=self.oraclesConnection)
-        t.start()
-        print("socket is created and Listener is created",self.parent.oracleSocketPort)
+    def recv(self,data):
+        try:
+            self.buffer.append(data)
+            if not self.t.is_alive():
+                self.t.start()
+        except:
+            print("\33[41m\33[41mAn exception occurred recv\33[0m" )
 
 
-    def oraclesConnection(self):
-        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
-            s.bind(("localhost", self.parent.oracleSocketPort))
-            s.listen()
-            self.socket = s
-            while True:
-                conn, addr = self.socket.accept()
-                print(conn, addr)
-                u = threading.Thread(target=Connection,args=(conn, addr,None,self)) # TODO socketprot dynamic
-                u.start()
+    def oracleInitial(self,data):
+        try:
+            while len(self.s.connected) < 2:
+                time.sleep(.5)
+            if(len(self.s.connected) == 2):
+                # if self.s.connected[0].addr[0] == data["bearer"]  and  self.s.connected[1].addr[0] == data["cryptor"]:
+                    self.bearer = self.s.connected[1]
+                    self.cryptor = self.s.connected[0]
+                # elif self.s.connected[1].addr[0] == data["bearer"]  and  self.s.connected[0].addr[0] == data["cryptor"]:
+                #     self.bearer = self.s.connected[1]
+                #     self.cryptor = self.s.connected[0]
+                # else:
+                #     raise Exception("Error") 
+                    
 
 
+            self.serverDomain = data["server"]
+            if type(self.serverDomain) == str:
+                self.serverDomain = [self.serverDomain]
+            # self.serverIP = socket.gethostbyname(data["server"])
+            self.serverIP = "216.58.205.228"
+            self.server = SocketHTTP(self.serverIP,443,self)
+        except Exception as e:
+            print("\33[41m\33[41mAn exception occurred oracleInitial Connector ",e,"\33[0m" )
+        
+    def keyExchange(self,data):
+        try:
+            while not self.server: 
+                time.sleep(.5)
+            self.key_exchange =bytes.fromhex( data["keyExchange"])
+            self.server.send(bytes.fromhex(self.client_hello()))
+        except NameError:
+            print(NameError)
+            print("\33[41mAn exception occurred keyExchange Connector,\33[0m")
 
 
-    def start(self,data):
-        self.path = data["path"]
-        print("Connector",data)
+    # def toCryptor(self,data):
+    #     try:
+    #         self.key_exchange =bytes.fromhex( data["keyExchange"])
+    #         self.server.send(bytes.fromhex(self.client_hello()))
+    #     except NameError:
+    #         print(NameError)
+    #         print("\33[41mAn exception occurred keyExchange Connector,\33[0m")
 
 
 
 
+    def client_hello(self):
+        try:
+            print("Done 1")
+            extensions = [
+                models.ClientExtension.server_names(self.serverDomain),
+                models.ClientExtension.supported_versions([b"\x03\x04"]),
+                models.ClientExtension.key_share(
+                    [models.KeyShareEntry(models.NamedGroup.x25519, self.key_exchange)]
+                ),
+                models.ClientExtension.signature_algorithms(list(models.SignatureScheme)),
+                models.ClientExtension.supported_groups([models.NamedGroup.x25519]),
+            ]
+
+
+            
+            compatibility_mode = True
+            handshake = models.Handshake(
+                models.HandshakeType.client_hello,
+                models.ClientHello(
+                    ...,
+                    os.urandom(32),
+                    os.urandom(32) if compatibility_mode else b"",
+                    list(models.CipherSuite),
+                    ...,
+                    extensions,
+                ),
+            )
+            self.client_hello_data = handshake.binary
+            self.handshake_context = bytearray(self.client_hello_data)
+            self.parser.parserSend(bytes(self.client_hello_data).hex(),self.cryptor,"fromContoCryHelloCLient")
+
+            data = models.ContentType.handshake.tls_plaintext(self.client_hello_data)
+            return bytes.hex(data)
+        except Exception as exception:
+            print("\33[41mAn exception occurred client_hello Connector,\33[0m",exception)
+
+
+    def tcp(self):
+        while 1: 
+
+            time.sleep(0.5)
+            while self.buffer and self.buffer[0] and len(self.buffer[0])>=10:
+                s = self.buffer[0][6:10]
+                print(s)
+                l = int(s,16)*2+10
+                a = self.lenCalc(l)
+                if not self.handshaked:
+                    self.parser.parserSend(a,self.cryptor,"fromContoCry")
+        self.t.exit()
+
+
+
+    def lenCalc(self, len2):
+        if len(self.buffer[0]) > len2:
+            a = self.buffer[0][:len2]
+            self.buffer[0] = self.buffer[0][len2:]
+            return a
+        elif len(self.buffer[0]) == len2 :
+            return self.buffer.pop(0)
+        elif len(self.buffer[0]) < len2 :
+            if self.buffer[1]:
+                self.buffer[0] = self.buffer[0] + self.buffer[1]
+                self.buffer.pop(1)
+                return lenCalc(self.buffer,len2)
+            else:
+                print("Data is not copmlete1 ")
+                time.sleep(1)
+                lenCalc(self.buffer,len2)
+        else: 
+            print("Data is not copmlet2e")
+            time.sleep(1)
+            lenCalc(self.buffer,len2)
+
+    
+
+    def MPC(self,data):
+        try:
+            print("TODO") # TODO
+        except Exception as exception :
+            print("\33[41mAn exception occurred MPC Connector " ,exception,"\33[0m" )   
+
+    def fromCrytoCon(self,data):
+        try:
+            print("TODO fromCrytoCon") # TODO
+        except Exception as exception :
+            print("\33[41mAn exception occurred fromCrytoCon Connector " ,exception,"\33[0m" )   
 
 
-    def createConnection(self):#216.58.205.228
-        print("Connector",self.key_exchange)
-        self.sock = socket.socket()
-        self.sock.connect(("216.58.205.228", 443))
-        self.sock.sendall(bytes.fromhex(p))

+ 82 - 27
oracle/worker/cryptor.py

@@ -1,38 +1,93 @@
 import socket
 import socket
 import threading
 import threading
 import config as cfg
 import config as cfg
-from .worker import Worker
 from nacl.public import PrivateKey
 from nacl.public import PrivateKey
-
+from connection.socket import SocketClient
+from tcp import TLSClientSession
+import time
 def new_x25519():
 def new_x25519():
     private_key = PrivateKey.generate()
     private_key = PrivateKey.generate()
     key_exchange = bytes(private_key.public_key)
     key_exchange = bytes(private_key.public_key)
     return bytes(private_key).hex() , key_exchange.hex()
     return bytes(private_key).hex() , key_exchange.hex()
 
 
-class Cryptor(Worker):
+class Cryptor():
 
 
-    def __init__(self, parent):
-        super().__init__(self,parent)
+    def __init__(self, parser):
         self.privatekey , self.key_exchange = new_x25519()
         self.privatekey , self.key_exchange = new_x25519()
-        print("\n\n CRYPTOR,  \n ",self.privatekey ,type (self.key_exchange),"\n")
-
-    
-    def socketOracle(self,HOST,PORT):
-        self.connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.connector.connect((HOST, PORT))
-        t = threading.Thread(target=self.receive)
-        t.start()
-        self.toSEND({
-            "type":"oracleInit",
-            "oracle":"Cryptor"
-        })
-        print("socket is created and Listener is created\n")
-        self.toSEND({
-            "type":"key_exchange",
-            "key_exchange":self.key_exchange
-        })
-
-
-    def start(self,a):
-        print("Cryptor",a)
-        self.socketOracle(self.connectorIP,self.connectorPort)
+        self.server = None
+        self.parser = parser
+        self.connector = None
+        self.data = []
+        print("\n\n CRYPTOR,  \n ",self.privatekey ,self.key_exchange,"\n")
+
+    def oracleInitial(self,data):
+        try:
+            self.server = data["server"]
+            self.connector = SocketClient(data["connector"][0],data["connector"][1],self.parser,"Cryptor")
+            time.sleep(1)
+
+            self.keyExchange()
+        except:
+            print("\33[41mAn exception occurred oracleInitial Cryptor\33[0m" )   
+    # def socketOracle(self,HOST,PORT):
+    #     self.connector = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    #     self.connector.connect((HOST, PORT))
+    #     t = threading.Thread(target=self.receive)
+    #     t.start()
+    #     self.toSEND({
+    #         "type":"oracleInit",
+    #         "oracle":"Cryptor"
+    #     })
+    #     print("socket is created and Listener is created\n")
+    #     self.toSEND({
+    #         "type":"key_exchange",
+    #         "key_exchange":self.key_exchange
+    #     })
+
+
+    def keyExchange(self):
+        try:
+            d = {}
+            self.parser.add(d,"type","keyExchange")
+            self.parser.add(d,"keyExchange",self.key_exchange)
+            self.connector.send(self.parser.toSEND(d))
+        except:
+            print("\33[41mAn exception occurred keyExchange Cryptor\33[0m")
+    # def start(self,a):
+    #     print("Cryptor",a)
+    #     self.socketOracle(self.connectorIP,self.connectorPort)
+
+    def fromContoCryHelloCLient(self, data):
+        try:
+            self.tcp = TLSClientSession(self.privatekey , self.key_exchange,memoryview(bytes.fromhex(data["data"])))
+
+            print("TODO fromContoCry",data["data"]) # TODO
+        except Exception as exception :
+            print("\33[41mAn exception occurred fromContoCryHelloCLient Cryptor " ,exception,"\33[0m" )
+
+
+    def toCryptorFromConnector(self,data):
+        try:
+            print("TODO") # TODO
+        except Exception as exception :
+            print("\33[41mAn exception occurred toCryptorFromConnector Cryptor " ,exception,"\33[0m" )   
+
+        
+    def MPC(self,data):
+        try:
+            print("TODO") # TODO
+        except Exception as exception :
+            print("\33[41mAn exception occurred MPC Cryptor " ,exception,"\33[0m" )   
+
+    def fromContoCry(self,data):
+        try:
+            self.tcp.tls_response(data["data"])
+            print("TODO fromContoCry") # TODO
+        except Exception as exception :
+            print("\33[41mAn exception occurred fromContoCry Cryptor " ,exception,"\33[0m" )
+
+
+
+
+
+

+ 1 - 1
oracle/worker/worker.py

@@ -1,6 +1,6 @@
 import json
 import json
 import config as cfg
 import config as cfg
-from src.socketClient import Socket
+from connection.socketClient import Socket
 LenFunc = cfg.LenFunc
 LenFunc = cfg.LenFunc
 
 
 
 

File diff suppressed because it is too large
+ 5 - 0
res.txt


+ 3 - 0
sp

@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VuAyEAn9etbc/0KY3T+W1bGyr5EKBTWxSI1/j6uzSamCiAthU=
+-----END PUBLIC KEY-----

+ 745 - 0
tcp/__init__.py

@@ -0,0 +1,745 @@
+import os
+import time
+import struct
+import random
+import iofree
+import typing
+from dataclasses import dataclass
+from enum import IntEnum
+from types import SimpleNamespace
+from nacl.public import PrivateKey
+from nacl.bindings import crypto_scalarmult
+
+from Crypto.PublicKey import RSA
+
+# from Cryptography import x509
+# from OpenSSL.crypto import load_certificate, FILETYPE_ASN1
+from . import ciphers
+from .key_schedule import PSKWrapper
+from .utils import pack_int, pack_list, pack_all
+
+MAX_LIFETIME = 24 * 3600 * 7
+AGE_MOD = 2 ** 32
+
+
+class Alert(Exception):
+    def __init__(self, level, description):
+        self.level = level
+        self.description = description
+
+
+class MyIntEnum(IntEnum):
+    @classmethod
+    def from_value(cls, value: int):
+        for e in cls:
+            if e == value:
+                return e
+        raise Exception(f"Known {cls.__name__} type: {value}")
+
+
+class UInt8Enum(MyIntEnum):
+    def pack(self) -> bytes:
+        return self.to_bytes(1, "big")
+
+
+class UInt16Enum(MyIntEnum):
+    def pack(self) -> bytes:
+        return self.to_bytes(2, "big")
+
+
+class HandshakeType(UInt8Enum):
+    client_hello = 1
+    server_hello = 2
+    new_session_ticket = 4
+    end_of_early_data = 5
+    encrypted_extensions = 8
+    certificate = 11
+    certificate_request = 13
+    certificate_verify = 15
+    finished = 20
+    key_update = 24
+    message_hash = 254
+
+    def pack_data(self, data: bytes) -> bytes:
+        return self.pack() + pack_int(3, data)
+
+    def tls_inner_plaintext(self, content: bytes) -> bytes:
+        return (
+            self.pack_data(content)
+            + ContentType.handshake.pack()
+            + (b"\x00" * random.randint(0, 10))
+        )
+
+
+class ExtensionType(UInt16Enum):
+    server_name = 0
+    max_fragment_length = 1
+    status_request = 5
+    supported_groups = 10
+    signature_algorithms = 13
+    use_srtp = 14
+    heartbeat = 15
+    application_layer_protocol_negotiation = 16
+    signed_certificate_timestamp = 18
+    client_certificate_type = 19
+    server_certificate_type = 20
+    padding = 21
+    pre_shared_key = 41
+    early_data = 42
+    supported_versions = 43
+    cookie = 44
+    psk_key_exchange_modes = 45
+    certificate_authorities = 47
+    oid_filters = 48
+    post_handshake_auth = 49
+    signature_algorithms_cert = 50
+    key_share = 51
+
+    def pack_data(self, data: bytes) -> bytes:
+        return self.pack() + pack_int(2, data)
+
+    @classmethod
+    def server_name_list(cls, host_names: list) -> bytes:
+        return cls.server_name.pack_data(
+            pack_list(
+                2, (NameType.host_name.pack_data(name.encode()) for name in host_names)
+            )
+        )
+
+    @classmethod
+    def supported_versions_list(cls) -> bytes:
+        return cls.supported_versions.pack_data(pack_int(1, b"\x03\x04"))
+
+    @classmethod
+    def supported_groups_list(cls, named_group, *named_groups) -> bytes:
+        return cls.supported_groups.pack_data(
+            pack_list(2, (group.pack() for group in (named_group, *named_groups)))
+        )
+
+    @classmethod
+    def signature_algorithms_list(cls, algo, *algos) -> bytes:
+        return cls.signature_algorithms.pack_data(
+            pack_list(2, (alg.pack() for alg in (algo, *algos)))
+        )
+
+    @classmethod
+    def unpack_from(cls, mv: memoryview):
+        extensions = {}
+        while mv:
+            type_value = int.from_bytes(mv[:2], "big")
+            mv = mv[2:]
+            if mv:
+                extension_data_lenth = int.from_bytes(mv[:2], "big")
+                pos = extension_data_lenth + 2
+                extension_data = mv[2:pos]
+                assert (
+                    extension_data.nbytes == extension_data_lenth
+                ), "extension length does not match"
+                mv = mv[pos:]
+            else:
+                extension_data = b""
+            et = cls.from_value(type_value)
+            extensions[et] = et.unpack(extension_data)
+        return extensions
+
+    def unpack(self, data: memoryview):
+        if self == ExtensionType.supported_versions:
+            return bytes(data)
+        if self == ExtensionType.key_share:
+            return NamedGroup.unpack_from(data)
+        if self == ExtensionType.server_name:
+            return data.decode()
+        if self == ExtensionType.pre_shared_key:
+            assert len(data) == 2, "invalid length"
+            return int.from_bytes(data, "big")
+        if self == ExtensionType.early_data:
+            if data:
+                assert len(data) == 4, "expect uint32 max_early_data_size"
+                return int.from_bytes(data, "big")
+            return
+        raise Exception("not support yet")
+
+
+class ContentType(UInt8Enum):
+    invalid = 0
+    change_cipher_spec = 20
+    alert = 21
+    handshake = 22
+    application_data = 23
+
+    def tls_plaintext(self, data: bytes) -> bytes:
+        assert len(data) > 0, "need data"
+        data = memoryview(data)
+        fragments = []
+        while True:
+            if len(data) > 16384:
+                fragments.append(data[:16384])
+                data = data[16384:]
+            else:
+                fragments.append(data)
+                break
+
+        return b"".join(
+            (
+                self.pack()
+                + (
+                    b"\x03\x01"
+                    if i == 0 and self is ContentType.handshake
+                    else b"\x03\x03"
+                )
+                + pack_int(2, fragment)
+                for i, fragment in enumerate(fragments)
+            )
+        )
+
+    def tls_inner_plaintext(self, content: bytes) -> bytes:
+        return content + self.pack() + (b"\x00" * random.randint(0, 10))
+
+
+class AlertLevel(UInt8Enum):
+    warning = 1
+    fatal = 2
+
+
+class AlertDescription(UInt8Enum):
+    close_notify = 0
+    unexpected_message = 10
+    bad_record_mac = 20
+    record_overflow = 22
+    handshake_failure = 40
+    bad_certificate = 42
+    unsupported_certificate = 43
+    certificate_revoked = 44
+    certificate_expired = 45
+    certificate_unknown = 46
+    illegal_parameter = 47
+    unknown_ca = 48
+    access_denied = 49
+    decode_error = 50
+    decrypt_error = 51
+    protocol_version = 70
+    insufficient_security = 71
+    internal_error = 80
+    inappropriate_fallback = 86
+    user_canceled = 90
+    missing_extension = 109
+    unsupported_extension = 110
+    unrecognized_name = 112
+    bad_certificate_status_response = 113
+    unknown_psk_identity = 115
+    certificate_required = 116
+    no_application_protocol = 120
+
+
+class SignatureScheme(UInt16Enum):
+    # RSASSA-PKCS1-v1_5 algorithms
+    rsa_pkcs1_sha256 = 0x0401
+    rsa_pkcs1_sha384 = 0x0501
+    rsa_pkcs1_sha512 = 0x0601
+    # ECDSA algorithms
+    ecdsa_secp256r1_sha256 = 0x0403
+    ecdsa_secp384r1_sha384 = 0x0503
+    ecdsa_secp521r1_sha512 = 0x0603
+    # RSASSA-PSS algorithms with public key OID rsaEncryption
+    rsa_pss_rsae_sha256 = 0x0804
+    rsa_pss_rsae_sha384 = 0x0805
+    rsa_pss_rsae_sha512 = 0x0806
+    # EdDSA algorithms
+    ed25519 = 0x0807
+    ed448 = 0x0808
+    # RSASSA-PSS algorithms with public key OID RSASSA-PSS
+    rsa_pss_pss_sha256 = 0x0809
+    rsa_pss_pss_sha384 = 0x080a
+    rsa_pss_pss_sha512 = 0x080b
+    # Legacy algorithms
+    rsa_pkcs1_sha1 = 0x0201
+    ecdsa_sha1 = 0x0203
+    # Reserved Code Points
+    # private_use(0xFE00..0xFFFF)
+
+
+dh_parameters = {
+    # "ffdhe2048": dh.generate_parameters(generator=2, key_size=2048, backend=backend),
+    # "ffdhe3072": dh.generate_parameters(generator=2, key_size=3072, backend=backend),
+    # "ffdhe4096": dh.generate_parameters(generator=2, key_size=4096, backend=backend),
+    # "ffdhe8192": dh.generate_parameters(generator=2, key_size=8192, backend=backend),
+}
+
+
+class NamedGroup(UInt16Enum):
+    # Elliptic Curve Groups (ECDHE)
+    secp256r1 = 0x0017
+    secp384r1 = 0x0018
+    secp521r1 = 0x0019
+    x25519 = 0x001D
+    x448 = 0x001E
+    # Finite Field Groups (DHE)
+    ffdhe2048 = 0x0100
+    ffdhe3072 = 0x0101
+    ffdhe4096 = 0x0102
+    ffdhe6144 = 0x0103
+    ffdhe8192 = 0x0104
+    # Reserved Code Points
+    # ffdhe_private_use(0x01FC..0x01FF)
+    # ecdhe_private_use(0xFE00..0xFEFF)
+
+    # def dh_key_share_entry(self):
+    #     private_key = dh_parameters[self.name].generate_private_key()
+    #     peer_public_key = private_key.public_key()
+    #     opaque = peer_public_key.public_bytes(
+    #         Encoding.DER, PublicFormat.SubjectPublicKeyInfo
+    #     )
+    #     return private_key, self.pack() + pack_int(2, opaque)
+
+    @classmethod
+    def new_x25519(cls):
+        private_key = PrivateKey.generate()
+        key_exchange = bytes(private_key.public_key)
+        return private_key, cls.x25519.pack() + pack_int(2, key_exchange)
+
+    @classmethod
+    def unpack_from(cls, data: memoryview):
+        value = int.from_bytes(data[:2], "big")
+        group_type = cls.from_value(value)
+        length = int.from_bytes(data[2:4], "big")
+        assert length == len(data[4:]), "group length does not match"
+        key_exchange = bytes(data[4:])
+        return KeyShareEntry(group_type, key_exchange)
+
+
+@dataclass
+class KeyShareEntry:
+    group: NamedGroup
+    key_exchange: bytes
+    __slots__ = ("group", "key_exchange")
+
+    def pack(self):
+        return self.group.pack() + pack_int(2, self.key_exchange)
+
+
+class CertificateType(UInt8Enum):
+    X509 = 0
+    RawPublicKey = 2
+
+
+@dataclass
+class CertificateEntry:
+    cert_type: CertificateType
+    cert_data: bytes
+    extensions: dict
+    __slots__ = ("cert_type", "cert_data", "extensions")
+
+    @classmethod
+    def unpack_from(cls, data: memoryview):
+        certificate_request_context_len = data[0]
+        certificate_request_context = data[1 : 1 + certificate_request_context_len]
+        certificate_request_context
+        data = data[1 + certificate_request_context_len :]
+        certificate_list_len = int.from_bytes(data[:3], "big")
+        certificate_list = data[3:]
+        assert certificate_list_len == len(
+            certificate_list
+        ), "Certificate length does not match"
+        certs = []
+        while certificate_list:
+            cert_data_len = int.from_bytes(certificate_list[:3], "big")
+            cert_data = certificate_list[3 : 3 + cert_data_len]
+            cert_type = 0
+            if cert_type == CertificateType.X509:
+                # x = x509.load_der_x509_certificate(data=cert_data, backend=backend)
+                # x = load_certificate(FILETYPE_ASN1, cert_data)
+                key = RSA.import_key(cert_data)
+                key
+            certificate_list = certificate_list[3 + cert_data_len :]
+            extensions_len = int.from_bytes(certificate_list[:2], "big")
+            assert extensions_len <= len(
+                certificate_list[2:]
+            ), "extensions length does not match"
+            extensions = ExtensionType.unpack_from(
+                certificate_list[2 : 2 + extensions_len]
+            )
+            certificate_list = certificate_list[2 + extensions_len :]
+            certs.append(cls(cert_type, cert_data, extensions))
+        return certs
+
+
+class KeyUpdateRequest(UInt8Enum):
+    update_not_requested = 0
+    update_requested = 1
+
+
+class PskKeyExchangeMode(UInt8Enum):
+    psk_ke = 0
+    psk_dhe_ke = 1
+
+    def extension(self):
+        return ExtensionType.psk_key_exchange_modes.pack_data(pack_int(1, self.pack()))
+
+    @classmethod
+    def both_extensions(cls):
+        return ExtensionType.psk_key_exchange_modes.pack_data(pack_int(1, b"\x00\x01"))
+
+
+class CipherSuite(UInt16Enum):
+    TLS_AES_128_GCM_SHA256 = 0x1301
+    TLS_AES_256_GCM_SHA384 = 0x1302
+    TLS_CHACHA20_POLY1305_SHA256 = 0x1303
+    TLS_AES_128_CCM_SHA256 = 0x1304
+    TLS_AES_128_CCM_8_SHA256 = 0x1305
+
+    @classmethod
+    def all(cls) -> set:
+        if not hasattr(cls, "_all"):
+            cls._all = {suite.pack() for suite in cls}
+        return cls._all
+
+    @classmethod
+    def select(cls, data):
+        data = memoryview(data)
+        for i in (0, data.nbytes, 2):
+            if data[i : i + 2] in cls.all():
+                return data[i : i + 2].tobytes()
+
+    @classmethod
+    def get_cipher(cls, data):
+        value = int.from_bytes(data, "big")
+        if value == cls.TLS_AES_128_GCM_SHA256:
+            return ciphers.TLS_AES_128_GCM_SHA256
+        elif value == cls.TLS_AES_256_GCM_SHA384:
+            return ciphers.TLS_AES_256_GCM_SHA384
+        elif value == cls.TLS_AES_128_CCM_SHA256:
+            return ciphers.TLS_AES_128_CCM_SHA256
+        elif value == cls.TLS_AES_128_CCM_8_SHA256:
+            return ciphers.TLS_AES_128_CCM_8_SHA256
+        elif value == cls.TLS_CHACHA20_POLY1305_SHA256:
+            return ciphers.TLS_CHACHA20_POLY1305_SHA256
+        else:
+            raise Exception("bad cipher suite")
+
+    @classmethod
+    def pack_all(cls):
+        return pack_all(
+            2,
+            [
+                cls.TLS_CHACHA20_POLY1305_SHA256,
+                cls.TLS_AES_128_GCM_SHA256,
+                cls.TLS_AES_256_GCM_SHA384,
+                cls.TLS_AES_128_CCM_SHA256,
+                cls.TLS_AES_128_CCM_8_SHA256,
+            ],
+        )
+
+
+class NameType(UInt8Enum):
+    host_name = 0
+
+    def pack_data(self, data: bytes) -> bytes:
+        return self.pack() + pack_int(2, data)
+
+
+class Const:
+    all_signature_algorithms = ExtensionType.signature_algorithms.pack_data(
+        pack_all(2, SignatureScheme)
+    )
+    all_supported_groups = ExtensionType.supported_groups.pack_data(
+        pack_all(2, [NamedGroup.x25519])
+    )
+    psk_ke_extension = PskKeyExchangeMode.psk_ke.extension()
+    psk_dhe_ke_extension = PskKeyExchangeMode.psk_dhe_ke.extension()
+    psk_both_extensions = PskKeyExchangeMode.both_extensions()
+
+
+def server_hello_pack(legacy_session_id_echo, cipher_suite, extensions) -> bytes:
+    legacy_version = b"\x03\x03"
+    msg = b"".join(
+        (
+            legacy_version,
+            os.urandom(32),
+            pack_int(1, legacy_session_id_echo),
+            cipher_suite.pack(),
+            b"\x00",
+        )
+    )
+    return ContentType.handshake.tls_plaintext(
+        HandshakeType.server_hello.pack_data(msg)
+    )
+
+
+def client_hello_key_share_extension(*key_share_entries):
+    return ExtensionType.key_share.pack_data(pack_list(2, key_share_entries))
+
+
+@dataclass
+class PskIdentity:
+    identity: bytes
+    obfuscated_ticket_age: int
+    binder_len: int
+
+
+def client_pre_shared_key_extension(
+    psk_identities: typing.Iterable
+) -> typing.Tuple[bytes, int]:
+    binders = pack_psk_binder_entries((i.binder_len * b"\x00" for i in psk_identities))
+    return (
+        ExtensionType.pre_shared_key.pack_data(
+            pack_list(
+                2,
+                (
+                    pack_int(2, i.identity) + i.obfuscated_ticket_age.to_bytes(4, "big")
+                    for i in psk_identities
+                ),
+            )
+            + binders
+        ),
+        len(binders),
+    )
+
+
+def pack_psk_binder_entries(binder_list: typing.Iterable[bytes]) -> bytes:
+    return pack_list(2, (pack_int(1, binder) for binder in binder_list))
+
+
+def unpack_certificate_verify(mv: memoryview):
+    algorithm = int.from_bytes(mv[:2], "big")
+    scheme = SignatureScheme.from_value(algorithm)
+    signature_len = int.from_bytes(mv[2:4], "big")
+    signature = mv[4 : 4 + signature_len]
+    return SimpleNamespace(algorithm=scheme, signature=signature)
+
+
+def unpack_new_session_ticket(mv: memoryview):
+    lifetime, age_add, nonce_len = struct.unpack_from("!IIB", mv)
+    mv = mv[9:]
+    nonce = mv[:nonce_len]
+    mv = mv[nonce_len:]
+    ticket_len = int.from_bytes(mv[:2], "big")
+    mv = mv[2:]
+    ticket = bytes(mv[:ticket_len])
+    mv = mv[ticket_len:]
+    ext_len = int.from_bytes(mv[:2], "big")
+    mv = mv[2:]
+    assert ext_len == len(mv), "extension length does not match"
+    extensions = ExtensionType.unpack_from(mv)
+    return NewSessionTicket(
+        lifetime=lifetime,
+        age_add=age_add,
+        nonce=nonce,
+        ticket=ticket,
+        max_early_data_size=extensions.get(ExtensionType.early_data),
+    )
+
+
+@dataclass
+class NewSessionTicket:
+    lifetime: int
+    age_add: int
+    nonce: bytes
+    ticket: bytes
+    max_early_data_size: int
+
+    def __post_init__(self):
+        self.outdated_time = time.time() + min(self.lifetime, MAX_LIFETIME)
+        self.obfuscated_ticket_age = ((self.lifetime * 1000) + self.age_add) % AGE_MOD
+
+    def is_outdated(self):
+        return time.time() >= self.outdated_time
+
+    def to_psk_identity(self, binder_len: int):
+        return PskIdentity(self.ticket, self.obfuscated_ticket_age, binder_len)
+
+
+class TLSClientSession:
+    def __init__(
+        self,
+        private_key: bytes ,
+        key_share_entry: bytes ,
+        client_hello_data: memoryview
+    ):
+        self.private_key, key_share_entry = private_key, key_share_entry
+        self.handshake_context = client_hello_data
+        self.server_finished = False
+
+
+
+    def unpack_server_hello(self, mv: memoryview):
+        assert mv[:2] == b"\x03\x03", "version must be 0x0303"
+        random = bytes(mv[2:34])
+        legacy_session_id_echo_length = mv[34]
+        legacy_session_id_echo = bytes(mv[35 : 35 + legacy_session_id_echo_length])
+        mv = mv[35 + legacy_session_id_echo_length :]
+        cipher_suite = CipherSuite.get_cipher(mv[:2])
+        assert mv[2] == 0, "legacy_compression_method should be 0"
+        extension_length = int.from_bytes(mv[3:5], "big")
+        extensions_mv = mv[5:]
+        assert (
+            extensions_mv.nbytes == extension_length
+        ), "extensions length does not match"
+        extensions = ExtensionType.unpack_from(extensions_mv)
+        return SimpleNamespace(
+            handshake_type=HandshakeType.server_hello,
+            random=random,
+            legacy_session_id_echo=legacy_session_id_echo,
+            cipher_suite=cipher_suite,
+            extensions=extensions,
+        )
+
+    def unpack_handshake(self, mv: memoryview):
+        handshake_type = mv[0]
+        length = int.from_bytes(mv[1:4], "big")
+        assert len(mv[4:]) == length, f"handshake length does not match"
+        handshake_data = mv[4:]
+        if handshake_type == HandshakeType.server_hello:
+            self.handshake_context.extend(mv)
+            return self.unpack_server_hello(handshake_data)
+        elif handshake_type == HandshakeType.encrypted_extensions:
+            self.handshake_context.extend(mv)
+            ext_len = int.from_bytes(handshake_data[:2], "big")
+            handshake_data = handshake_data[2:]
+            assert (
+                len(handshake_data) == ext_len
+            ), "encrypted extensions length does not match"
+            self.encrypted_extensions = ExtensionType.unpack_from(handshake_data)
+        elif handshake_type == HandshakeType.certificate_request:
+            self.handshake_context.extend(mv)
+        elif handshake_type == HandshakeType.certificate:
+            self.handshake_context.extend(mv)
+            self.certificate_entry = CertificateEntry.unpack_from(handshake_data)
+        elif handshake_type == HandshakeType.certificate_verify:
+            self.handshake_context.extend(mv)
+            self.certificate_verify = unpack_certificate_verify(handshake_data)
+            print(self.certificate_verify)
+        elif handshake_type == HandshakeType.finished:
+            assert handshake_data == self.peer_cipher.verify_data(
+                self.handshake_context
+            ), "server handshake finished does not match"
+            self.handshake_context.extend(mv)
+            self.server_finished = True
+        elif handshake_type == HandshakeType.new_session_ticket:
+            self.session_tickets.append(unpack_new_session_ticket(handshake_data))
+        else:
+            raise Exception(f"unknown handshake type {handshake_type}")
+
+    def tls_response(self, mv: memoryview):
+        head = mv[:5]
+        assert head[1:3] == b"\x03\x03", f"bad legacy_record_version {head[1:3]}"
+        length = int.from_bytes(head[3:], "big")
+        if (head[0] == ContentType.application_data and length > (16384 + 256)) or (
+            head[0] != ContentType.application_data and length > 16384
+        ):
+            raise Alert(AlertLevel.fatal, AlertDescription.record_overflow)
+        content = mv[5:]
+        if head[0] == ContentType.alert:
+            level = AlertLevel.from_value(content[0])
+            description = AlertDescription.from_value(content[1])
+            raise Alert(level, description)
+        elif head[0] == ContentType.handshake:
+            self.peer_handshake = self.unpack_handshake(content)
+            assert (
+                self.peer_handshake.handshake_type == HandshakeType.server_hello
+            ), "expect server hello"
+
+            peer_pk = self.peer_handshake.extensions[
+                ExtensionType.key_share
+            ].key_exchange
+
+            shared_key = crypto_scalarmult(bytes(self.private_key), peer_pk)
+
+            TLSCipher = self.peer_handshake.cipher_suite
+            self.TLSCipher = TLSCipher
+            key_scheduler = TLSCipher.tls_hash.scheduler(shared_key, None)
+            self.key_scheduler = key_scheduler
+            secret = key_scheduler.server_handshake_traffic_secret(
+                self.handshake_context
+            )
+            # server handshake cipher
+            self.peer_cipher = TLSCipher(secret)
+            client_handshake_traffic_secret = key_scheduler.client_handshake_traffic_secret(
+                self.handshake_context
+            )
+            print("\n\tpeer_pk\t",bytes(peer_pk).hex())
+            print("\n\tprivate_key\t",bytes(self.private_key).hex() )
+            print("\n\tshared_key\t",bytes(shared_key).hex() )
+            print("\n\tself.key_scheduler.\t",self.key_scheduler)
+            print("\n\tself.peer_cipher\t",self.peer_cipher)
+            print("\n\tself.TLSCipher\t",self.TLSCipher)
+            print("\n\tsecret\t",bytes(secret).hex())
+            print("\n\tkey\t",self.peer_cipher.key )
+            print("\n\tIV\t",self.peer_cipher.iv )
+            print("\n",)
+
+        elif head[0] == ContentType.application_data:
+            plaintext = self.peer_cipher.decrypt(content, head).rstrip(b"\x00")
+            content_type = ContentType.from_value(plaintext[-1])
+            if content_type == ContentType.handshake:
+                self.unpack_handshake(plaintext[:-1])
+                if self.server_finished:
+
+                    # client handshake cipher
+                    cipher = TLSCipher(client_handshake_traffic_secret)
+                    client_finished = cipher.verify_data(self.handshake_context)
+                    client_finished_data = HandshakeType.finished.pack_data(
+                        client_finished
+                    )
+                    inner_plaintext = ContentType.handshake.tls_inner_plaintext(
+                        client_finished_data
+                    )
+                    record = cipher.tls_ciphertext(inner_plaintext)
+                    change_cipher_spec = ContentType.change_cipher_spec.tls_plaintext(
+                        b"\x01"
+                    )
+                    # parser.write(change_cipher_spec + record)
+                    # server application cipher
+                    server_secret = key_scheduler.server_application_traffic_secret_0(
+                        self.handshake_context
+                    )
+                    self.peer_cipher = TLSCipher(server_secret)
+                    self.server_finished = False
+
+                    # client application cipher
+                    client_secret = key_scheduler.client_application_traffic_secret_0(
+                        self.handshake_context
+                    )
+                    self.cipher = TLSCipher(client_secret)
+                    self.handshake_context.extend(client_finished_data)
+            elif content_type == ContentType.application_data:
+                self.data_callback(plaintext[:-1])
+            elif content_type == ContentType.alert:
+                level = AlertLevel.from_value(plaintext[0])
+                description = AlertDescription.from_value(plaintext[1])
+                raise Alert(level, description)
+            elif content_type == ContentType.invalid:
+                raise Exception("invalid content type")
+            else:
+                raise Exception(f"unexpected content type {content_type}")
+        elif head[0] == ContentType.change_cipher_spec:
+            assert content == b"\x01", "change_cipher should be 0x01"
+        else:
+            raise Exception(f"Unknown content type: {head[0]}")
+
+    def pack_client_hello(self):
+        data = ContentType.handshake.tls_plaintext(self.client_hello_data)
+        return data 
+
+    def pack_application_data(self, payload: bytes) -> bytes:
+        inner_plaintext = ContentType.application_data.tls_inner_plaintext(payload)
+        return self.cipher.tls_ciphertext(inner_plaintext)
+
+    def pack_alert(self, description: AlertDescription, level: AlertLevel) -> bytes:
+        payload = level.pack() + description.pack()
+        if self.cipher:
+            inner_plaintext = ContentType.alert.tls_inner_plaintext(payload)
+            return self.cipher.tls_ciphertext(inner_plaintext)
+        else:
+            return ContentType.alert.tls_plaintext(payload)
+
+    def pack_warning(self, description: AlertDescription) -> bytes:
+        return self.pack_alert(description, AlertLevel.warning)
+
+    def pack_fatal(self, description: AlertDescription) -> bytes:
+        return self.pack_alert(description, AlertLevel.fatal)
+
+    def pack_close(self) -> bytes:
+        return self.pack_warning(AlertDescription.close_notify)
+
+    def pack_canceled(self) -> bytes:
+        return self.pack_warning(AlertDescription.user_canceled)

+ 137 - 0
tcp/ciphers.py

@@ -0,0 +1,137 @@
+import abc
+import nacl.bindings
+from Cryptodome.Cipher import AES
+from .key_schedule import tls_sha256, tls_sha384
+
+
+class TLS_AEAD_Cipher(abc.ABC):
+    NONCE_LEN = 12
+
+    @property
+    @abc.abstractmethod
+    def KEY_LEN(self):
+        ""
+
+    @property
+    @abc.abstractmethod
+    def MAC_LEN(self):
+        ""
+
+    @property
+    @abc.abstractmethod
+    def tls_hash(self):
+        ""
+
+    @abc.abstractmethod
+    def cipher(self):
+        ""
+
+    def __init__(self, secret):
+        self.reset(secret)
+
+    def reset(self, secret):
+        self.secret = secret
+        self.key = self.tls_hash.derive_key(self.secret, self.KEY_LEN)
+        self.iv = int.from_bytes(
+            self.tls_hash.derive_iv(self.secret, self.NONCE_LEN), "big"
+        )
+        self.sequence_number = 0
+
+    def next_application_traffic_secret(self):
+        return self.tls_hash.hkdf_expand_label(
+            self.secret, b"traffic upd", b"", self.tls_hash.hash_len
+        )
+
+    def update_traffic_secret(self):
+        self.reset(self.next_application_traffic_secret())
+
+    def verify_data(self, msg):
+        return self.tls_hash.verify_data(self.secret, msg)
+
+    def get_nonce(self):
+        nonce = self.sequence_number ^ self.iv
+        nonce = nonce.to_bytes(self.NONCE_LEN, "big")
+        self.sequence_number += 1
+        return nonce
+
+    def decrypt(self, ciphertext, associated_data):
+        cipher = self.cipher()
+        cipher.update(associated_data)
+        return cipher.decrypt_and_verify(
+            ciphertext[: -self.MAC_LEN], ciphertext[-self.MAC_LEN :]
+        )
+
+    def encrypt(self, plaintext, associated_data):
+        cipher = self.cipher()
+        cipher.update(associated_data)
+        ciphertext, tag = cipher.encrypt_and_digest(plaintext)
+        return ciphertext + tag
+
+    def tls_ciphertext(self, plaintext):
+        head = b"\x17\x03\x03" + (len(plaintext) + self.MAC_LEN).to_bytes(2, "big")
+        return head + self.encrypt(plaintext, head)
+
+
+class TLS_CHACHA20_POLY1305_SHA256(TLS_AEAD_Cipher):
+    KEY_LEN = 32
+    MAC_LEN = 16
+    tls_hash = tls_sha256
+
+    def cipher(self):
+        ""
+
+    def decrypt(self, ciphertext, associated_data):
+        nonce = self.get_nonce()
+        return nacl.bindings.crypto_aead_chacha20poly1305_ietf_decrypt(
+            bytes(ciphertext), associated_data, nonce, self.key
+        )
+
+    def encrypt(self, plaintext, associated_data):
+        nonce = self.get_nonce()
+        return nacl.bindings.crypto_aead_chacha20poly1305_ietf_encrypt(
+            bytes(plaintext), associated_data, nonce, self.key
+        )
+
+
+class TLS_AES_128_GCM_SHA256(TLS_AEAD_Cipher):
+    KEY_LEN = 16
+    MAC_LEN = 16
+    tls_hash = tls_sha256
+
+    def cipher(self):
+        return AES.new(
+            self.key, AES.MODE_GCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
+        )
+
+
+class TLS_AES_256_GCM_SHA384(TLS_AEAD_Cipher):
+    KEY_LEN = 32
+    MAC_LEN = 16
+    tls_hash = tls_sha384
+
+    def cipher(self):
+        return AES.new(
+            self.key, AES.MODE_GCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
+        )
+
+
+class TLS_AES_128_CCM_SHA256(TLS_AEAD_Cipher):
+    KEY_LEN = 16
+    MAC_LEN = 16
+    tls_hash = tls_sha256
+
+    def cipher(self):
+        return AES.new(
+            self.key, AES.MODE_CCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
+        )
+
+
+class TLS_AES_128_CCM_8_SHA256(TLS_AEAD_Cipher):
+    tls_hash = tls_sha256
+    KEY_LEN = 16
+    MAC_LEN = 8
+
+    def cipher(self):
+        return AES.new(
+            self.key, AES.MODE_CCM, nonce=self.get_nonce(), mac_len=self.MAC_LEN
+        )

+ 145 - 0
tcp/key_schedule.py

@@ -0,0 +1,145 @@
+import hmac
+import hkdf
+import hashlib
+
+
+class TlsHash:
+    def __init__(self, hashmod=hashlib.sha256):
+        self.hashmod = hashmod
+        self.hash_len = hashmod().digest_size
+
+    def hkdf_extract(self, salt: bytes, input_key_material: bytes) -> bytes:
+        if input_key_material is None:
+            input_key_material = b"\x00" * self.hash_len
+        return hkdf.hkdf_extract(salt, input_key_material, self.hashmod)
+
+    def hkdf_label(self, label: bytes, context: bytes, length: int) -> bytes:
+        label = b"tls13 " + label
+        return (
+            length.to_bytes(2, "big")
+            + len(label).to_bytes(1, "big")
+            + label
+            + len(context).to_bytes(1, "big")
+            + context
+        )
+
+    def hkdf_expand_label(
+        self, secret: bytes, label: bytes, context: bytes, length: int
+    ) -> bytes:
+        hkdf_label = self.hkdf_label(label, context, length)
+        return hkdf.hkdf_expand(secret, hkdf_label, length, self.hashmod)
+
+    def derive_secret(self, secret: bytes, label: bytes, messages) -> bytes:
+        if type(messages) == list:
+            messages = b"".join(messages)
+        return self.hkdf_expand_label(
+            secret, label, self.hashmod(messages).digest(), self.hash_len
+        )
+
+    def transcript_hash(self, *msgs):
+        return self.hashmod(b"".join(msgs)).digest()
+
+    # def transcript_hash(self, client_hello_data, *others):
+    #     digest = self.hashmod(client_hello_data).digest()
+    #     return self.hashmod(
+    #         b"\xfe\x00\x00"
+    #         + self.hash_len.to_bytes(1, "big")
+    #         + digest
+    #         + b"".join(others)
+    #     ).digest()
+
+    def derive_key(self, secret: bytes, key_length: int) -> bytes:
+        return self.hkdf_expand_label(secret, b"key", b"", key_length)
+
+    def derive_iv(self, secret: bytes, iv_length: int) -> bytes:
+        return self.hkdf_expand_label(secret, b"iv", b"", iv_length)
+
+    def finished_key(self, base_key: bytes) -> bytes:
+        return self.hkdf_expand_label(base_key, b"finished", b"", self.hash_len)
+
+    def verify_data(self, secret: bytes, msg: bytes) -> bytes:
+        return hmac.new(
+            self.finished_key(secret), self.transcript_hash(msg), self.hashmod
+        ).digest()
+
+    def scheduler(self, ecdhe: bytes, psk: bytes = None):
+        return KeyScheduler(self, ecdhe, psk)
+
+
+tls_sha256 = TlsHash()
+tls_sha384 = TlsHash(hashlib.sha384)
+
+
+class PSKWrapper:
+    def __init__(self, psk: bytes, tls_hash=tls_sha256, is_ext: bool = True):
+        self.tls_hash = tls_hash
+        self.early_secret = self.tls_hash.hkdf_extract(None, psk)
+        self.is_ext = is_ext
+
+    def ext_binder_key(self) -> bytes:
+        return self.tls_hash.derive_secret(self.early_secret, b"ext binder", b"")
+
+    def res_binder_key(self) -> bytes:
+        return self.tls_hash.derive_secret(self.early_secret, b"res binder", b"")
+
+    def binder_key(self) -> bytes:
+        return self.ext_binder_key() if self.is_ext else self.res_binder_key()
+
+    def client_early_traffic_secret(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(self.early_secret, b"c e traffic", messages)
+
+    def early_exporter_master_secret(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(self.early_secret, b"e exp master", messages)
+
+
+class KeyScheduler:
+    def __init__(self, tls_hash, ecdhe: bytes, psk: bytes = None):
+        self.tls_hash = tls_hash
+        self.ecdhe = ecdhe
+
+        self.early_secret = self.tls_hash.hkdf_extract(None, psk)
+        self.first_salt = self.tls_hash.derive_secret(
+            self.early_secret, b"derived", b""
+        )
+        self.handshake_secret = self.tls_hash.hkdf_extract(self.first_salt, self.ecdhe)
+        self.second_salt = self.tls_hash.derive_secret(
+            self.handshake_secret, b"derived", b""
+        )
+        self.master_secret = self.tls_hash.hkdf_extract(self.second_salt, None)
+
+    def client_handshake_traffic_secret(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(
+            self.handshake_secret, b"c hs traffic", messages
+        )
+
+    def server_handshake_traffic_secret(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(
+            self.handshake_secret, b"s hs traffic", messages
+        )
+
+    def client_application_traffic_secret_0(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(
+            self.master_secret, b"c ap traffic", messages
+        )
+
+    def server_application_traffic_secret_0(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(
+            self.master_secret, b"s ap traffic", messages
+        )
+
+    def application_traffic_secret_N(self, last_secret) -> bytes:
+        return self.tls_hash.hkdf_expand_label(
+            last_secret, b"traffic upd", b"", self.tls_hash.hash_len
+        )
+
+    def exporter_master_secret(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(self.master_secret, b"exp master", messages)
+
+    def resumption_master_secret(self, messages) -> bytes:
+        return self.tls_hash.derive_secret(self.master_secret, b"res master", messages)
+
+    def resumption_psk(self, messages, ticket_nonce: bytes) -> bytes:
+        secret = self.resumption_master_secret(messages)
+        return self.tls_hash.hkdf_expand_label(
+            secret, b"resumption", ticket_nonce, self.tls_hash.hash_len
+        )

+ 13 - 0
tcp/utils.py

@@ -0,0 +1,13 @@
+import typing
+
+
+def pack_int(length: int, data: bytes) -> bytes:
+    return len(data).to_bytes(length, "big") + data
+
+
+def pack_list(length: int, iterable: typing.Iterable[bytes]) -> bytes:
+    return pack_int(length, b"".join(data for data in iterable))
+
+
+def pack_all(length: int, iterable: typing.Iterable) -> bytes:
+    return pack_int(length, b"".join(obj.pack() for obj in iterable))

File diff suppressed because it is too large
+ 9 - 0
test.py


+ 0 - 0
tls/aes_gcm.py


+ 1 - 0
tls/pycryptodome

@@ -0,0 +1 @@
+Subproject commit 4fbf0c3229e3b0257a552074ac8992930454af8c

+ 0 - 0
user/__init__.py


+ 0 - 24
user/broadcast.py

@@ -1,24 +0,0 @@
-
-import socket
-import threading
-
-        
-class Broadcast():
-
-    def __init__(self,broadcast,  broadcastPort): 
-        msg = bytes("Hello, Who can do somthing for me? Tnx",'utf-8')
-        self.onlineOracles=[]
-        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
-        self.sock.sendto(msg,(broadcast, broadcastPort))
-        t1 = threading.Thread(target=self.listen)
-        t1.start()
-        print("Broadcast  sended")
-
-
-
-    def listen(self):
-        while True:
-            msg, addr = self.sock.recvfrom(32)
-            self.onlineOracles.append((addr[0],msg.decode("utf-8")))
-            # print("message",msg," from ",addr)

+ 41 - 49
user/user.py

@@ -1,53 +1,45 @@
 
 
-from .broadcast import Broadcast
-from src.socketClient import Socket
+from connection.broadcast import BroadcastClient
+from connection.socket import SocketClient
 import time
 import time
 import config as cfg 
 import config as cfg 
+from .userParser import UserParser
+
+
+class User():
+    def __init__(self,data, server, broadcast, broadcastPort):
+        print("user")
+        self.onlineOracles = []
+        self.id = "PADRA"
+        self.parser = UserParser(self) 
+        self.b = BroadcastClient(broadcast=broadcast,
+        broadcastPort=broadcastPort,parser=self.parser,id=self.id)
+
+    def run(self):
+        self.b.send(self.parser.requestOracleBroadcast(self.id),self.b.addr)
+        
+        while(len(self.onlineOracles) < cfg.numberOfOracles):
+            print("\tWe need min  ",cfg.numberOfOracles," Oracles. Waiting for mor Oracle. we have now ",len(self.onlineOracles)," online Oracles")
+            time.sleep(.5)
+
+        print("\33[31m now we have min ",cfg.numberOfOracles,"Oracles. List of All Online Oracles ->\n",self.onlineOracles,"\n\033[0m")
+
+        worker = []
+        
+        # Socket creation
+        for i in range(cfg.numberOfOracles):
+            worker.append(SocketClient("127.0.0.1",int(self.onlineOracles[i][1]),self.parser,None))
+        
+        #  send rule to each oracle
+        for i in range(cfg.numberOfOracles):
+            data = self.parser.socketConnecting(i)
+            worker[i].id = i
+            worker[i].send(data)
+
+
+        time.sleep(1)
+
+        worker[0].send(self.parser.oracleInitialConnector("www.google.com",worker[1].Host,worker[2].Host))
+        worker[1].send(self.parser.oracleInitialCryptor((worker[0].Host,worker[0].port+1),"www.google.com"))
+        worker[2].send(self.parser.oracleInitialBearer((worker[0].Host,worker[0].port+1),"Masalan ina data hastand"))
 
 
-
-
-def run(data, server, broadcast, broadcastPort):
-
-    b = Broadcast(broadcast=broadcast,broadcastPort=broadcastPort)
-
-    while(len(b.onlineOracles) < cfg.numberOfOracles):
-        print("\tWe need min  ",cfg.numberOfOracles," Oracles. Waiting for mor Oracle. we have now ",len(b.onlineOracles)," online Oracles")
-        time.sleep(.5)
-
-
-    print("\nnow we have min ",cfg.numberOfOracles,"Oracles. List of All Online Oracles ->\n \t\n",b.onlineOracles,"\n\n")
-    worker = []
-    for i in range(cfg.numberOfOracles):
-        print(i,b.onlineOracles[i])
-        worker.append(Socket("127.0.0.1",int(b.onlineOracles[i][1]),{"type":"user","oracle":i})) #_[0] 
-
-    print("Done",worker)
-    print("\n")
-    time.sleep(1)
-
-    worker[0].toSEND({
-        "type":"init",
-        "id":"test",
-        "connectorIP":"127.0.0.1",
-        "connectorPort":int(worker[0].port)+1,
-        "path":"/", # TODO
-        "server":"smarthome.agio360.com" # TODO
-    })
-    worker[1].toSEND({
-        "type":"init",
-        "id":"test",
-        "connectorIP":"127.0.0.1",
-        "connectorPort":int(worker[0].port)+1,
-        "server":"smarthome.agio360.com"
-
-    })
-    worker[2].toSEND({
-        "type":"init",
-        "id":"test",
-        "connectorIP":"127.0.0.1",
-        "connectorPort":int(worker[0].port)+1,
-        "server":"smarthome.agio360.com",
-        "data":"GET ......"# TODO
-    })
-
-    

+ 73 - 0
user/userParser.py

@@ -0,0 +1,73 @@
+from connection.parser import Parser
+
+
+
+class UserParser(Parser):
+    def __init__(self,user):
+        self.user = user
+        print("createt User Parser")
+
+    def parser(self,data,addr,Connection):
+        try:
+            if data["type"] == "responseUserBroadcast":
+                self.responseUserBroadcast(data,addr) 
+        except:
+            print("\33[41mAn exception occurred DATA\33[0m" )
+
+
+
+# Broadcast Parser
+    def requestOracleBroadcast(self, id):
+        try:
+            data = {}
+            self.add(data,"type","requestOracleBroadcast")
+            self.add(data,"id",id)
+            return self.toSEND(data)
+        except:
+            print("\33[41mAn exception occurred requestOracleBroadcast\33[0m" )
+    
+    def responseUserBroadcast(self, data,addr):
+        try:
+            self.user.onlineOracles.append((addr[0],data["socket"]))
+        except:
+            print("\33[41mAn exception occurred responseUserBroadcast" )
+
+# Socket Parser
+    def socketConnecting(self,oracleNumber):
+        try:
+            data = {}
+            self.add(data,"type","socketConnecting")
+            self.add(data,"oracle",oracleNumber)
+            return self.toSEND(data)
+        except:
+            print("\33[41mAn exception occurred requestOracleBroadcast\33[0m" )
+
+# Socket Parser
+    def oracleInitialConnector(self,server,cryptor,bearer):
+        try:
+            data = {}
+            self.add(data,"type","oracleInitial")
+            self.add(data,"server",server)
+            self.add(data,"bearer",bearer)
+            self.add(data,"cryptor",cryptor)
+            return self.toSEND(data)
+        except:
+            print("\33[41mAn exception occurred oracleInitialConnector\33[0m" )
+    def oracleInitialCryptor(self,connector,server):
+        try:
+            data = {}
+            self.add(data,"type","oracleInitial")
+            self.add(data,"connector",connector)
+            self.add(data,"server",server)
+            return self.toSEND(data)
+        except:
+            print("\33[41mAn exception occurred oracleInitialCryptor\33[0m" )
+    def oracleInitialBearer(self,connector,d):
+        try:
+            data = {}
+            self.add(data,"type","oracleInitial")
+            self.add(data,"connector",connector)
+            self.add(data,"data",d)
+            return self.toSEND(data)
+        except:
+            print("\33[41mAn exception occurred oracleInitialBearer\33[0m" )

Some files were not shown because too many files changed in this diff