# File lib/openid/consumer.rb, line 637
    def associate(server_url)
      dh = OpenID::DiffieHellman.new
      cpub = OpenID::Util.to_base64(OpenID::Util.num_to_str(dh.public))
      args = {
        'openid.mode' => 'associate',
        'openid.assoc_type' =>'HMAC-SHA1',
        'openid.session_type' =>'DH-SHA1',
        'openid.dh_modulus' => OpenID::Util.to_base64(OpenID::Util.num_to_str(dh.p)),
        'openid.dh_gen' => OpenID::Util.to_base64(OpenID::Util.num_to_str(dh.g)),
        'openid.dh_consumer_public' => cpub
      }
      body = OpenID::Util.urlencode(args)
      
      ret = @fetcher.post(server_url, body)
      return nil if ret.nil?
      url, data = ret
      results = OpenID::Util.parsekv(data)
      
      assoc_type = results["assoc_type"]
      return nil if assoc_type.nil? or assoc_type != "HMAC-SHA1"
      
      assoc_handle = results["assoc_handle"]
      return nil if assoc_handle.nil?    
      
      expires_in = results.fetch("expires_in", "0").to_i

      session_type = results["session_type"]
      if session_type.nil?
        secret = OpenID::Util.from_base64(results["mac_key"])
      else
        return nil if session_type != "DH-SHA1"
        
        dh_server_public = results["dh_server_public"]
        return nil if dh_server_public.nil?
        
        spub = OpenID::Util.str_to_num(OpenID::Util.from_base64(dh_server_public))
        dh_shared = dh.get_shared_secret(spub)
        enc_mac_key = results["enc_mac_key"]
        secret = OpenID::Util.strxor(OpenID::Util.from_base64(enc_mac_key),
                                     OpenID::Util.sha1(OpenID::Util.num_to_str(dh_shared)))
      end
   
      assoc = OpenID::Association.from_expires_in(expires_in, assoc_handle,
                                                  secret, 'HMAC-SHA1')
      @store.store_association(server_url, assoc)
      return assoc
    end