Ejemplo n.º 1
0
    def __init__(self):
        """Initialize the obfs2 pluggable transport."""
        super(Obfs2Transport, self).__init__()

        # Check if the shared_secret class attribute was already
        # instantiated. If not, instantiate it now.
        if not hasattr(self, 'shared_secret'):
            self.shared_secret = None
        # If external-mode code did not specify the number of hash
        # iterations, just use the default.
        if not hasattr(self, 'ss_hash_iterations'):
            self.ss_hash_iterations = HASH_ITERATIONS

        if self.shared_secret:
            log.debug("Starting obfs2 with shared secret: %s" %
                      self.shared_secret)

        # Our state.
        self.state = ST_WAIT_FOR_KEY

        if self.we_are_initiator:
            self.initiator_seed = rand.random_bytes(
                SEED_LENGTH)  # Initiator's seed.
            self.responder_seed = None  # Responder's seed.
        else:
            self.initiator_seed = None  # Initiator's seed.
            self.responder_seed = rand.random_bytes(
                SEED_LENGTH)  # Responder's seed

        # Shared secret seed.
        self.secret_seed = None

        # Crypto to encrypt outgoing data.
        self.send_crypto = None
        # Crypto to encrypt outgoing padding.
        self.send_padding_crypto = None
        # Crypto to decrypt incoming data.
        self.recv_crypto = None
        # Crypto to decrypt incoming padding.
        self.recv_padding_crypto = None

        # Number of padding bytes left to read.
        self.padding_left_to_read = 0

        # If it's True, it means that we received upstream data before
        # we had the chance to set up our crypto (after receiving the
        # handshake). This means that when we set up our crypto, we
        # must remember to push the cached upstream data downstream.
        self.pending_data_to_send = False
Ejemplo n.º 2
0
    def __init__(self, private_key = None):
        # Generate private key
        if private_key != None:
            if len(private_key) != self.group_len:
                raise ValueError("private_key is a invalid length (Expected %d, got %d)" % (group_len, len(private_key)))
            self.priv_str = private_key
        else:
            self.priv_str = rand.random_bytes(self.group_len)
        self.priv = int(binascii.hexlify(self.priv_str), 16)

        # Make the private key even
        flip = self.priv % 2
        self.priv -= flip

        # Generate public key
        #
        # Note: Always generate both valid public keys, and then pick to avoid
        # leaking timing information about which key was chosen.
        pub = modexp.powMod(self.g, self.priv, self.mod)
        pub_p_sub_X = self.mod - pub
        if flip == 1:
            self.pub = pub_p_sub_X
        else:
            self.pub = pub
        self.pub_str = int_to_bytes(self.pub, self.group_len)

        self.shared_secret = None
Ejemplo n.º 3
0
    def _read_handshake_post_dh(self, shared_secret, other_pubkey, data):
        """
        Setup the crypto from the calculated shared secret, and complete the
        obfs3 handshake.
        """

        self.shared_secret = shared_secret
        log_prefix = "obfs3:_read_handshake_post_dh()"
        log.debug("Got public key: %s.\nGot shared secret: %s" %
                  (repr(other_pubkey), repr(self.shared_secret)))

        # Set up our crypto.
        self.send_crypto = self._derive_crypto(self.send_keytype)
        self.recv_crypto = self._derive_crypto(self.recv_keytype)
        self.other_magic_value = hmac_sha256.hmac_sha256_digest(self.shared_secret,
                                                                self.recv_magic_const)

        # Send our magic value to the remote end and append the queued outgoing data.
        # Padding is prepended so that the server does not just send the 32-byte magic
        # in a single TCP segment.
        padding_length = random.randint(0, MAX_PADDING/2)
        magic = hmac_sha256.hmac_sha256_digest(self.shared_secret, self.send_magic_const)
        message = rand.random_bytes(padding_length) + magic + self.send_crypto.crypt(self.queued_data)
        self.queued_data = ''

        log.debug("%s: Transmitting %d bytes (with magic)." % (log_prefix, len(message)))
        self.circuit.downstream.write(message)

        self.state = ST_SEARCHING_MAGIC
        if len(data) > 0:
             log.debug("%s: Processing %d bytes of handshake data remaining after key." % (log_prefix, len(data)))
             self._scan_for_magic(data)
