Esempio n. 1
0
    def __init__(self, blockNumber, previousHash, data, nonce):
        self.blockNum = blockNumber
        self.prevHash = previousHash
        self.nonce = nonce
        self.data = data

        toMine = dict()
        toMine["blockNumber"] = self.blockNum
        toMine["previousHash"] = self.prevHash
        toMine["nonce"] = self.nonce
        toMine["data"] = self.data

        self.hash = b64encode(calculateHashOverFields(toMine)).decode("ascii")

        self.next = None
Esempio n. 2
0
def validReceiptSignature(signature, certificate, data):
    signature = b64decode(bytes(signature, "ascii"))
    certificateBytes = b64decode(bytes(certificate, "ascii"))

    certificate = load_pem_x509_certificate(certificateBytes,
                                            default_backend())

    valid, _, _, _ = validCertificate(certificateBytes)
    if not valid:
        return False

    serverPublicKey = PublicKeyServer(certificate.public_key())

    if not serverPublicKey.verify(calculateHashOverFields({"": data}),
                                  signature):
        return False

    return True
Esempio n. 3
0
def newBid(sock, clientCert, symmetricEncryption, sessionId):

    mutex.acquire()

    openAuctionList = []
    for auction in OPEN_AUCTIONS.values():
        openAuctionList.append(auction.getAuctionInfo())

    #Sends lists with all open auctions
    sendEncryptedMessage(sock, {"openAuctionList": openAuctionList},
                         symmetricEncryption, sessionId, 4)

    mandatoryFields = []
    mandatoryFields.append(Field("auctionId", int))
    mandatoryFields.append(Field("timestamp", int))
    mandatoryFields.append(Field("amount", float))
    mandatoryFields.append(BytesField("nonce"))
    mandatoryFields.append(BytesField("signature"))
    msg = readMessage(sock, mandatoryFields, symmetricEncryption, sessionId, 5)

    auctionId = msg["auctionId"]

    if auctionId not in OPEN_AUCTIONS.keys():
        sendEncryptedMessage(sock, {"error": "No auction with that id"},
                             symmetricEncryption, sessionId, 6)
        return

    clientId, clientName = getUserInfo(clientCert)
    clientCertBytes = b64encode(clientCert.public_bytes(
        Encoding.PEM)).decode("ascii")

    bid = {
        "timestamp": msg["timestamp"],
        "clientId": clientId,
        "clientName": clientName,
        "clientCertificate": clientCertBytes,
        "amount": msg["amount"],
        "nonce": msg["nonce"],
        "auctionId": auctionId,
        "auctionType": OPEN_AUCTIONS[auctionId].getAuctionInfo()["type"]
    }

    if not PublicKeyClient(clientCert.public_key()).verify(
            calculateHashOverFields(bid),
            b64decode(bytes(msg["signature"], "ascii"))):
        mutex.release()
        sendEncryptedMessage(sock, {"error": "Invalid signature over bid"},
                             symmetricEncryption, sessionId, 6)
        return

    sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock2.connect(constants.MANAGER_ADDR)

    symmetricEncryption2, sessionId2 = handshake.clientHandShake(
        sock2, privateKey, certificate, POSSIB_CIPHERS, POSSIB_MODES,
        POSSIB_PADDING)

    sendEncryptedMessage(sock2, {"action": ActionTypes.VALIDATE_BID},
                         symmetricEncryption2, sessionId2, 3)

    toValidate = {"clientValidation": msg["signature"], "bid": bid}

    auction = OPEN_AUCTIONS[auctionId]
    if auction.getAuctionInfo()["type"] == "BlindShown":
        if clientId not in CLIENTS_BIDS_COUNT.keys():
            CLIENTS_BIDS_COUNT[clientId] = dict()
        if auctionId not in CLIENTS_BIDS_COUNT[clientId].keys():
            CLIENTS_BIDS_COUNT[clientId][auctionId] = 0

        toValidate["countBidsDone"] = CLIENTS_BIDS_COUNT[clientId][auctionId]

    sendEncryptedMessage(sock2, toValidate, symmetricEncryption2, sessionId2,
                         4)

    exceptionHappen = False
    try:
        msg = readMessage(sock2, [], symmetricEncryption2, sessionId2, 5)
    except ErrorMessage as e:
        exceptionHappen = True
        sendEncryptedMessage(sock, {"error": e.args[0]}, symmetricEncryption,
                             sessionId, 6)

    if exceptionHappen:
        mutex.release()
        return

    sock2.close()

    blockNum, prevHash = auction.lastBlockInfo()
    blockNum += 1

    cryptopuzzleChallange = {
        "difficulty": auction.getAuctionInfo()["difficulty"],
        "toMine": {
            "blockNumber": blockNum,
            "previousHash": prevHash,
            "data": msg
        }
    }

    sendEncryptedMessage(sock, cryptopuzzleChallange, symmetricEncryption,
                         sessionId, 6)

    mandatoryFields = []
    mandatoryFields.append(BytesField("hash"))
    mandatoryFields.append(BytesField("nonce"))
    msg = readMessage(sock, mandatoryFields, symmetricEncryption, sessionId, 7,
                      60)

    blockInfo = cryptopuzzleChallange["toMine"]
    blockInfo["nonce"] = msg["nonce"]

    valid, cause = verifyCryptopuzzle(msg["hash"], blockInfo,
                                      auction.getAuctionInfo()["difficulty"])

    if not valid:
        mutex.release()
        sendEncryptedMessage(sock, {"error": cause}, symmetricEncryption,
                             sessionId, 8)
        return

    if auction.getAuctionInfo()["type"] == "BlindShown":
        if clientId not in CLIENTS.keys():
            CLIENTS[clientId] = set()
        CLIENTS[clientId].add(auctionId)

    auction.newBid(blockInfo["data"], blockInfo["nonce"], msg["hash"])

    receipt = auction.getAllData()
    signature = privateKey.sign(calculateHashOverFields({"": receipt}))
    signature = b64encode(signature).decode("ascii")
    cert = b64encode(certificate.public_bytes(Encoding.PEM)).decode("ascii")

    sendEncryptedMessage(sock, {
        "receipt": receipt,
        "signature": signature,
        "certificate": cert
    }, symmetricEncryption, sessionId, 8)

    mutex.release()
