def recv(self, nb=False):
     if self.authenticated == True:
         ct = self.server.recv() if not nb else self.server.nb_recv()
         if ct is None:
             return None
         log(
             logging.info,
             self,
             self.recv,
             "Ciphertext received: {}".format(ct)
         )
         pt = crypto.decrypt(self._session_key, ct)
         log(
             logging.info,
             self,
             self.recv,
             "Ciphertext decrypted to: {}".format(pt)
         )
         return pt
     else:
         raise NoAuthentication("No Authentication Established")
    def mutauth_step(self, reset=False):
        if reset:
            self._mutau_state = self.MUTUAL_AUTH_STATES[-1]
            return

        if self._shared_key is None:
            raise NoSharedKey("Shared key is not setup yet. Can't proceed")

        if self._mutau_state == self.MUTUAL_AUTH_STATES[-1]:
            log(
                logging.info,
                self,
                self.mutauth_step,
                "server receive client's ra"
            )
            self._Ra = self.server.recv()
            
            self._mutau_state = self.MUTUAL_AUTH_STATES[0]
        elif self._mutau_state == self.MUTUAL_AUTH_STATES[0]:
            # Send response: RB, E("Bob", RA, gb mod p, KAB)
            self._Rb = os.urandom(crypto.BLOCK_SIZE)
            gb_mod_p = pow(self._g, self._secret_value, self._p)
            pt = self._identifier + self._Ra + str(gb_mod_p)
            ct = crypto.encrypt(self._shared_key, pt)
            msg = self._Rb + ct
            self.client.send(msg)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "server sends rb + its identifier, rb, and gb mod p"
            )

            self._mutau_state = self.MUTUAL_AUTH_STATES[1]
        elif self._mutau_state == self.MUTUAL_AUTH_STATES[1]:
            # Receive E("Alice", RB, ga mod p, KAB)
            ct = self.server.recv()
            pt = crypto.decrypt(self._shared_key, ct)
            identifier, rb, ga_mod_p = self.extract_auth_msg_parts(pt)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "server receives client's identifier, rb, and ga mod p"
            )

            if rb != self._Rb:
                raise BeingAttacked("Trudy is attacking")
            if identifier == self._identifier:
                raise BeingAttacked("Trudy is doing replay attack")

            self._session_key = pow(long(ga_mod_p), self._secret_value, self._p)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "server creates the session key"
            )

            self._mutau_state = self.MUTUAL_AUTH_STATES[2]
            self._session_key = crypto.derive_new_key(str(self._session_key))
        elif self._mutau_state == self.MUTUAL_AUTH_STATES[2]:
            raise StopIteration("Authentication completed successfully.")
    def mutauth_step(self, reset=False):
        """This method steps through mutual authentication 
            and key exchange using Diffie-Helman

        Each call to this method will perform one step out of the
         total steps necessary for authentication

        :param bool reset: If this is set, we reset back to step -1
        """
        if reset:
            self._mutau_state = self.MUTUAL_AUTH_STATES[-1]
            return

        if self._shared_key is None:
            raise NoSharedKey("Shared key is not setup yet. Can't proceed")

        if self._mutau_state == self.MUTUAL_AUTH_STATES[-1]:
            # Send our public key (Ra)
            self._Ra = os.urandom(crypto.BLOCK_SIZE)
            self.client.send(self._Ra)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "Client sends Ra"
            )

            self._mutau_state = self.MUTUAL_AUTH_STATES[0]
        elif self._mutau_state == self.MUTUAL_AUTH_STATES[0]:
            # Get response: RB, E("Bob", RA, gb mod p, KAB)
            resp = self.server.recv()
            self._rb = resp[:crypto.BLOCK_SIZE]
            log(
                logging.info,
                self,
                self.mutauth_step,
                "client receives rb"
            )
            ct = resp[crypto.BLOCK_SIZE:]
            pt = crypto.decrypt(self._shared_key, ct)
            self._server_ident, ra, gb_mod_p = self.extract_auth_msg_parts(pt)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "client receives identifier of server, ra, and gb mod p"
            )

            if ra != self._Ra:
                raise BeingAttacked("Trudy is attacking")

            self._session_key = pow(long(gb_mod_p), self._secret_value, self._p)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "client creates the session key"
            )

            self._mutau_state = self.MUTUAL_AUTH_STATES[1]
        elif self._mutau_state == self.MUTUAL_AUTH_STATES[1]:
            # Send E("Alice", RB, ga mod p, KAB)

            # Client identifier can be anything other the the server's ident
            identifier = os.urandom(crypto.BLOCK_SIZE)
            while identifier == self._server_ident:
                identifier = os.urandom(crypto.BLOCK_SIZE)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "client creates its identifier that's not the same as server's"
            )
 
            ga_mod_p = pow(self._g, self._secret_value, self._p)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "client creates ga mod p"
            )
 
            pt = identifier + self._rb + str(ga_mod_p)
            log(
                logging.info,
                self,
                self.mutauth_step,
                "client sends its identifier, the server's rb, and ga mod p"
            )
 
            ct = crypto.encrypt(self._shared_key, pt) 
            self.client.send(ct)
            
            self._mutau_state = self.MUTUAL_AUTH_STATES[2]
            self._session_key = crypto.derive_new_key(str(self._session_key))
        elif self._mutau_state == self.MUTUAL_AUTH_STATES[2]:

            raise StopIteration("Authentication completed successfully.")