<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def auth(self):
 """Authenticate using the SOAP interface. Authentication is a two-step process. First a initial payload is sent to the device requesting additional login information in the form of a publickey, a challenge string and a cookie. These values are then hashed by a MD5 algorithm producing a privatekey used for the header and a hashed password for the XML payload. If everything is accepted the XML returned will contain a LoginResult tag with the string 'success'. See https://github.com/bikerp/dsp-w215-hnap/wiki/Authentication-process for more information. """


        payload = self.initial_auth_payload()

        # Build initial header
        headers = {'Content-Type' : '"text/xml; charset=utf-8"',
           'SOAPAction': '"http://purenetworks.com/HNAP1/Login"'}

        # Request privatekey, cookie and challenge
        try:
            response = urlopen(Request(self.url, payload, headers))
        except URLError:
            if self._error_report is False:
                _LOGGER.warning('Unable to open a connection to dlink switch {}'.format(self.ip))
                self._error_report = True
            return None
        xmlData = response.read().decode()
        root = ET.fromstring(xmlData)

        # Find responses
        ChallengeResponse = root.find('.//{http://purenetworks.com/HNAP1/}Challenge')
        CookieResponse = root.find('.//{http://purenetworks.com/HNAP1/}Cookie')
        PublickeyResponse = root.find('.//{http://purenetworks.com/HNAP1/}PublicKey')

        if (ChallengeResponse == None or CookieResponse == None or PublickeyResponse == None) and self._error_report is False:
            _LOGGER.warning("Failed to receive initial authentication from smartplug.")
            self._error_report = True
            return None

        if self._error_report is True:
            return None

        Challenge = ChallengeResponse.text
        Cookie = CookieResponse.text
        Publickey = PublickeyResponse.text

        # Generate hash responses
        PrivateKey = hmac.new((Publickey+self.password).encode(), (Challenge).encode()).hexdigest().upper()
        login_pwd = hmac.new(PrivateKey.encode(), Challenge.encode()).hexdigest().upper()

        response_payload = self.auth_payload(login_pwd)
        # Build response to initial request
        headers = {'Content-Type' : '"text/xml; charset=utf-8"',
           'SOAPAction': '"http://purenetworks.com/HNAP1/Login"',
           'HNAP_AUTH' : '"{}"'.format(PrivateKey),
           'Cookie' : 'uid={}'.format(Cookie)}
        response = urlopen(Request(self.url, response_payload, headers))
        xmlData = response.read().decode()
        root = ET.fromstring(xmlData)

        # Find responses
        login_status = root.find('.//{http://purenetworks.com/HNAP1/}LoginResult').text.lower()

        if login_status != "success" and self._error_report is False:
            _LOGGER.error("Failed to authenticate with SmartPlug {}".format(self.ip))
            self._error_report = True
            return None

        self._error_report = False # Reset error logging
        return (PrivateKey, Cookie)