Esempio n. 4
0
def validateAuctionContent(allData, compareBid=None, compareBlock=None):
    previousHash = b64encode(bytes(32)).decode("ascii")

    key = None

    validateOpen = not all(k in allData[-1]["block"]["data"].keys()
                           for k in ["key", "winnerBlockNumber"])

    if not validateOpen:
        key = b64decode(bytes(allData[-1]["block"]["data"]["key"], "ascii"))

    winnerAmount = winnerBlockNumber = difficulty = -1
    for i, blockData in enumerate(allData):
        blockHash = b64decode(bytes(blockData["hash"], "ascii"))
        block = blockData["block"]

        #print(block)

        if compareBlock != None and compareBlock["blockNumber"] == block[
                "blockNumber"] and compareBlock != block:
            print("Data on the blockchain is different from the receipt")
            return

        if block["previousHash"] != previousHash:
            print("Hash of previous block don't match")
            return

        if block["blockNumber"] != i:
            print("Number of block does not match sequence")
            return

        if blockHash != calculateHashOverFields(block):
            print("Hash of blocks don't match")
            return
        previousHash = blockData["hash"]

        if i == 0:
            difficulty = block["data"]["difficulty"]
            continue
        elif i == len(allData) - 1 and not validateOpen:
            if winnerBlockNumber != block["data"]["winnerBlockNumber"]:
                print("Winner block number don't match")
                return
            continue

        if not (int(blockHash.hex(), 16) < 2**(256 - difficulty)):
            print("Hash of a block not under the target")
            return

        data = block["data"]

        managerValidation = data.pop("managerValidation")

        managerCertificateBytes = b64decode(
            bytes(managerValidation["certificate"], "ascii"))
        managerCertificate = load_pem_x509_certificate(managerCertificateBytes,
                                                       default_backend())
        managerPublicKey = PublicKeyServer(managerCertificate.public_key())
        signature = b64decode(bytes(managerValidation["signature"], "ascii"))

        if not managerPublicKey.verify(calculateHashOverFields(data),
                                       signature):
            print("Signature of manager validation not valid")
            return

        if not validateOpen:
            originalBid = deepcopy(data["bid"])
            bid = data["bid"]

            if compareBlock != None and compareBlock["blockNumber"] == block[
                    "blockNumber"] and compareBid != bid:
                print("Bid sent is different!")
                return

            decryptBid(bid, key)

            if bid["auctionId"] != allData[0]["block"]["data"]["auctionId"]:
                print("Auction Id on a bid doesn't match")
                return

            if bid["auctionType"] != allData[0]["block"]["data"]["type"]:
                print("Auction type on a bid doesn't match")
                return

            valid, _, _, _ = validCertificate(
                managerCertificateBytes,
                datetime.fromtimestamp(int(bid["timestamp"])))
            if not valid:
                print("Manager certificate not valid")
                return

            clientCertificateBytes = b64decode(
                bytes(bid["clientCertificate"], "ascii"))
            clientCertificate = load_pem_x509_certificate(
                clientCertificateBytes, default_backend())

            valid, _, _, _ = validCertificate(
                clientCertificateBytes,
                datetime.fromtimestamp(int(bid["timestamp"])))
            if not valid:
                print("Client certificate not valid")
                return

            clientPublicKey = PublicKeyClient(clientCertificate.public_key())

            signature = data["clientValidation"]

            if bid["auctionType"] in ["English", "BlindHidden"]:
                signature, iv = signature.split("\n")

                iv = b64decode(bytes(iv, "ascii"))
                signature = b64decode(bytes(signature, "ascii"))

                decryptor = Cipher(AES(key), CBC(iv),
                                   default_backend()).decryptor()
                uncryptedField = decryptor.update(
                    signature) + decryptor.finalize()

                unpadder = PKCS7(AES.block_size).unpadder()
                signature = unpadder.update(
                    uncryptedField) + unpadder.finalize()

                signature = b64decode(signature)
            else:
                signature = b64decode(bytes(signature, "ascii"))

            if not clientPublicKey.verify(calculateHashOverFields(bid),
                                          signature):
                print("Signature of client over bids not valid")
                return

            if float(bid["amount"]) > winnerAmount:
                winnerAmount = float(bid["amount"])
                winnerBlockNumber = block["blockNumber"]

    print("All ok")
