diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 86bad9d..7fa029b 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -321,6 +321,14 @@ class Gem::RemoteFetcher
     response['content-length'].to_i
   end
 
+  def escape_auth_info(str)
+    str && URI.encode_www_form_component(str)
+  end
+
+  def unescape_auth_info(str)
+    str && URI.decode_www_form_component(str)
+  end
+
   def escape(str)
     return unless str
     @uri_parser ||= uri_escaper
@@ -362,8 +370,8 @@ class Gem::RemoteFetcher
 
     if uri and uri.user.nil? and uri.password.nil? then
       # Probably we have http_proxy_* variables?
-      uri.user = escape(ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER'])
-      uri.password = escape(ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS'])
+      uri.user = escape_auth_info(ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER'])
+      uri.password = escape_auth_info(ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS'])
     end
 
     uri
@@ -387,8 +395,8 @@ class Gem::RemoteFetcher
       net_http_args += [
         @proxy_uri.host,
         @proxy_uri.port,
-        @proxy_uri.user,
-        @proxy_uri.password
+        unescape_auth_info(@proxy_uri.user),
+        unescape_auth_info(@proxy_uri.password)
       ]
     end
 
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index d3cc388..a96deaa 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -438,7 +438,7 @@ gems:
       uri.user, uri.password = 'domain%5Cuser', 'bar'
       fetcher = Gem::RemoteFetcher.new uri.to_s
       proxy = fetcher.instance_variable_get("@proxy_uri")
-      assert_equal 'domain\user', fetcher.unescape(proxy.user)
+      assert_equal 'domain\user', fetcher.unescape_auth_info(proxy.user)
       assert_equal 'bar', proxy.password
       assert_data_from_proxy fetcher.fetch_path(@server_uri)
     end
@@ -449,7 +449,7 @@ gems:
       fetcher = Gem::RemoteFetcher.new uri.to_s
       proxy = fetcher.instance_variable_get("@proxy_uri")
       assert_equal 'user', proxy.user
-      assert_equal 'my pass', fetcher.unescape(proxy.password)
+      assert_equal 'my pass', fetcher.unescape_auth_info(proxy.password)
       assert_data_from_proxy fetcher.fetch_path(@server_uri)
     end
   end
@@ -472,8 +472,19 @@ gems:
       ENV['http_proxy_pass'] = 'my bar'
       fetcher = Gem::RemoteFetcher.new nil
       proxy = fetcher.instance_variable_get("@proxy_uri")
-      assert_equal 'foo\user', fetcher.unescape(proxy.user)
-      assert_equal 'my bar', fetcher.unescape(proxy.password)
+      assert_equal 'foo\user', fetcher.unescape_auth_info(proxy.user)
+      assert_equal 'my bar', fetcher.unescape_auth_info(proxy.password)
+      assert_data_from_proxy fetcher.fetch_path(@server_uri)
+    end
+
+    use_ui @ui do
+      ENV['http_proxy'] = @proxy_uri
+      ENV['http_proxy_user'] = 'foo@user'
+      ENV['http_proxy_pass'] = 'my@bar'
+      fetcher = Gem::RemoteFetcher.new nil
+      proxy = fetcher.instance_variable_get("@proxy_uri")
+      assert_equal 'foo@user', fetcher.unescape_auth_info(proxy.user)
+      assert_equal 'my@bar', fetcher.unescape_auth_info(proxy.password)
       assert_data_from_proxy fetcher.fetch_path(@server_uri)
     end
   end
