8

I am using Base64.encode64 to create a hash from HMAC used in an API request (an API that I did not develop). The generated hashes sometimes included a "+". The requests that included the "+" fail. Requests without succeed.

The same kind of script in Python, for example, never has a "+" in the Base64 encoded hash.

Below are the two snippets. Again, the Python never has a "+", the Ruby sometimes does.

Any ideas what is going on? How can I keep Ruby's base64 encoding from using "+" characters?

Ruby:

hmac = OpenSSL::HMAC.digest('sha256', hmackey, request_string)
signature = URI::encode(Base64.encode64(hmac))

Python:

hmac = hmac.new(self.hmackey, urltosign, digestmod=hashlib.sha256).digest()
signature = base64.b64encode(hmac)
Matt Fordham
  • 3,147
  • 10
  • 34
  • 51
  • 1
    + is a valid char in base64. Are these equivalent? I don't see the equivalent of your `URI::encode` step in the python, which will change all spaces to +'s also (post-base64) – Joe Mar 01 '14 at 00:22

2 Answers2

16

Python uses the RFC 3548 for the base64 conversion. Other languages like Ruby, Java(Possibly RFC 2045) they may be using different RFC for the conversion. So you may find few are using / and few are using + on their encoded string.

So if you then you need to match with them, just replace the characters with equivalent one after the encoding.

Community
  • 1
  • 1
Sabuj Hassan
  • 38,281
  • 14
  • 75
  • 85
9

To add to @Sabuj Hassan's great answer.

In Ruby you can do Base64.urlsafe_encode64 to comply to RFC 4648, which seems to be more universally useful.

From the docs

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 '/'.

Toby
  • 8,483
  • 13
  • 45
  • 68