Esempio n. 5
0
def newBid():

    while True:
        amount = input("Amount to bid: ")

        if not match("^[0-9]+(\.[0-9][0-9]?)?$", amount):
            print("ERROR: Insert a valid amount")
            continue

        amount = float(amount)

        break

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    sock.connect(constants.REPOSITORY_ADDR)
    cert = getCertificate()
    symmetricEncryption, sessionId = clientHandShake(sock, privateKey, cert, ciphers, modes, paddings)

    sendEncryptedMessage(sock, {'action':ActionTypes.NEW_BID}, symmetricEncryption, sessionId, 3)

    msgRecv = readMessage(sock, [], symmetricEncryption, sessionId, 4)

    #display data
    openAuctionList = msgRecv["openAuctionList"]

    if len(openAuctionList) == 0:
        print("No open auctions")
        sock.close()
        return

    for i, auction in enumerate(openAuctionList):
        print("## {} ##".format(i+1))
        print("Auction Id:     ",     auction["auctionId"])
        print("Name:           ",     auction["name"])
        print("Description:    ",     auction["description"])
        print("Type:           ",     auction["type"])
        print("Duration:       ",     auction["duration"])
        print("Creation Time:  ",     auction["creationTime"])
        print("Difficulty:     ",     auction["difficulty"])
        print("Base amount:    ",     auction["baseAmount"])
        print("Validation Code\n"   + auction["validationCode"])
        print("Modification Code\n" + auction["modificationCode"])
        print("Creator Id:     ",     auction["creatorId"])
        print("Creator Name:   ",     auction["creatorName"])
        print("--------------------------------------\n")

    while True:
        opt = input("$ ")

        if not match("^[0-9]+$", opt):
            print("ERROR: Insert a valid number!")
            continue

        opt = int(opt)
    
        if opt < 1 or opt > len(openAuctionList):
            print("Error: Insert a number between 1 and " + str(len(openAuctionList)))
            continue

        opt -= 1

        break

    clientId, clientName = getUserInfo(cert)

    auctionId = openAuctionList[opt]["auctionId"]
    auctionType = openAuctionList[opt]["type"]
    timestamp = int(time.time())
    nonce = b64encode(urandom(32)).decode("ascii")
    bid = {
        "timestamp":timestamp,
        "clientId":clientId,
        "clientName":clientName,
        "clientCertificate":b64encode(cert.public_bytes(Encoding.PEM)).decode("ascii"),
        "amount":amount,
        "nonce":nonce,
        "auctionId":auctionId,
        "auctionType":auctionType
    }

    signature = b64encode(privateKey.sign(calculateHashOverFields(bid))).decode("ascii")

    sendEncryptedMessage(sock, {'auctionId': auctionId, "timestamp":timestamp, "nonce":nonce, "amount":amount, "signature":signature},
            symmetricEncryption, sessionId, 5)

    cryptopuzzleChallange = readMessage(sock, [], symmetricEncryption, sessionId, 6)

    nonce, newHash = solveCriptopuzzle(cryptopuzzleChallange["difficulty"], cryptopuzzleChallange["toMine"])

    sendEncryptedMessage(sock, {"nonce":nonce, "hash":newHash}, symmetricEncryption, sessionId, 7)

    msg = readMessage(sock, [], symmetricEncryption, sessionId, 8)

    if not validReceiptSignature(msg["signature"], msg["certificate"], msg["receipt"]):
        print("Signature on receipt received not valid")
        return
    else:
        print("Signature on receipt ok")

    if not os.path.exists("receipts"):
        os.mkdir("receipts")
        os.mkdir("receipts/" + clientId)

    if not os.path.exists("receipts/" + clientId):
        os.mkdir("receipts/" + clientId)

    while True:
        receiptName = input("Name for receipt: ")
        if receiptName == "":
            print("ERROR: Insert a valid name")
            continue
        break

    cryptopuzzleChallange["toMine"]["nonce"] = nonce

    receipt = {
        "whatISaw":{
            'bid': bid,
            "cryptopuzzleChallange":cryptopuzzleChallange
        },
        "received":msg
    }

    f = open("receipts/" + clientId + "/" + receiptName + ".txt", "w+")
    f.write(json.dumps({"auctionId":auctionId, "receipt":receipt}))
    f.close()

    sock.close()
