Пример #1
0
def challenge():

    #create host object
    host = Host()

    #Create a hash of the node's public key to send to the auth node for identity verification
    keyhash = str(
        base64.b64encode(
            hashlib.sha256(
                rsa_encrypt.get_pub_key().exportKey("PEM")).digest()), 'ascii')

    #creates a payload of the message that identifies that this is a client node that needs to be updated
    payload = "imup" + ":" + str(
        comms_number) + ":" + keyhash + ":" + settings.ID

    #create a socket to communicate with the auth nodes
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                       socket.IPPROTO_UDP) as s:
        s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)

        #Create an empty data and address variable and a socket to recieve the data
        data = ""
        addr = 0
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as us:

            #set a timeout for if there is no auth node ready
            us.settimeout(1)
            us.bind(('0.0.0.0', 55551))

            #send the challenge tag to the auth nodes along with a public key to encrypt their return message with
            s.sendto(
                aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                                  "who?:" + keyhash), ((host.host, host.port)))

            #Recv a number from the auth node to connect to
            try:
                data, addr = us.recvfrom(4096)
            #if it fails return an error
            except socket.timeout:
                us.close()
                return -1

        #Decrypt the recieved message
        data = aes_crypt.aes_dec(rsa_encrypt.get_priv_key(), data)

        #if message is bad return error
        if data == -1 or data == -2:
            return -1

        #convert data to a string to return to the auth nodes along with the instruction payload
        data = str(data, 'ascii')

        #send payload and return expected address
        s.sendto(
            aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                              "you!:" + data + ":" + payload),
            ((host.host, host.port)))
        return addr
Пример #2
0
def register(user, name, keys):
    payload = "usrW" + ":" + rsa_encrypt.get_auth_hash() + ":" + user + ":" + name + ":" + ":".join(keys)
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) as s:
        s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)

        payload = aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), payload)
        s.sendto(payload, (settings.MULT_ADDR, settings.MULT_PORT))
Пример #3
0
def contest_auth(address):

    #open a socket to the reciever
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:

        #send the number
        data = aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                                 str(my_number))
        s.sendto(data, (address, 44443))
Пример #4
0
def challenge(my_number, kind):

    #Creates a host object for use in multicast socket
    host = Host()

    #Creates a multicast socket to communicate with all auth nodes at once
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                       socket.IPPROTO_UDP) as s:
        s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)

        #Creates a socket to recieve a unique number from the first auth node to respond to the contest
        data = ""
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as us:
            #sets a small timeout in case this is the first auth node in the system or the response is delayed
            us.settimeout(1)
            us.bind(('0.0.0.0', 55551))

            #Sends a messafe to the other auth nodes to start a contest
            s.sendto(
                aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                                  "regA:" + str(my_number)),
                ((host.host, host.port)))

            #Recieves encrypted number from auth node
            data, address = us.recvfrom(4096)

        #Decrypt the recieved number using auth private key
        data = aes_crypt.aes_dec(rsa_encrypt.get_priv_key_auth(), data)

        #Check to make sure the message wasnt tampered with, return error if it was
        if data == -1 or data == -2:
            return 1

        #convert the number to a string
        data = str(data, 'ascii')

        #encrypt the number with the auth public key and send it back to the auth nodes, letting them know which one was chosen and what action to preform
        #in this case the asction is provising updates to the auth server
        s.sendto(
            aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                              "you!:" + data + ":" + kind),
            ((host.host, host.port)))
        return address
Пример #5
0
def send_share(share, host):

    #Store the share as a string
    payload = "auth:" + share['id'] + ":" + share['x'] + ":" + share['y']

    #open a socket to the multicast address
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                       socket.IPPROTO_UDP) as s:
        s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)

        #encrypt the share with the auth public key and send it to the multicast address
        s.sendto(aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), payload),
                 ((host.host, host.port)))
Пример #6
0
def db_send(db, num):

    ts = str(time.time())

    comms.database_log([db, num, ts])

    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                       socket.IPPROTO_UDP) as s:
        s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
        s.sendto(
            aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                              "DBUP:" + db + ":" + num + ":" + ts),
            (settings.MULT_ADDR, settings.MULT_PORT))

    comms.send_clients()
