# File lib/openid/server.rb, line 412
    def associate(args)
      assoc_type = args.fetch('openid.assoc_type', 'HMAC-SHA1')
      assoc = create_association(assoc_type)
      
      if assoc.nil?
        e = "unable to create association for type #{assoc_type}"
        return post_error(e)
      else
        @store.store_association(@normal_key, assoc)
      end

      reply = {
        'assoc_type' => 'HMAC-SHA1',
        'assoc_handle' => assoc.handle,
        'expires_in' => assoc.expires_in.to_s
      }

      session_type = args['openid.session_type']
      unless session_type.nil?
        if session_type == 'DH-SHA1'
          modulus = args['openid.dh_modulus']
          generator = args['openid.dh_gen']
          
          begin
            dh = OpenID::DiffieHellman.from_base64(modulus, generator)
          rescue
            e = "Please convert to two's comp correctly"
            return post_error(e)
          end

          consumer_public = args['openid.dh_consumer_public']
          if consumer_public.nil?
            return post_error('Missing openid.dh_consumer_public')
          end

          cpub = OpenID::Util.base64_to_num(consumer_public)
          if cpub < 0
            return post_error("Please convert to two's comp correctly")
          end
          
          dh_server_public = OpenID::Util.num_to_base64(dh.public)
          mac_key = dh.xor_secrect(cpub, assoc.secret)
          reply['session_type'] = session_type
          reply['dh_server_public'] = dh_server_public
          reply['enc_mac_key'] = OpenID::Util.to_base64(mac_key)
        else
          return post_error('session_type must be DH-SHA1')
        end
      else
        reply['mac_key'] = OpenID::Util.to_base64(assoc.secret)
      end

      return [REMOTE_OK, OpenID::Util.kvform(reply)]
    end