Beispiel #1
0
    def handshake(self, circuit):
        """This function is invoked after a circuit was established. The server
        generates a time-lock puzzle and sends it to the client. The client
        does nothing during the handshake."""

        log.debug("Entering handshake().")
        if self.circuit == None:
            self.circuit = circuit

        # Only the server is generating and transmitting a puzzle.
        if self.weAreServer:

            # Generate master key and derive client -and server key.
            masterKey = mycrypto.strong_random(const.MASTER_KEY_SIZE)
            self._deriveSecrets(masterKey)

            # Append random padding to obfuscate length and transmit blurb.
            padding = mycrypto.weak_random(random.randint(0, \
                    const.MAX_PADDING_LENGTH))
            log.debug("Sending puzzle with %d-byte of padding." % len(padding))

            puzzle, nonce = timelock.encryptPuzzle( \
                    timelock.generateRawPuzzle(masterKey))

            circuit.downstream.write(nonce + puzzle + padding)

            log.debug("Switching to state ST_WAIT_FOR_TICKET.")
            self.state = const.ST_WAIT_FOR_TICKET

        # Send a session ticket to the server (if we have one).
        elif self.weAreClient:
            stop = False
            try:
                with open(const.DATA_DIRECTORY + const.TICKET_FILE,
                          "rb") as fd:
                    masterKey = fd.read(const.MASTER_KEY_SIZE)
                    ticket = fd.read(const.TICKET_LENGTH)
                    fd.close()
            except IOError as e:
                log.error("Could not read session ticket from \"%s\"." % \
                        (const.DATA_DIRECTORY + const.TICKET_FILE))
                stop = True

            if not stop:
                log.debug("Trying to redeem session ticket: 0x%s..." % \
                        ticket.encode('hex')[:10])
                self._deriveSecrets(masterKey)
                padding = mycrypto.weak_random(random.randint(0, \
                        const.MAX_PADDING_LENGTH))
                circuit.downstream.write(ticket + padding)
                self.redeemedTicket = True

        # Now start transmitting cover traffic.
        self.stopCoverTraffic = False
        reactor.callLater(0, self._sendCoverTraffic, circuit)
Beispiel #2
0
    def handshake(self, circuit):
        """This function is invoked after a circuit was established. The server
        generates a time-lock puzzle and sends it to the client. The client
        does nothing during the handshake."""

        log.debug("Entering handshake().")
        if self.circuit == None:
            self.circuit = circuit

        # Only the server is generating and transmitting a puzzle.
        if self.weAreServer:

            # Generate master key and derive client -and server key.
            masterKey = mycrypto.strong_random(const.MASTER_KEY_SIZE)
            self._deriveSecrets(masterKey)

            # Append random padding to obfuscate length and transmit blurb.
            padding = mycrypto.weak_random(random.randint(0, const.MAX_PADDING_LENGTH))
            log.debug("Sending puzzle with %d-byte of padding." % len(padding))

            puzzle, nonce = timelock.encryptPuzzle(timelock.generateRawPuzzle(masterKey))

            circuit.downstream.write(nonce + puzzle + padding)

            log.debug("Switching to state ST_WAIT_FOR_TICKET.")
            self.state = const.ST_WAIT_FOR_TICKET

        # Send a session ticket to the server (if we have one).
        elif self.weAreClient:
            stop = False
            try:
                with open(const.DATA_DIRECTORY + const.TICKET_FILE, "rb") as fd:
                    masterKey = fd.read(const.MASTER_KEY_SIZE)
                    ticket = fd.read(const.TICKET_LENGTH)
                    fd.close()
            except IOError as e:
                log.error('Could not read session ticket from "%s".' % (const.DATA_DIRECTORY + const.TICKET_FILE))
                stop = True

            if not stop:
                log.debug("Trying to redeem session ticket: 0x%s..." % ticket.encode("hex")[:10])
                self._deriveSecrets(masterKey)
                padding = mycrypto.weak_random(random.randint(0, const.MAX_PADDING_LENGTH))
                circuit.downstream.write(ticket + padding)
                self.redeemedTicket = True

        # Now start transmitting cover traffic.
        self.stopCoverTraffic = False
        reactor.callLater(0, self._sendCoverTraffic, circuit)