Пример #7
0
def broadcast(uid):

    print("Sending New Share to other Auth Nodes")

    #instantiate a shares list
    shares = []

    #For each database
    for i in settings.DBS:

        #Open a connection to the db
        conn = sqlite3.connect(settings.DBdir + i + ".db")
        conn.row_factory = sqlite3.Row
        c = conn.cursor()

        #Grab the provided user's share from this database
        c.execute("SELECT * FROM enc_shares WHERE id = ?", [uid])

        #append the share to the list and close the connection
        shares.append(c.fetchone())
        conn.close()

    #Connect to the secrets database
    conn = sqlite3.connect(settings.DBdir + "secrets.db")
    conn.row_factory = sqlite3.Row
    c = conn.cursor()

    #Grab the user's secret entry
    c.execute("SELECT * FROM secrets WHERE id = ?", [uid])

    #append the secret to the list and close the connection
    shares.append(c.fetchone())
    conn.close()

    #Create an empty string to hold the data
    data = ""

    #For each share
    for i in range(len(shares) - 1):

        #Add no data if this is a delete message
        if shares[i] == None:
            data += "NONE||"

        else:
            #Append the share as a string to the data using the seperator ||
            data += (
                str(shares[i]['id']) + "|" +
                str(shares[i]['share'] + "|" + str(shares[i]['timestamp'])) +
                "||")

    #Append the secrets entry to the data string
    data += (str(shares[-1]['id']) + "|" + str(shares[-1]['name']) + "|" +
             str(shares[-1]['secret']) + "|" + str(shares[-1]['timestamp']))

    #Prepend a hash of the auth private key to the data
    data = (rsa_encrypt.get_auth_hash() + "||" + data)

    #Open a socket to the multicast address
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                       socket.IPPROTO_UDP) as s:
        s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)

        #Set the data header
        data = "here:" + str(my_number) + ":" + data

        #Encrypt the data and send it to the auth nodes
        payload = aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), data)
        s.sendto(payload, (settings.MULT_ADDR, settings.MULT_PORT))
Пример #8
0
def broadcast(uid):

    print("Sending New Share to other Auth Nodes")

    #grab auth hash for use
    auth_hash = rsa_encrypt.get_auth_hash()

    #instantiate a shares list
    shares = []

    #open socket to multicast address
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                       socket.IPPROTO_UDP) as s:
        s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)

        #For each database
        for i in settings.DBS:

            #Open a connection to the db
            conn = sqlite3.connect(settings.DBdir + i + ".db")
            conn.row_factory = sqlite3.Row
            c = conn.cursor()

            #Grab the provided user's share from this database
            c.execute("SELECT * FROM enc_shares WHERE id = ?", [uid])

            #append the share to the list and close the connection
            shares.append(c.fetchone())
            conn.close()

        #Connect to the secrets database
        conn = sqlite3.connect(settings.DBdir + "secrets.db")
        conn.row_factory = sqlite3.Row
        c = conn.cursor()

        #Grab the user's secret entry
        c.execute("SELECT * FROM secrets WHERE id = ?", [uid])

        #append the secret to the list and close the connection
        shares.append(c.fetchone())
        conn.close()

        #For each share
        for i in range(len(shares) - 1):

            #Add no data if this is an empty message
            if shares[i] == None:
                continue

            else:
                #Grab the data from current database as a string
                data = settings.DBS[i] + "||" + str(
                    shares[i]['id']) + "||" + str(
                        shares[i]['share']) + "||" + str(
                            shares[i]['timestamp'])

                #prepend header and send data
                data = "here:" + str(my_number) + ":" + auth_hash + "||" + data
                s.sendto(
                    aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), data),
                    ((settings.MULT_ADDR, settings.MULT_PORT)))

        #grab the data from the secrets database as a string
        data = "secrets||" + str(shares[-1]['id']) + "||" + str(
            shares[-1]['name']) + "||" + str(
                shares[-1]['secret']) + "||" + str(shares[-1]['timestamp'])

        #Prepend header and send data
        data = "here:" + str(my_number) + ":" + auth_hash + "||" + data
        s.sendto(aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), data),
                 ((settings.MULT_ADDR, settings.MULT_PORT)))