Ejemplo n.º 4
0
    def _read_handshake_post_dh(self, shared_secret, other_pubkey, data):
        """
        Setup the crypto from the calculated shared secret, and complete the
        obfs3 handshake.
        """

        self.shared_secret = shared_secret
        log_prefix = "obfs3:_read_handshake_post_dh()"
        log.debug("Got public key: %s.\nGot shared secret: %s" %
                  (repr(other_pubkey), repr(self.shared_secret)))

        # Set up our crypto.
        self.send_crypto = self._derive_crypto(self.send_keytype)
        self.recv_crypto = self._derive_crypto(self.recv_keytype)
        self.other_magic_value = hmac_sha256.hmac_sha256_digest(self.shared_secret,
                                                                self.recv_magic_const)

        # Send our magic value to the remote end and append the queued outgoing data.
        # Padding is prepended so that the server does not just send the 32-byte magic
        # in a single TCP segment.
        padding_length = random.randint(0, MAX_PADDING/2)
        magic = hmac_sha256.hmac_sha256_digest(self.shared_secret, self.send_magic_const)
        message = rand.random_bytes(padding_length) + magic + self.send_crypto.crypt(self.queued_data)
        self.queued_data = ''

        log.debug("%s: Transmitting %d bytes (with magic)." % (log_prefix, len(message)))
        self.circuit.downstream.write(message)

        self.state = ST_SEARCHING_MAGIC
        if len(data) > 0:
             log.debug("%s: Processing %d bytes of handshake data remaining after key." % (log_prefix, len(data)))
             self._scan_for_magic(data)
Ejemplo n.º 5
0
    def __init__(self):
        """Initialize the obfs2 pluggable transport."""
        super(Obfs2Transport, self).__init__()

        # Check if the shared_secret class attribute was already
        # instantiated. If not, instantiate it now.
        if not hasattr(self, 'shared_secret'):
            self.shared_secret = None
        # If external-mode code did not specify the number of hash
        # iterations, just use the default.
        if not hasattr(self, 'ss_hash_iterations'):
            self.ss_hash_iterations = HASH_ITERATIONS

        if self.shared_secret:
            log.debug("Starting obfs2 with shared secret: %s" % self.shared_secret)

        # Our state.
        self.state = ST_WAIT_FOR_KEY

        if self.we_are_initiator:
            self.initiator_seed = rand.random_bytes(SEED_LENGTH) # Initiator's seed.
            self.responder_seed = None # Responder's seed.
        else:
            self.initiator_seed = None # Initiator's seed.
            self.responder_seed = rand.random_bytes(SEED_LENGTH) # Responder's seed

        # Shared secret seed.
        self.secret_seed = None

        # Crypto to encrypt outgoing data.
        self.send_crypto = None
        # Crypto to encrypt outgoing padding.
        self.send_padding_crypto = None
        # Crypto to decrypt incoming data.
        self.recv_crypto = None
        # Crypto to decrypt incoming padding.
        self.recv_padding_crypto = None

        # Number of padding bytes left to read.
        self.padding_left_to_read = 0

        # If it's True, it means that we received upstream data before
        # we had the chance to set up our crypto (after receiving the
        # handshake). This means that when we set up our crypto, we
        # must remember to push the cached upstream data downstream.
        self.pending_data_to_send = False
Ejemplo n.º 6
0
    def __init__(self, circuit, ext_orport_addr, cookie_file, peer_addr):
        self.state = STATE_WAIT_FOR_AUTH_TYPES
        self.name = "ext_%s" % hex(id(self))

        self.ext_orport_addr = ext_orport_addr
        self.peer_addr = peer_addr
        self.cookie_file = cookie_file

        self.client_nonce = rand.random_bytes(AUTH_NONCE_LEN)
        self.client_hash = None

        network.GenericProtocol.__init__(self, circuit)
