15

The common coreutils base64 tool can't encode/decode base64url. The = padding is optional in base64url and the last two characters of its alphabet are - and _.[0][1] What is a simple way to encode and decode base64url using common unix tools?

Context: this question came up while working with JWT (RFC7519).

[0]: https://www.rfc-editor.org/rfc/rfc4648#section-5
[1]: https://en.wikipedia.org/wiki/Base64#Variants_summary_table

2 Answers 2

17

Self-answering my question for future reference.

base64url::encode () { base64 -w0 | tr '+/' '-_' | tr -d '='; }
base64url::decode () { awk '{ if (length($0) % 4 == 3) print $0"="; else if (length($0) % 4 == 2) print $0"=="; else print $0; }' | tr -- '-_' '+/' | base64 -d; }

Some tests:

$ echo 'he' | base64url::encode
aGUK
$ echo 'aGUK' | base64url::decode
he

$ echo 'hel' | base64url::encode
aGVsCg
$ echo 'aGVsCg' | base64url::decode
hel

$ echo 'hell' | base64url::encode
aGVsbAo
$ echo 'aGVsbAo' | base64url::decode
hell

$ echo 'hello' | base64url::encode
aGVsbG8K
$ echo 'aGVsbG8K' | base64url::decode
hello

$ dd if=/dev/urandom bs=1 count=1M > ./test.bin
1048576+0 records in
1048576+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 3.1961 s, 328 kB/s

$ sha256sum ./test.bin
a9d5268ac338fa273245073e463058d9399221c5a60d8bea6cc20cab601863e6  ./test.bin

$ sha256sum <(base64url::encode < ./test.bin | base64url::decode)
a9d5268ac338fa273245073e463058d9399221c5a60d8bea6cc20cab601863e6  /dev/fd/63
0
0

Avoiding any external tools*:

#!/bin/bash

base64url_decode() {
    local t=$1
    t=${t//-/+}
    t=${t//_/\/}
    while [[ $(( ${#t} % 4 )) -ne 0 ]]; do
        t="$t="
    done
    t=$(echo "$t" | base64 -d)
    printf '%s\n' "$t"
}

base64_encode() {
    local t=$1
    t=$(printf '%s' "$t" | base64)
    t=${t//+/-}
    t=${t//\//_}
    t=${t//=/}
    printf '%s\n' "$t"
}

Usage:

base64url_encode 'Lorem ipsum dolor sit amet'
base64url_decode 'TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ'

Output:

TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQ
Lorem ipsum dolor sit amet

* aside from base64 of course; I'm not that much of a sadist.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.