0

I have two BASE64 encoded strings and I would like to get the BASE64 encoding of the binary concatenation of the two string using just the command line.

Example:

> $ echo -n "\x01\x02" |base64                                                          
AQI=

> $ echo -n "\x03\x04" |base64                                                              
AwQ=

> $ echo -n "\x01\x02\x03\x04" |base64
AQIDBA==

So the input values to my problem would be AQI= and AwQ=, the desired output is AQIDBA==

2 Answers 2

3

Probably easiest to decode the inputs and encode again:

$ echo "AQI=AwQ=" | base64 -d | base64
AQIDBA==

(Or just run the decoder separately for each string if reading the string past the = padding offends your sensibilities.)

$ (echo "AQI=" |base64 -d ; echo "AwQ=" |base64 -d) | base64
AQIDBA==
4
  • 2
    This takes advantage of a glitch in base64. If won't work with other Base64 decoders / encoders (f.i. with mimencode -u / mimencode). That's because = is only valid at the end of the string, as padding. Jun 8, 2017 at 12:36
  • glitch or a feature? In this case it happens to do exactly what is wanted.
    – ilkkachu
    Jun 8, 2017 at 18:22
  • As I said: AQI=AwQ= is invalid Base64 data, I can't really see how that could be a feature. I can however easily imagine it being a parser glitch. :) In fact I'm not convinced off hand it's going to work in all cases. You have only tested it with a single pair of 2-byte strings, where all bytes have a zero high nibble. At the very least you need to test more corner cases. shrug Jun 8, 2017 at 20:22
  • @SatoKatsura, is it forbidden for a decoder to decode multiple back-to-back base64 strings, then? Calling it a glitch and assuming it's broken is quite a leap, but you're of course free to show an input it breaks with.
    – ilkkachu
    Jun 8, 2017 at 21:18
3

With bash:

str1=$(echo -ne "\x01\x02" | base64)
str2=$(echo -ne "\x03\x04" | base64)
if [[ $str1 =~ =$ ]; then
    concat=$( { base64 -d <<<"$str1"; base64 -d <<<"$str2"; } | base64 )
else
    concat="${str1}${str2}"
fi
printf '%s\n' "$concat"

The point being that if str1 doesn't end in in = then the Base64 form has no padding, so it can be concatenated just as it is. Otherwise the string needs to be re-encoded.

2
  • Surely there's a way to combine padded base64 strings without decoding the whole thing. Base64 encodes chunks of data (I think 4 bytes?), and later chunks have no effect on earlier chunks. In the case that the first string contains padding, you can just decode from the second-last chunk boundary of the first string and append the decoded second string before re-encoding. If you're dealing with several MB or GB of strings this makes a big difference (in terms of processing time and buffer size). For more than 2 strings this can be done recursively.
    – ATLief
    Feb 17, 2020 at 17:23
  • @ATLief Yes, you only need to decode the last 4 characters in the first string, and you can also avoid decoding the second string with the use of a suitably large translation table for 1- and 2-bits shifts. Would that be an optimization? Absolutely. Would that matter in the context of the actual question above, of strings of length 2 (or at least "short enough")? Err... ROFL. See also: straw man argument. Feb 18, 2020 at 18:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .