diff --git a/lib/oauth_util.rb b/lib/oauth_util.rb
index a98cb686e7adf815c13195b3a65179deaec70571..ba223d4e3b71ba011219ccfc2c3154f22721d75c 100644
--- a/lib/oauth_util.rb
+++ b/lib/oauth_util.rb
@@ -56,7 +56,7 @@ class OauthUtil
   def query_string
     pairs = []
     @params.sort.each { | key, val | 
-      pairs.push( "#{ percent_encode( key ) }=#{ percent_encode( val.to_s ) }" )
+      pairs.push( "#{ CGI.escape(key.to_s).gsub(/%(5B|5D)/n) { [$1].pack('H*') } }=#{ CGI.escape(val.to_s) }" )
     }
     pairs.join '&'
   end
diff --git a/test/oauth_util_test.rb b/test/oauth_util_test.rb
new file mode 100644
index 0000000000000000000000000000000000000000..78dea62ca494e6af81cb0978c962ee9468d99162
--- /dev/null
+++ b/test/oauth_util_test.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+require 'test_helper'
+require 'cgi'
+require 'uri'
+
+class OauthUtilTest < Test::Unit::TestCase
+  def test_query_string_escapes_single_quote
+    base_url = "http://example.com?location=d%27iberville"
+
+    o = OauthUtil.new
+    o.consumer_key = 'consumer_key'
+    o.consumer_secret = 'consumer_secret'
+
+    query_string = o.sign(URI.parse(base_url)).query_string
+
+    assert_match "location=d%27iberville", query_string
+  end
+
+  def test_query_string_sorts_url_keys
+    base_url = "http://example.com?a_param=a&z_param=b&b_param=c&n_param=d"
+
+    o = OauthUtil.new
+    o.consumer_key = 'consumer_key'
+    o.consumer_secret = 'consumer_secret'
+
+    query_string = o.sign(URI.parse(base_url)).query_string
+
+    assert_match /.*a_param=.*b_param=.*n_param=.*z_param=.*/, query_string
+  end
+end