def _build_pub_key_auth(self, context, nonce, auth_token, public_key):
        """
        [MS-CSSP] 3.1.5 Processing Events and Sequencing Rules - Step 3
        https://msdn.microsoft.com/en-us/library/cc226791.aspx

        This step sends the final SPNEGO token to the server if required and
        computes the value for the pubKeyAuth field for the protocol version
        negotiated.

        The format of the pubKeyAuth field depends on the version that the
        server supports.

        For version 2 to 4:
        The pubKeyAuth field is just wrapped using the authenticated context

        For versions 5 to 6:
        The pubKeyAuth is a sha256 hash of the server's public key plus a nonce
        and a magic string value. This hash is wrapped using the authenticated
        context and the nonce is added to the TSRequest alongside the nonce
        used in the hash calcs.

        :param context: The authenticated context
        :param nonce: If versions 5+, the nonce to use in the hash
        :param auth_token: If NTLM, this is the last msg (authenticate msg) to
            send in the same request
        :param public_key: The server's public key
        :return: The TSRequest as a byte string to send to the server
        """
        ts_request = TSRequest()

        if auth_token is not None:
            nego_token = NegoToken()
            nego_token['negoToken'] = auth_token
            ts_request['negoTokens'].append(nego_token)

        if nonce is not None:
            ts_request['clientNonce'] = nonce
            hash_input = b"CredSSP Client-To-Server Binding Hash\x00" + \
                         nonce + public_key
            pub_value = hashlib.sha256(hash_input).digest()
        else:
            pub_value = public_key

        enc_public_key = context.wrap(pub_value)
        ts_request['pubKeyAuth'] = enc_public_key

        return encoder.encode(ts_request)