Esempio n. 1
0
 def test_exchange(self):
     dh_x = obfs3_dh.UniformDH(self._x_str)
     dh_y = obfs3_dh.UniformDH(self._y_str)
     xY = dh_x.get_secret(dh_y.get_public())
     yX = dh_y.get_secret(dh_x.get_public())
     self.assertEqual(self._xYyX_str,  xY)
     self.assertEqual(self._xYyX_str,  yX)
Esempio n. 2
0
 def test_benchmark(self):
     start = time.clock()
     for i in range(0, 1000):
         dh_x = obfs3_dh.UniformDH()
         dh_y = obfs3_dh.UniformDH()
         xY = dh_x.get_secret(dh_y.get_public())
         yX = dh_y.get_secret(dh_x.get_public())
         self.assertEqual(xY, yX)
     end = time.clock()
     taken = (end - start) / 1000 / 2
     log.msg("Generate + Exchange: %f sec" % taken)
Esempio n. 3
0
    def test_uniform_dh(self):
        alice = obfs3_dh.UniformDH()
        bob = obfs3_dh.UniformDH()

        alice_pub = alice.get_public()
        bob_pub = bob.get_public()

        alice_secret = alice.get_secret(bob_pub)
        bob_secret = bob.get_secret(alice_pub)

        self.assertEqual(alice_secret, bob_secret)
Esempio n. 4
0
    def receivePublicKey(self, data, callback, srvState=None):
        """
        Extract the public key and invoke a callback with the master secret.

        First, the UniformDH public key is extracted out of `data'.  Then, the
        shared master secret is computed and `callback' is invoked with the
        master secret as argument.  If any of this fails, `False' is returned.
        """

        # Extract the public key sent by the remote host.
        remotePublicKey = self.extractPublicKey(data, srvState)
        if not remotePublicKey:
            return False

        if self.weAreServer:
            self.remotePublicKey = remotePublicKey
            # As server, we need a DH object; as client, we already have one.
            self.udh = obfs3_dh.UniformDH()

        assert self.udh is not None

        try:
            uniformDHSecret = self.udh.get_secret(remotePublicKey)
        except ValueError:
            raise base.PluggableTransportError("Corrupted public key.")

        # First, hash the 4096-bit UniformDH secret to obtain the master key.
        masterKey = Crypto.Hash.SHA256.new(uniformDHSecret).digest()

        # Second, session keys are now derived from the master key.
        callback(masterKey)

        return True
Esempio n. 5
0
    def createHandshake(self):
        """
        Create and return a ready-to-be-sent UniformDH handshake.

        The returned handshake data includes the public key, pseudo-random
        padding, the mark and the HMAC.  If a UniformDH object has not been
        initialised yet, a new instance is created.
        """

        assert self.sharedSecret is not None

        log.debug("Creating UniformDH handshake message.")

        if self.udh is None:
            self.udh = obfs3_dh.UniformDH()
        publicKey = self.udh.get_public()

        assert (const.MAX_PADDING_LENGTH - const.PUBLIC_KEY_LENGTH) >= 0

        # Subtract the length of the public key to make the handshake on
        # average as long as a redeemed ticket.  That should thwart statistical
        # length-based attacks.
        padding = mycrypto.strongRandom(
            random.randint(0,
                           const.MAX_PADDING_LENGTH - const.PUBLIC_KEY_LENGTH))

        # Add a mark which enables efficient location of the HMAC.
        mark = mycrypto.HMAC_SHA256_128(self.sharedSecret, publicKey)

        # Authenticate the handshake including the current approximate epoch.
        mac = mycrypto.HMAC_SHA256_128(
            self.sharedSecret, publicKey + padding + mark + util.getEpoch())

        return publicKey + padding + mark + mac
Esempio n. 6
0
    def __init__(self):
        """Initialize the obfs3 pluggable transport."""

        # Our state.
        self.state = ST_WAIT_FOR_KEY

        # Uniform-DH object
        self.dh = obfs3_dh.UniformDH()

        # DH shared secret
        self.shared_secret = None

        # Bytes of padding scanned so far.
        self.scanned_padding = 0
        # Last padding bytes scanned.
        self.last_padding_chunk = ''

        # Magic value that the other party is going to send
        # (initialized after deriving shared secret)
        self.other_magic_value = None
        # Crypto to encrypt outgoing data.
        self.send_crypto = None
        # Crypto to decrypt incoming data.
        self.recv_crypto = None

        # Buffer for the first data, Tor is trying to send but can't right now
        # because we have to handle the DH handshake first.
        self.queued_data = ''

        # Attributes below are filled by classes that inherit Obfs3Transport.
        self.send_keytype = None
        self.recv_keytype = None
        self.send_magic_const = None
        self.recv_magic_const = None
        self.we_are_initiator = None
Esempio n. 7
0
    def createHandshake(self, srvState=None):
        """
        Create and return a ready-to-be-sent UniformDH handshake.

        The returned handshake data includes the public key, pseudo-random
        padding, the mark and the HMAC.  If a UniformDH object has not been
        initialised yet, a new instance is created.
        """

        assert self.sharedSecret is not None

        log.debug("Creating UniformDH handshake message.")

        if self.udh is None:
            self.udh = obfs3_dh.UniformDH()
        publicKey = self.udh.get_public()

        assert (const.MAX_PADDING_LENGTH - const.PUBLIC_KEY_LENGTH) >= 0

        # Subtract the length of the public key to make the handshake on
        # average as long as a redeemed ticket.  That should thwart statistical
        # length-based attacks.
        padding = mycrypto.strongRandom(
            random.randint(0,
                           const.MAX_PADDING_LENGTH - const.PUBLIC_KEY_LENGTH))

        # Add a mark which enables efficient location of the HMAC.
        mark = mycrypto.HMAC_SHA256_128(self.sharedSecret, publicKey)

        if self.echoEpoch is None:
            epoch = util.getEpoch()
        else:
            epoch = self.echoEpoch
            log.debug("Echoing epoch rather than recreating it.")

        # Authenticate the handshake including the current approximate epoch.
        mac = mycrypto.HMAC_SHA256_128(
            self.sharedSecret,
            publicKey + padding + mark + epoch.encode('utf-8'))

        if self.weAreServer and (srvState is not None):
            log.debug("Adding the HMAC authenticating the server's UniformDH "
                      "message to the replay table: %s." % mac.encode('hex'))
            srvState.registerKey(mac)

        return publicKey + padding + mark + mac
Esempio n. 8
0
 def test_even_key(self):
     dh_y = obfs3_dh.UniformDH(self._y_str)
     self.assertEqual(self._y_str, dh_y.priv_str)
     self.assertEqual(self._Y_str, dh_y.get_public())
Esempio n. 9
0
 def test_odd_key(self):
     dh_x = obfs3_dh.UniformDH(self._x_str)
     self.assertEqual(self._x_str, dh_x.priv_str)
     self.assertEqual(self._X_str, dh_x.get_public())