165
$ echo -n "apfjxkic-omyuobwd339805ak:60a06cd2ddfad610b9490d359d605407" | base64
YXBmanhraWMtb215dW9id2QzMzk4MDVhazo2MGEwNmNkMmRkZmFkNjEwYjk0OTBkMzU5ZDYwNTQw
Nw==

The output has a return before Nw==. What is the correct way to generate base64 in Linux?

terminal screenshot

12
  • 6
    Are you certain the output contains a newline, and it's not just your window wrapping? That command worked fine for me on mac. What OS are you using?
    – Ian
    Jul 3, 2017 at 5:10
  • 51
    RFC 2045, which defined Base64, REQUIRES a newline after 76 characters (max). What makes you think your example is not the correct way?
    – MSalters
    Jul 3, 2017 at 8:40
  • 31
    @MSalters RFC 4648 specifically addresses that issue. Implementations MUST NOT add line feeds to base-encoded data unless the specification referring to this document explicitly directs base encoders to add line feeds after a specific number of characters. => this implementation is incorrect according to RFC 4648, as long as it claims to produce 'plain' base64-encoded output. More interestingly, GNU base64 (in question?) manpages specifically refers to RFC 3548, which also specifies no wrapping by default, and which RFC 4648 obsoletes.
    – Bob
    Jul 3, 2017 at 10:46
  • 4
    @Bob: RFC's have a bit less respect for API stability; a base64 tool can't just change its output format without breaking scripts.
    – MSalters
    Jul 4, 2017 at 6:44
  • 3
    @MSalters I cannot be certain an older version does not exist, but GNU base64 was written in 2004 and AFAICT always claimed to follow RFC 3548. RFC 3548 contains the same "MUST NOT add line feeds" clause. So even the original implementation was "wrong". At the very least, its implementation does not match its documentation. Anyway, you asked for why OP's example is correct and referenced an RFC; my response is the correct RFC that actually defines base64 in isolation. If your answer is "for historical reasons", so be it, but OP isn't wrong here.
    – Bob
    Jul 4, 2017 at 7:05

2 Answers 2

288

Try:

echo -n "apfjxkic-omyuobwd339805ak:60a06cd2ddfad610b9490d359d605407" | base64 -w 0

From man base64:

-w, --wrap=COLS
Wrap encoded lines after COLS character (default 76). Use 0 to disable line wrapping.

A likely reason for 76 being the default is that Base64 encoding was to provide a way to include binary files in e-mails and Usenet postings which was intended for humans using monitors with 80 characters width. Having a 76-character width as default made that usecase easier.

10
  • 27
    Oh man, I always just piped this through tr. Good to know there's a "proper way". Jul 3, 2017 at 17:05
  • The explanation about why the default value is not zero is a mistery for me.
    – Dherik
    Jul 25, 2019 at 21:01
  • 3
    @Dherik I guess it's courtesy towards text processing tools. base64 encodes arbitrary binary data as text. Tools that expect text usually read one line at a time and may not deal with very long lines well. If -w 0 was the default, you would get by default just one line of text; an enormously long line if the input was large. It's better to wrap by default. I think 76 was chosen because it's little less than 80 which is a sort of de-facto standard for terminals. Jul 25, 2019 at 21:32
  • @KamilMaciorowski thank you for the information. Every time that I used the base64 command I needed to pass the -w 0 (and when I forgot, weird things can happen...), so this default behaviour was very strange to me.
    – Dherik
    Jul 25, 2019 at 21:35
  • 2
    @Dherik A likely reason is that base64 encoding was to provide a way to include binary files in emails and usenet postings which was intended for humans using monitors with 80 characters width. Having a 76-character width as default made that usecase easier. Jan 20, 2020 at 6:19
81

On systems where the -w option to base64 is not available (e.g. Alpine Linux, an Arch Linux initramfs hook, etc.), you can manually process the output of base64:

base64 some_file.txt | tr -d \\n

This is the brute-force approach; instead of getting the program to co-operate, I am using tr to indiscriminately strip every newline on stdout.

3
  • 3
    Always use the hammer when available.
    – dna
    Sep 16, 2020 at 11:56
  • 1
    The following was useful for "correcting" a base64-encoded value: echo 'dGVzdAo=' | base64 -d | tr -d \\n | base64 Mar 16, 2021 at 0:32
  • Not inferior, just a different and often only approach. As you said there are plenty of systems out there without the -w option, including MacOSX..
    – nnsense
    Nov 1, 2021 at 20:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.