def __init__( self ): """ Initialise a ScrambleSuitTransport object. """ log.error("\n\n################################################\n" "Do NOT rely on ScrambleSuit for strong security!\n" "################################################\n") log.debug("Initialising %s." % const.TRANSPORT_NAME) super(ScrambleSuitTransport, self).__init__() # Load the server's persistent state from file. if self.weAreServer: self.srvState = state.load() # Initialise the protocol's state machine. log.debug("Switching to state ST_WAIT_FOR_AUTH.") self.protoState = const.ST_WAIT_FOR_AUTH # Buffer for outgoing data. self.sendBuf = "" # Buffer for inter-arrival time obfuscation. self.choppingBuf = fifobuf.Buffer() # AES instances to decrypt incoming and encrypt outgoing data. self.sendCrypter = mycrypto.PayloadCrypter() self.recvCrypter = mycrypto.PayloadCrypter() # Packet morpher to modify the protocol's packet length distribution. self.pktMorpher = packetmorpher.new(self.srvState.pktDist if self.weAreServer else None) # Inter-arrival time morpher to obfuscate inter arrival times. self.iatMorpher = self.srvState.iatDist if self.weAreServer else \ probdist.new(lambda: random.random() % const.MAX_PACKET_DELAY) # Used to extract protocol messages from encrypted data. self.protoMsg = message.MessageExtractor() # Used by the server-side: `True' if the ticket is already # decrypted but not yet authenticated. self.decryptedTicket = False # If we are in external mode we should already have a shared # secret set up because of validate_external_mode_cli(). if self.weAreExternal: assert(self.uniformDHSecret) if self.weAreClient and not self.weAreExternal: # As a client in managed mode, we get the shared secret # from callback `handle_socks_args()' per-connection. Set # the shared secret to None for now. self.uniformDHSecret = None self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)
def handle_socks_args(self, args): """ Receive arguments `args' passed over a SOCKS connection. The SOCKS authentication mechanism is (ab)used to pass arguments to pluggable transports. This method receives these arguments and parses them. As argument, we only expect a UniformDH shared secret. """ log.debug("Received the following arguments over SOCKS: %s." % args) if len(args) != 1: raise base.SOCKSArgsError("Too many SOCKS arguments " "(expected 1 but got %d)." % len(args)) # The ScrambleSuit specification defines that the shared secret is # called "password". if not args[0].startswith("password="******"The SOCKS argument must start with " "`password='******'=')[1].strip())) except TypeError as error: log.error(error.message) raise base.PluggableTransportError("Given password '%s' is not " \ "valid Base32! Run 'generate_password.py' to generate " \ "a good password." % args[0].split('=')[1].strip()) rawLength = len(self.uniformDHSecret) if rawLength != const.SHARED_SECRET_LENGTH: raise base.PluggableTransportError( "The UniformDH password " "must be %d bytes in length but %d bytes are given." % (const.SHARED_SECRET_LENGTH, rawLength)) self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)
def handle_socks_args(self, args): """ Receive arguments `args' passed over a SOCKS connection. The SOCKS authentication mechanism is (ab)used to pass arguments to pluggable transports. This method receives these arguments and parses them. As argument, we only expect a UniformDH shared secret. """ log.debug("Received the following arguments over SOCKS: %s." % args) if len(args) != 1: raise base.SOCKSArgsError("Too many SOCKS arguments " "(expected 1 but got %d)." % len(args)) # The ScrambleSuit specification defines that the shared secret is # called "password". if not args[0].startswith("password="******"The SOCKS argument must start with " "`password='******'%s' is not " "valid Base32! Run 'generate_password.py' to generate " "a good password." % args[0].split("=")[1].strip() ) rawLength = len(self.uniformDHSecret) if rawLength != const.SHARED_SECRET_LENGTH: raise base.PluggableTransportError( "The UniformDH password " "must be %d bytes in length but %d bytes are given." % (const.SHARED_SECRET_LENGTH, rawLength) ) self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer)
def test4_extractPublicKey( self ): # Create UniformDH authentication message. sharedSecret = "A" * const.SHARED_SECRET_LENGTH realEpoch = util.getEpoch # Try three valid and one invalid epoch value. for epoch in util.expandedEpoch() + ["000000"]: udh = uniformdh.new(sharedSecret, True) util.getEpoch = lambda: epoch authMsg = udh.createHandshake() util.getEpoch = realEpoch buf = obfs_buf.Buffer() buf.write(authMsg) if epoch == "000000": self.assertFalse(udh.extractPublicKey(buf)) else: self.assertTrue(udh.extractPublicKey(buf))
def setUp( self ): weAreServer = True self.udh = uniformdh.new("A" * const.SHARED_SECRET_LENGTH, weAreServer)
def __init__( self, transportConfig ): """ Initialise a ScrambleSuitTransport object. """ log.error("\n\n################################################\n" "Do NOT rely on ScrambleSuit for strong security!\n" "################################################\n") log.debug("Initialising %s." % const.TRANSPORT_NAME) util.setStateLocation(transportConfig.getStateLocation()) # Load the server's persistent state from file. if self.weAreServer: self.srvState = state.load() # Initialise the protocol's state machine. log.debug("Switching to state ST_WAIT_FOR_AUTH.") self.protoState = const.ST_WAIT_FOR_AUTH # Buffers for incoming and outgoing data. self.sendBuf = self.recvBuf = "" # Buffer for inter-arrival time obfuscation. self.choppingBuf = "" # AES instances to decrypt incoming and encrypt outgoing data. self.sendCrypter = mycrypto.PayloadCrypter() self.recvCrypter = mycrypto.PayloadCrypter() # Packet morpher to modify the protocol's packet length distribution. self.pktMorpher = packetmorpher.new(self.srvState.pktDist if self.weAreServer else None) # Inter-arrival time morpher to obfuscate inter arrival times. self.iatMorpher = self.srvState.iatDist if self.weAreServer else \ probdist.new(lambda: random.random() % const.MAX_PACKET_DELAY) if self.weAreServer: # `True' if the ticket is already decrypted but not yet # authenticated. self.decryptedTicket = False if not hasattr(self, 'uniformDHSecret'): # As the server, we get the shared secret from the constructor. cfg = transportConfig.getServerTransportOptions() self.uniformDHSecret = base64.b32decode(cfg["password"]) self.uniformDHSecret = self.uniformDHSecret.strip() else: # As the client, we get the shared secret from obfsproxy calling # `handle_socks_args()'. if not hasattr(self, 'uniformDHSecret'): self.uniformDHSecret = None self.uniformdh = uniformdh.new(self.uniformDHSecret, self.weAreServer) # Variables used to unpack protocol messages. self.totalLen = self.payloadLen = self.flags = None