Strange \n in base64 encoded string in Ruby
Asked Answered
C

6

193

The inbuilt Base64 library in Ruby is adding some '\n's. I'm unable to find out the reason. For this special example:

irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'base64'
=> true
irb(main):003:0> str =  "1110--ad6ca0b06e1fbeb7e6518a0418a73a6e04a67054"
=> "1110--ad6ca0b06e1fbeb7e6518a0418a73a6e04a67054"
irb(main):004:0> Base64.encode64(str)
=> "MTExMC0tYWQ2Y2EwYjA2ZTFmYmViN2U2NTE4YTA0MThhNzNhNmUwNGE2NzA1\nNA==\n"

The \n's are at the last and 6th position from end. The decoder (Base64.decode64) returns back the old string perfectly. Strange thing is, these \n's don't add any value to the encoded string. When I remove the newlines from the output string, the decoder decodes it again perfectly.

irb(main):005:0> Base64.decode64(Base64.encode64(str).gsub("\n", '')) == str
=> true

More of this, I used an another JS library to produce the base64 encoded output of the same input string, the output comes without the \n's.

Is this a bug or anything else? Has anybody faced this issue before?

FYI,

$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i486-linux]
Chaffin answered 12/4, 2010 at 9:30 Comment(1)
same weird problem hereThickset
P
284

Edit: Since I wrote this answer Base64.strict_encode64() was added, which does not add newlines.


The docs are somewhat confusing, the b64encode method is supposed to add a newline for every 60th character, and the example for the encode64 method is actually using the b64encode method.

It seems the pack("m") method for the Array class used by encode64 also adds the newlines. I would consider it a design bug that this is not optional.

You could either remove the newlines yourself, or if you're using rails, there's ActiveSupport::CoreExtensions::Base64::Encoding with the encode64s method.

Pisistratus answered 12/4, 2010 at 9:38 Comment(4)
Seems that since i wrote this answer there is now strict_encode64() which ostensibly does not add newlines.Carbon
So dumb! Why you do this to me, Ruby?Emmie
This is an assinie default, but as @ChristofferHammarström mentions, there's a way to get a true b64 encoding now.Tjirebon
Apparently this exists to maintain backwards compat with software that cannot handle long lines. https://mcmap.net/q/136642/-is-it-ok-to-remove-newline-in-base64-encodingGent
C
124

In ruby-1.9.2 you have Base64.strict_encode64 which doesn't add that \n (newline) at the end.

Cherilyncherilynn answered 13/1, 2011 at 12:32 Comment(3)
That's a much easier solution!Ul
I have checked Base64.strict_encode64 is not properly encoded three character string. like Base64.strict_encode64('abc') -> YWJj . the above example is not encoded correctly.Kimberykimble
@CodeMaker I thought YWJj is correct. What's wrong with that?Uriia
M
14

Use strict_encode64 method. encode64 adds \n every 60 symbols

Minor answered 1/2, 2018 at 13:19 Comment(1)
can we change it to add after 76 symbols ?Nucleonics
F
9

Yeah, this is quite normal. The doc gives an example demonstrating the line-splitting. base64 does the same thing in other languages too (eg. Python).

The reason content-free newlines are added at the encode stage is because base64 was originally devised as an encoding mechanism for sending binary content in e-mail, where the line length is limited. Feel free to replace them away if you don't need them.

Fungus answered 12/4, 2010 at 9:43 Comment(1)
This just happened in my Android App (Java's Base64 library). I was totally confused with this strange occuring. Took me literally 1 hour to figure out what's wrong and then searched for the error. This comment is helping understand legacy issues even after 6 years.Novel
G
6

Seems they've got to be stripped/ignored, like:

Base64.encode64(str).gsub(/\n/, '')
Grosswardein answered 22/2, 2013 at 15:28 Comment(2)
This solution is dirty.. anythein else?Afterbirth
@yaauie (via suggested edit): Edits that make a substantial change should generally not be done. I'd recommend posting that as a separate answer.Enrichment
O
2

The \n added when using Base64#encode64 is correct, check this post out: https://glaucocustodio.github.io/2014/09/27/a-reminder-about-base64encode64-in-ruby/

Octans answered 29/10, 2015 at 12:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.