Ejemplo n.º 7
0
    def circuitConnected(self):
        """
        Do the obfs3 handshake:
        PUBKEY | WR(PADLEN)
        """
        padding_length = random.randint(0, MAX_PADDING/2)

        handshake_message = self.dh.get_public() + rand.random_bytes(padding_length)

        log.debug("obfs3 handshake: %s queued %d bytes (padding_length: %d) (public key: %s).",
                  "initiator" if self.we_are_initiator else "responder",
                  len(handshake_message), padding_length, repr(self.dh.get_public()))

        self.circuit.downstream.write(handshake_message)
Ejemplo n.º 8
0
    def circuitConnected(self):
        """
        Do the obfs3 handshake:
        PUBKEY | WR(PADLEN)
        """
        padding_length = random.randint(0, MAX_PADDING/2)

        handshake_message = self.dh.get_public() + rand.random_bytes(padding_length)

        log.debug("obfs3 handshake: %s queued %d bytes (padding_length: %d) (public key: %s).",
                  "initiator" if self.we_are_initiator else "responder",
                  len(handshake_message), padding_length, repr(self.dh.get_public()))

        self.circuit.downstream.write(handshake_message)
Ejemplo n.º 9
0
    def __init__(self):
        # Generate private key
        self.priv_str = rand.random_bytes(self.group_len)
        self.priv = int(binascii.hexlify(self.priv_str), 16)

        # Make the private key even
        flip = self.priv % 2
        self.priv -= flip

        # Generate public key
        self.pub = modexp.powMod(self.g, self.priv, self.mod)
        if flip == 1:
            self.pub = self.mod - self.pub
        self.pub_str = int_to_bytes(self.pub, self.group_len)

        self.shared_secret = None
Ejemplo n.º 10
0
    def __init__(self):
        # Generate private key
        self.priv_str = rand.random_bytes(self.group_len)
        self.priv = int(binascii.hexlify(self.priv_str), 16)

        # Make the private key even
        flip = self.priv % 2
        self.priv -= flip

        # Generate public key
        self.pub = pow(self.g, self.priv, self.mod)
        if flip == 1:
            self.pub = self.mod - self.pub
        self.pub_str = int_to_bytes(self.pub, self.group_len)

        self.shared_secret = None
Ejemplo n.º 11
0
    def _read_handshake(self, data, circuit):
        """
        Read handshake message, parse the other peer's public key and
        set up our crypto.
        """

        log_prefix = "obfs3:_read_handshake()"
        if len(data) < PUBKEY_LEN:
            log.debug("%s: Not enough bytes for key (%d)." %
                      (log_prefix, len(data)))
            return

        log.debug("%s: Got %d bytes of handshake data (waiting for key)." %
                  (log_prefix, len(data)))

        # Get the public key from the handshake message, do the DH and
        # get the shared secret.
        other_pubkey = data.read(PUBKEY_LEN)
        try:
            self.shared_secret = self.dh.get_secret(other_pubkey)
        except ValueError:
            raise base.PluggableTransportError(
                "obfs3: Corrupted public key '%s'" % repr(other_pubkey))
        log.debug("Got public key: %s.\nGot shared secret: %s" %
                  (repr(other_pubkey), repr(self.shared_secret)))

        # Set up our crypto.
        self.send_crypto = self._derive_crypto(self.send_keytype)
        self.recv_crypto = self._derive_crypto(self.recv_keytype)
        self.other_magic_value = hmac_sha256.hmac_sha256_digest(
            self.shared_secret, self.recv_magic_const)

        # Send our magic value to the remote end and append the queued outgoing data.
        # Padding is prepended so that the server does not just send the 32-byte magic
        # in a single TCP segment.
        padding_length = random.randint(0, MAX_PADDING / 2)
        magic = hmac_sha256.hmac_sha256_digest(self.shared_secret,
                                               self.send_magic_const)
        message = rand.random_bytes(
            padding_length) + magic + self.send_crypto.crypt(self.queued_data)
        self.queued_data = ''

        log.debug("%s: Transmitting %d bytes (with magic)." %
                  (log_prefix, len(message)))
        circuit.downstream.write(message)

        self.state = ST_SEARCHING_MAGIC