Пример #9
0
def updater(address):

    #Open a socket to send the shares from, connecting to the provided address
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((address, 55552))

        #create a random number for the challenge response authentication
        challenge = int.from_bytes(Random.get_random_bytes(10), 'big')

        #Send the number to the recieving node
        s.send(
            aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), str(challenge)))

        #Get the number back, along with the updatee's timestamps
        #Recieve until done
        response = b""
        temp = b""
        try:
            while 1 == 1:
                temp = s.recv(4096)
                if temp and len(temp) == 4096:
                    response += temp
                else:
                    break
            response += temp

        #exit if connection breaks
        except:
            return -1

        #decrypt response
        response = aes_crypt.aes_dec(rsa_encrypt.get_priv_key_auth(), response)

        #return error if data is corrupted
        if response == -1 or response == -2:
            return -1

        #split response into timestamp and the response number
        response = str(response, 'ascii').split(":")

        #confirm that the response is correct
        if (challenge + 1) == int(response[0], 0):

            #grab timestamp
            timestamps = response[1].split("|")

            #create holder for share information
            data = ""

            #for each database
            for i in settings.DBS:

                #set up connection
                conn = sqlite3.connect(settings.DBdir + i + ".db")
                conn.row_factory = sqlite3.Row
                c = conn.cursor()

                #Make sure table exists
                c.execute(
                    "CREATE TABLE IF NOT EXISTS enc_shares(id PRIMARY KEY, share, timestamp DOUBLE)"
                )

                #Grab all shares from the current database with timestamp greater than the client's timestamp
                c.execute("SELECT * FROM enc_shares")
                d = c.fetchall()

                shares = []
                #for each share
                for i in range(len(d)):
                    #Join the components into a string if they are needed by the updatee
                    if not str(d[i]['timestamp']) in timestamps:
                        shares.append(d[i]["id"] + "|" + d[i]["share"] + "|" +
                                      str(d[i]["timestamp"]))

                #Join each share together
                shares = "::".join(shares)

                #add the information from this database to the database string
                data += (shares + ":::")

                #close connection
                conn.close()

            #open the secrets db
            conn = sqlite3.connect(settings.DBdir + "secrets.db")
            conn.row_factory = sqlite3.Row
            c = conn.cursor()

            #make sure table exists
            c.execute(
                "CREATE TABLE IF NOT EXISTS secrets(id PRIMARY KEY, name, secret, timestamp DOUBLE)"
            )

            #Grab all shares past the client timestamp
            c.execute("SELECT * FROM secrets")
            d = c.fetchall()

            secrets = []
            #For each secret
            for i in range(len(d)):

                #convert the share to a string if it is needed by the updatee
                if not str(d[i]['timestamp']) in timestamps:
                    secrets.append(d[i]["id"] + "|" + d[i]["name"] + "|" +
                                   d[i]["secret"] + "|" +
                                   str(d[i]['timestamp']))

            #join all the shares and add them to the db string
            data += "::".join(secrets)

            #send the databases to the client and exit
            s.send(aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), data))
    return 0
Пример #10
0
def updateee(my_number):

    #open socket to recieve shares into
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('0.0.0.0', 55552))
        s.listen(5)
        address = 0

        #Attempt to update the node
        try:
            #make sure that challenge exits succesfully and grab host address
            address = challenge(my_number, "woke")
            while address == 1:
                address = challenge(my_number, "woke")

        #If socket times out then return, this is likely the first auth node to be activated
        except socket.timeout:
            print("No Auth Nodes Found")
            return

        #accept connection from the node that shares will be pulled from
        cli, addr = s.accept()
        while not addr[0] == address[0]:
            cli, addr = s.accept()

        #Challenge response authentication, the node recieves a number from the auth node responsible for the update
        #and sends the number + 1 to the other node

        data = cli.recv(1024)

        #decrypt number and increment it by one
        data = aes_crypt.aes_dec(rsa_encrypt.get_priv_key_auth(), data)
        data = str(data, 'ascii')
        data = str(int(data) + 1)

        #encrypt number and return it to the host
        #send the timestamp of the most recent share along with the number
        timestamps = grab_timestamps()
        cli.send(
            aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                              data + ":" + timestamps))

        #Recv data until the sender is done
        data = b""
        temp = b""
        try:
            while 1 == 1:
                temp = cli.recv(4096)
                if temp and len(temp) == 4096:
                    data += temp
                else:
                    break
            data += temp

        #if the sender loses the connection then quit
        except:
            print("registered: 0 updates")
            return

        #Decrypt the data with the auth private key
        data = aes_crypt.aes_dec(rsa_encrypt.get_priv_key_auth(), data)

        #if the data is invalid return error
        if data == -2 or data == -1:
            return -1

        #if no databases hold data then return
        if data == b':::' * settings.TOTAL:
            print("registered: 0 updates")
            return

        #split the data into a list of databases
        data = str(data, 'ascii').split(":::")

        #for each database split the entries into a list
        for i in range(len(data)):
            data[i] = data[i].split("::")

        #store the list of db's into a disctonary
        #they are sent in the order they are listed in settings.py
        updates = {}
        for i in range(len(settings.DBS)):
            updates[settings.DBS[i]] = data[i]

        #store the secrets database into the dictionary
        updates['secrets'] = data[-1]

        #fill the databases
        fill_dbs(updates)

        #exit, ptinting the number of shares that were updated
        print("registered: " + str(len(updates['secrets'])) + " updates")
    return
