Just use the base64 program from the coreutils package:
echo QWxhZGRpbjpvcGVuIHNlc2FtZQ== | base64 --decode
Or, to include the newline character
echo `echo QWxhZGRpbjpvcGVuIHNlc2FtZQ== | base64 --decode`
output (includes newline):
Aladdin:open sesame
Answer from January on askubuntu.comJust use the base64 program from the coreutils package:
echo QWxhZGRpbjpvcGVuIHNlc2FtZQ== | base64 --decode
Or, to include the newline character
echo `echo QWxhZGRpbjpvcGVuIHNlc2FtZQ== | base64 --decode`
output (includes newline):
Aladdin:open sesame
openssl can also encode and decode base64
$ openssl enc -base64 <<< 'Hello, World!'
SGVsbG8sIFdvcmxkIQo=
$ openssl enc -base64 -d <<< SGVsbG8sIFdvcmxkIQo=
Hello, World!
EDIT: An example where the base64 encoded string ends up on multiple lines:
$ openssl enc -base64 <<< 'And if the data is a bit longer, the base64 encoded data will span multiple lines.'
QW5kIGlmIHRoZSBkYXRhIGlzIGEgYml0IGxvbmdlciwgdGhlIGJhc2U2NCBlbmNv
ZGVkIGRhdGEgd2lsbCBzcGFuIG11bHRpcGxlIGxpbmVzLgo=
$ openssl enc -base64 -d << EOF
> QW5kIGlmIHRoZSBkYXRhIGlzIGEgYml0IGxvbmdlciwgdGhlIGJhc2U2NCBlbmNv
> ZGVkIGRhdGEgd2lsbCBzcGFuIG11bHRpcGxlIGxpbmVzLgo=
> EOF
And if the data is a bit longer, the base64 encoded data will span multiple lines.
How to decode Base64 in Linux?
Converting a base64 string generated on a Linux server by PowerShell on Windows
shell - How to encode and decode data in base64 and base64URL by using unix commands? - Stack Overflow
Stupid Linux tricks - use base64 to perfectly preserve formatting when copy/pasting between terminals, ssh sessions, serial connections, etc.
Hey all,I have a base64 value that I generated on Linux like so:
echo 'test is a test' | base64 dGVzdCBpcyBhIHRlc3QK echo 'dGVzdCBpcyBhIHRlc3QK' | base64 --decode test is a test
But when I try to decode the string on Windows using PowerShell I'm getting a different result:
[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('dGVzdCBpcyBhIHRlc3QK'))
整瑳椠整瑳�Suggestions?
Thanks!
EDIT: This solution in the comments worked for me:
[System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String('dGVzdCBpcyBhIHRlc3QK'))
tl;dr
Use basenc(1) from coreutils:
$ printf "xs?>>>" | basenc --base64
eHM/Pj4+
$ printf "xs?>>>" | basenc --base64url
eHM_Pj4-
As with base64(1), add the -d switch to decode.
A bit of explanation
Recent versions of coreutils include basenc(1) which supports several different encodings. From its help screen:
--base64 same as 'base64' program (RFC4648 section 4)
--base64url file- and url-safe base64 (RFC4648 section 5)
--base32 same as 'base32' program (RFC4648 section 6)
--base32hex extended hex alphabet base32 (RFC4648 section 7)
--base16 hex encoding (RFC4648 section 8)
--base2msbf bit string with most significant bit (msb) first
--base2lsbf bit string with least significant bit (lsb) first
--z85 ascii85-like encoding (ZeroMQ spec:32/Z85);
when encoding, input length must be a multiple of 4;
when decoding, input length must be a multiple of 5
Here is a string that illustrates the difference:
s="xs?>>>"
As binary:
$ printf "%s" "$s" | xxd -b -c1 | cut -d' ' -f2 | nl
1 01111000
2 01110011
3 00111111
4 00111110
5 00111110
6 00111110
And as 6 bit blocks (as base64 reads the data):
$ printf "%s" "$s" | xxd -b -c1 | cut -d' ' -f2 | tr -d '\n' | fold -w6 | nl
1 011110
2 000111
3 001100
4 111111
5 001111
6 100011
7 111000
8 111110
Note that block 4 and block 8 map to / and + respectively (Base64 table on Wikipedia):
This is the same suggestion as @jps but shorter. Also remember that echo by default always adds newline at the end, so when you want to encode it, you must add -n.
echo -n "Some_data_to_be_converted" | base64 | tr '/+' '_-' | tr -d '='
Decoding it back with bulit-in bash tools is more complicated as I didn't find an easy way to pad the string back with '=' so that the length will dividable by 4. Probably can be done with awk but I didn't dig deep enough. If you have local ruby it becomes trivial:
2.6.2 > require 'base64'
2.6.2 > Base64.urlsafe_encode64('test', padding: false)
=> "dGVzdA"
2.6.2 > Base64.urlsafe_decode64('dGVzdA')
=> "test"
Here's another example of "what's old is new again" - remember how a long time ago, you interacted with a modem by giving it textual commands, and then it connected you to distant machines, which you also spoke to in text, and when you wanted to send and receive binary files, you had to encode those as text too?
Well, that still works, and the commands needed to encode/decode it are installed by default pretty much everywhere, so that means you can...
-
Suppose there's some system you connect to through a VPN and then two jump boxes. You've ssh'd all the way there, but were lazy and didn't bother port-forwarding (if that's even allowed), and now you need to get a copy of some config file. Instead of copy/pasting it a bit at a time, or trying to make your scrollback buffer and text wrapping cooperate (and still convert tabs to weird numbers of spaces...), you can:
on the sending side: cat file.conf | base64
Now you don't have to worry about formatting at all*! Just copy all the base64 text as a block, and on the receive side: base64 -d > file.conf_from_remote
now paste the text, press enter, then ctrl+d when you're done, and you have a binary-identical copy of the file on your local system, regardless of how many spaces, newlines, and messed up terminal wrapping you copied.
-
* The caveat: sometimes you'll run into this on decode: "base64: invalid input". In that case, try
base64 -dias the decode command - for some weird reason, certain versions of the base64 utility can't even decode their own input by default, because they decide to insert newlines on encode, but barf immediately on any non-base64 character on decode...including newlines. I have seen this behaviour primarily on old Gentoo boxes, Solaris, and ancient versions of CentOS and Red Hat. -
Doesn't even have to be a remote system of course. I use this sometimes when I can't be arsed to deal with
sudo/chmod/chownwhen copying a file between sessions running as different restricted users, or across a chroot, container, VM, etc.
Next trick:
Suppose you're editing a file locally and you want to copy a piece of a remote file, and it's very important to exactly preserve the indenting and whitespace (because it's python, yaml, or you've forgotten about ":set paste" in vim and internalised the notion that auto-indent is forever...but "set paste" doesn't help you with tabs not surviving a terminal display anyway). You can do this:
shift+V to go to visual select line mode; select the block you want
type :! base64 <enter>
copy & paste the block into your other vim, then select the base64 text
type :! base64 -d <enter>
and there it is, in all its tabular/nonprinting/emoji/16-bit-big-endian-unicode-because-why-not glory. (You'll want to undo the encode step on the source system, obviously.)
Don't believe me that it's 100% binary identical? Select the text blocks on both sides and check:
:! md5sum
[Edit: Important note about md5sum - it is only useful as a casual check against random errors nowadays, it is not a secure or cryptographic hash by any means. Think of it like a "deluxe crc32"; using it in interactive contexts like this is fine, but do not use it in scripts, etc.]
(Incidentally, if the block of text you want is really small or your local one is very similar already, you can skip the base64 and just edit it manually and just use md5sum to confirm you got it right.)
If your file or block of text is longer than a screenful
Pipe it to gzip first:
cat file.txt | gzip -9 | base64
base64 -d | gunzip > file.txt_copy
(For very small inputs, gzip often produces slightly fewer bytes than xz and even zstd, plus it's available practically everywhere.)
You can also scrunch down the base64 a little more by setting the line-width to unlimited (base64 -w 0), but be aware that:
-
Some implementations are buggy when it comes to very long lines (the opposite problem of the earlier caveat).
-
Even if the base64 command is OK with it, sometimes the terminal program isn't.
-
4096 bytes per line is a common threshold at which something barfs.
-
It can make the copy/pasting more error-prone, as it's easier to miss a single character somewhere (and if you accidentally paste it in the wrong place, it makes more of a mess... on the other hand, at least your shell history will only have one bogus entry on accidental paste instead of 150. Ask me how many times I've seen "
-bash: H4sIAAAAAAACAxXJQQ6AIAxE0b2nmJu49RoVxmgiLaFFw+2V3X/5m71IooiTUAakWNeAHaBGszpm: No such file or directory -bash: ztn1etic2Iki7r/ugczUKM68Lh893ENmSgAAAA==: No such file or directory" :P).
Important note for sysadmins and especially network people
I mentioned serial connections at the beginning of this. I cannot believe how many times I've see people laboriously copy a few lines at a time, paste them into their terminal window, wait (9600 8 N 1 only goes so fast, y'all...), copy a few more... and then cross their fingers and pray that no characters got lost, and none of the accidental extra whitespace will matter, when restoring a switch configuration.
The civilised way to do this is to be in shell mode on the switch instead of config mode (and if your switches don't have a basic Linux-like shell, consider switching to some that do), and do a base64 copy/paste as described, and then compare checksums. Especially if gzip is available on the switch, this is much, much faster and more reliable, and then you can do a local "load config" and not have any terminal issues in config mode.
(Some may argue that transferring over tftp or some variant of DHCP-mediated auto-provision is "more civilised", but 1, you're in this situation because your network is buggered so that might not be an option, and 2, I bet if you held a race, the base64 person would be done long before the tftp person has even finished the "how the crap do I get this server listening again?! why is it not serving files?!" stage of cursing, never mind the "I fat-fingered a subnet mask" or "oh yeah, we block tftp at the firewall for this subnet now, don't we?" stages of cursing.)
If your remote system is weird and doesn't have a base64 command
Good chance it still does and it's just part of something else. Hint: openssl has it built in (openssl base64 is equivalent to base64) if that's available (e.g. Juniper switches I think). openssl md5 also works if you're missing md5sum, but also try just md5, because it's called that on some unixes (I want to say Juniper switches again? or Mac OS?).