Ejemplo n.º 12
0
    def _read_handshake(self, data):
        """
        Read handshake message, parse the other peer's public key and
        set up our crypto.
        """

        log_prefix = "obfs3:_read_handshake()"
        if len(data) < PUBKEY_LEN:
            log.debug("%s: Not enough bytes for key (%d)." % (log_prefix, len(data)))
            return

        log.debug("%s: Got %d bytes of handshake data (waiting for key)." % (log_prefix, len(data)))

        # Get the public key from the handshake message, do the DH and
        # get the shared secret.
        other_pubkey = data.read(PUBKEY_LEN)
        try:
            self.shared_secret = self.dh.get_secret(other_pubkey)
        except ValueError:
            raise base.PluggableTransportError("obfs3: Corrupted public key '%s'" % repr(other_pubkey))
        log.debug("Got public key: %s.\nGot shared secret: %s" %
                  (repr(other_pubkey), repr(self.shared_secret)))

        # Set up our crypto.
        self.send_crypto = self._derive_crypto(self.send_keytype)
        self.recv_crypto = self._derive_crypto(self.recv_keytype)
        self.other_magic_value = hmac_sha256.hmac_sha256_digest(self.shared_secret,
                                                                self.recv_magic_const)

        # Send our magic value to the remote end and append the queued outgoing data.
        # Padding is prepended so that the server does not just send the 32-byte magic
        # in a single TCP segment.
        padding_length = random.randint(0, MAX_PADDING/2)
        magic = hmac_sha256.hmac_sha256_digest(self.shared_secret, self.send_magic_const)
        message = rand.random_bytes(padding_length) + magic + self.send_crypto.crypt(self.queued_data)
        self.queued_data = ''

        log.debug("%s: Transmitting %d bytes (with magic)." % (log_prefix, len(message)))
        self.circuit.downstream.write(message)

        self.state = ST_SEARCHING_MAGIC
Ejemplo n.º 13
0
    def circuitConnected(self):
        """
        Do the obfs2 handshake:
        SEED | E_PAD_KEY( UINT32(MAGIC_VALUE) | UINT32(PADLEN) | WR(PADLEN) )
        """
        # Generate keys for outgoing padding.
        self.send_padding_crypto = \
            self._derive_padding_crypto(self.initiator_seed if self.we_are_initiator else self.responder_seed,
                                        self.send_pad_keytype)

        padding_length = random.randint(0, MAX_PADDING)
        seed = self.initiator_seed if self.we_are_initiator else self.responder_seed

        handshake_message = seed + self.send_padding_crypto.crypt(srlz.htonl(MAGIC_VALUE) +
                                                                  srlz.htonl(padding_length) +
                                                                  rand.random_bytes(padding_length))

        log.debug("obfs2 handshake: %s queued %d bytes (padding_length: %d).",
                  "initiator" if self.we_are_initiator else "responder",
                  len(handshake_message), padding_length)

        self.circuit.downstream.write(handshake_message)
Ejemplo n.º 14
0
    def circuitConnected(self):
        """
        Do the obfs2 handshake:
        SEED | E_PAD_KEY( UINT32(MAGIC_VALUE) | UINT32(PADLEN) | WR(PADLEN) )
        """
        # Generate keys for outgoing padding.
        self.send_padding_crypto = \
            self._derive_padding_crypto(self.initiator_seed if self.we_are_initiator else self.responder_seed,
                                        self.send_pad_keytype)

        padding_length = random.randint(0, MAX_PADDING)
        seed = self.initiator_seed if self.we_are_initiator else self.responder_seed

        handshake_message = seed + self.send_padding_crypto.crypt(srlz.htonl(MAGIC_VALUE) +
                                                                  srlz.htonl(padding_length) +
                                                                  rand.random_bytes(padding_length))

        log.debug("obfs2 handshake: %s queued %d bytes (padding_length: %d).",
                  "initiator" if self.we_are_initiator else "responder",
                  len(handshake_message), padding_length)

        self.circuit.downstream.write(handshake_message)