Пример #11
0
def register():

    #Create socket to recieve updates from
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.settimeout(5)
        s.bind(("0.0.0.0", 55550))
        s.listen(5)

        #make sure that challenge executes correctly, else return error
        print("Looking for Auth Node")
        address = challenge()
        if address == -1:
            return -1

        #Create a connection with the auth node, if it is not the
        #expected address than continue waiting
        try:
            cli, addr = s.accept()
            while not addr[0] == address[0]:
                cli, addr = s.accept()
        except socket.timeout:
            return -1

        #Report
        print("Recieving Updates Now")

        #Recieve two sums for challenge response authentication
        #One for the database and one for the public key
        sums = cli.recv(2048).split(b"::")

        #Decrypt the sums using the node and db public keys
        sums[0] = aes_crypt.aes_dec(rsa_encrypt.get_priv_key(), sums[0])
        sums[1] = aes_crypt.aes_dec(rsa_encrypt.get_priv_key_db(settings.ID),
                                    sums[1])

        #if there is an error in the communication of the sums return an error
        if sums[0] == -1 or sums[0] == -2 or sums[1] == -1 or sums[1] == -2:
            return 1

        #Increment the sums and return them via the auth public key
        sum1 = str(int(sums[0]) + 1)
        sum2 = str(int(sums[1]) + 1)

        #send the incremented sums back to proove node identity
        payload = aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(),
                                    sum1 + ":" + sum2)
        #Fill recv buffer
        cli.send(payload + b"\x00" * (4096 - len(payload)))

        #Grab the latest timestamp
        timestamps = grab_timestamps()

        #Send the timestamp encrypted with the auth public key
        cli.send(
            aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), str(timestamps)))

        #Run the update process
        num_updates = shamir_updater.update(cli)

        #make number presentable
        if num_updates == -1:
            num_updates = 0

        #Report shares
        print("Registered: " + str(num_updates) + " updates")

        #clean up and exit
        cli.close()
    return
Пример #12
0
def updater(address):

    #Open a socket to send the shares from, connecting to the provided address
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((address, 44441))

        #create a random number for the challenge response authentication
        challenge = int.from_bytes(Random.get_random_bytes(10), 'big')

        #Send the number to the recieving node
        s.send(
            aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), str(challenge)))

        #Get the number back, along with the most recent timestamp that the recieving server has
        response = s.recv(2048)

        #decrypt response
        response = aes_crypt.aes_dec(rsa_encrypt.get_priv_key_auth(), response)

        #return error if data is corrupted
        if response == -1 or response == -2:
            return -1

        #split response into timestamp and the response number
        response = str(response, 'ascii').split(":")

        #confirm that the response is correct
        if (challenge + 1) == int(response[0], 0):

            #grab timestamp
            timestamp = response[1]

            #create holder for share information
            data = ""

            #for each database
            for i in settings.DBS:

                #set up connection
                conn = sqlite3.connect(settings.DBdir + i + ".db")
                conn.row_factory = sqlite3.Row
                c = conn.cursor()

                #Make sure table exists
                c.execute(
                    "CREATE TABLE IF NOT EXISTS enc_shares(id PRIMARY KEY, share, timestamp DOUBLE)"
                )

                #Grab all shares from the current database with timestamp greater than the client's timestamp
                c.execute("SELECT * FROM enc_shares WHERE timestamp > ?",
                          [float(timestamp)])
                d = c.fetchall()

                #for each share
                for i in range(len(d)):
                    #Join the components into a string
                    d[i] = d[i]["id"] + "|" + d[i]["share"] + "|" + str(
                        d[i]["timestamp"])

                #Join each share together
                d = "::".join(d)

                #add the information from this database to the database string
                data += (d + ":::")

                #close connection
                conn.close()

            #open the secrets db
            conn = sqlite3.connect(settings.DBdir + "secrets.db")
            conn.row_factory = sqlite3.Row
            c = conn.cursor()

            #make sure table exists
            c.execute(
                "CREATE TABLE IF NOT EXISTS secrets(id PRIMARY KEY, name, secret, timestamp DOUBLE)"
            )

            #Grab all shares past the client timestamp
            c.execute("SELECT * FROM secrets WHERE timestamp > ?",
                      [float(timestamp)])
            d = c.fetchall()

            #For each share
            for i in range(len(d)):

                #convert the share to a string
                d[i] = d[i]["id"] + "|" + d[i]["name"] + "|" + d[i][
                    "secret"] + "|" + str(d[i]['timestamp'])

            #join all the shares and add them to the db string
            data += "::".join(d)

            #send the databases to the client and exit
            s.send(aes_crypt.aes_enc(rsa_encrypt.get_pub_key_auth(), data))
    return 0