Beispiel #3
0
    def decryptedPuzzleCallback(self, masterKey):
        """This method is invoked as soon as the puzzle is unlocked. The
        argument `masterKey' is the content of the unlocked puzzle."""

        log.debug("Callback invoked after solved puzzle.")

        # Sanity check to verify that we solved a real puzzle.
        if not const.MASTER_KEY_PREFIX in masterKey:
            log.critical("No MASTER_KEY_PREFIX in puzzle. What did we just " "solve?")
            return

        masterKey = masterKey[len(const.MASTER_KEY_PREFIX) :]
        assert len(masterKey) == const.MASTER_KEY_SIZE

        self._deriveSecrets(masterKey)

        log.debug("Stopping cover traffic generation.")
        self.stopCoverTraffic = True

        # Send bridge randomness || magic value.
        log.debug("Sending magic value to server.")
        assert self.circuit
        self.circuit.downstream.write(
            mycrypto.weak_random(random.randint(0, const.MAX_PADDING_LENGTH)) + self.sendMagic
        )

        log.debug("Switching to state ST_WAIT_FOR_MAGIC.")
        self.state = const.ST_WAIT_FOR_MAGIC
Beispiel #4
0
    def decryptedPuzzleCallback(self, masterKey):
        """This method is invoked as soon as the puzzle is unlocked. The
        argument `masterKey' is the content of the unlocked puzzle."""

        log.debug("Callback invoked after solved puzzle.")

        # Sanity check to verify that we solved a real puzzle.
        if not const.MASTER_KEY_PREFIX in masterKey:
            log.critical("No MASTER_KEY_PREFIX in puzzle. What did we just " \
                    "solve?")
            return

        masterKey = masterKey[len(const.MASTER_KEY_PREFIX):]
        assert len(masterKey) == const.MASTER_KEY_SIZE

        self._deriveSecrets(masterKey)

        log.debug("Stopping cover traffic generation.")
        self.stopCoverTraffic = True

        # Send bridge randomness || magic value.
        log.debug("Sending magic value to server.")
        assert self.circuit
        self.circuit.downstream.write(
            mycrypto.weak_random(random.randint(0, const.MAX_PADDING_LENGTH)) +
            self.sendMagic)

        log.debug("Switching to state ST_WAIT_FOR_MAGIC.")
        self.state = const.ST_WAIT_FOR_MAGIC
Beispiel #5
0
    def _sendMagicValue(self, circuit, magic):
        """Sends the given `magic' to the remote machine using `circuit'. Before
        that, the cover traffic generator is stopped."""

        log.debug("Stopping cover traffic generation.")
        self.stopCoverTraffic = True

        # FIXME - Use packet morpher oracle for padding.
        circuit.downstream.write(mycrypto.weak_random(random.randint(0, const.MAX_PADDING_LENGTH)) + magic)
Beispiel #6
0
    def _sendMagicValue(self, circuit, magic):
        """Sends the given `magic' to the remote machine using `circuit'. Before
        that, the cover traffic generator is stopped."""

        log.debug("Stopping cover traffic generation.")
        self.stopCoverTraffic = True

        # FIXME - Use packet morpher oracle for padding.
        circuit.downstream.write(mycrypto.weak_random(random.randint(0, \
                const.MAX_PADDING_LENGTH)) + magic)
Beispiel #7
0
    def _sendCoverTraffic(self, circuit):
        """Send random cover traffic using `circuit'. This is done to make DPI
        boxes believe that we are communicating when in fact the client is busy
        solving the puzzle."""

        if self.stopCoverTraffic == True:
            return

        coverTraffic = mycrypto.weak_random(self.pktMorpher.randomSample())
        log.debug("Sending %d bytes of cover traffic." % len(coverTraffic))
        circuit.downstream.write(coverTraffic)

        # When should we send the next chunk of bytes?
        if random.random() > 0.3:
            delay = self.iatMorpher.randomSample()
        else:
            delay = random.random() * 5

        reactor.callLater(delay, self._sendCoverTraffic, circuit)
Beispiel #8
0
    def _sendCoverTraffic(self, circuit):
        """Send random cover traffic using `circuit'. This is done to make DPI
        boxes believe that we are communicating when in fact the client is busy
        solving the puzzle."""

        if self.stopCoverTraffic == True:
            return

        coverTraffic = mycrypto.weak_random(self.pktMorpher.randomSample())
        log.debug("Sending %d bytes of cover traffic." % len(coverTraffic))
        circuit.downstream.write(coverTraffic)

        # When should we send the next chunk of bytes?
        if random.random() > 0.3:
            delay = self.iatMorpher.randomSample()
        else:
            delay = random.random() * 5

        reactor.callLater(delay, self._sendCoverTraffic, circuit)