Esempio n. 6
0
def validateBid(sock, symmetricEncryption, sessionId):

    msg = readMessage(sock, [], symmetricEncryption, sessionId, 4)

    bid = msg["bid"]
    clientValidation = msg["clientValidation"]

    auction = AUCTIONS[bid["auctionId"]]
    type = auction.auctionInfo["type"]

    if type == "BlindShown":
        assert "countBidsDone" in msg.keys()
        countBidsDone = msg["countBidsDone"]
    else:
        countBidsDone = None

    if not bidValidation(auction.validationCode, type, deepcopy(bid),
                         auction.lastAmount, countBidsDone):
        sendEncryptedMessage(sock, {"error": "Bid failed bid validation"},
                             symmetricEncryption, sessionId, 5)
        return

    payload = bidModification(auction.modificationCode, type, deepcopy(bid),
                              auction.lastAmount, countBidsDone)

    if float(bid["amount"]) < auction.baseAmount:
        sendEncryptedMessage(
            sock, {"error": "Amount has to greater than the base amount"},
            symmetricEncryption, sessionId, 5)
        return
    bidAmount = float(bid["amount"])
    if type == "English":
        if bidAmount <= auction.lastAmount:
            sendEncryptedMessage(
                sock, {"error": "Amount has to greater than the last one"},
                symmetricEncryption, sessionId, 5)
            return
        else:
            auction.lastAmount = bidAmount

    if type == "English" or type == "BlindHidden":
        for field in [
                "clientId", "clientName", "clientCertificate", "timestamp"
        ]:
            bid[field] = auction.encryptField(bid[field])
        clientValidation = auction.encryptField(clientValidation)

    if "Blind" in type:
        bid["amount"] = auction.encryptField(bid["amount"])
    bid["nonce"] = auction.encryptField(bid["nonce"])

    posValidation = {
        "bid": bid,
        "payload": payload,
        "clientValidation": clientValidation
    }

    signature = b64encode(
        privateKey.sign(
            calculateHashOverFields(posValidation))).decode("ascii")

    posValidation["managerValidation"] = {
        "signature":
        signature,
        "certificate":
        b64encode(certificate.public_bytes(Encoding.PEM)).decode("ascii")
    }

    sendEncryptedMessage(sock, posValidation, symmetricEncryption, sessionId,
                         5)