Issue #10740 has been updated by Scott Blum.


I suspect the reason the spec is that way is that it's easier to calculate what the decoded length will be if the encoding is always divisible by 4, since it's just `(encoded_len / 4) * 3`.  It makes more since in the context of wire protocols such as email MIME where base64 originally came from.  In a language like Ruby where strings have lengths the data length is always known so I suspect it's less relevant.

It is worth noting that SecureRandom.urlsafe_base64 has an optional `padding` parameter which defaults to false.  I think ideally we should follow that example, and default to no padding on the encode side.  But if that's too risky we could default padding to false to maintain the current behavior.

On the decoding side, it seems like a no-brainer to be lenient and fill in the proper padding.  Otherwise, you have the bizarre situation where: 

`Base64.urlsafe_decode64(SecureRandom.urlsafe_base64(len) # raises if len % 3 != 0`


----------------------------------------
Feature #10740: Base64 urlsafe methods are not urlsafe
https://bugs.ruby-lang.org/issues/10740#change-51011

* Author: Scott Blum
* Status: Feedback
* Priority: Normal
* Assignee: Yusuke Endoh
----------------------------------------
Base64.urlsafe_decode64 is not to spec, because it currently REQUIRES appropriate trailing '=' characters.
Base64.urlsafe_encode64 produces trailing '=' characters.

'=' is not web safe, and is not recommended for base64url.  Some specs even disallow.

Suggested fix:

~~~
  # Returns the Base64-encoded version of +bin+.
  # This method complies with ``Base 64 Encoding with URL and Filename Safe
  # Alphabet'' in RFC 4648.
  # The alphabet uses '-' instead of '+' and '_' instead of '/'
  # and has no trailing pad characters.
  def urlsafe_encode64(bin)
    strict_encode64(bin).tr("+/", "-_").tr('=', '')
  end

  # Returns the Base64-decoded version of +str+.
  # This method complies with ``Base 64 Encoding with URL and Filename Safe
  # Alphabet'' in RFC 4648.
  # The alphabet uses '-' instead of '+' and '_' instead of '/'.
  # Trailing pad characters are optional.
  def urlsafe_decode64(str)
    str = str.tr("-_", "+/")
    str = str.ljust((str.length + 3) & ~3, '=')
    strict_decode64(str)
  end
~~~


---Files--------------------------------
base64-urlsafe-encode64-search-result.txt (19.9 KB)


-- 
https://bugs.ruby-lang.org/