Home / Alt manpages / base32(1)

  • base32(1)
  • User command
  • linux

Encode and Decode Files Safely with GNU base32

GNU base32 turns data into RFC 4648 Base32 and back, and the real risk lives in shell redirection, not the command itself. Allow about ten minutes for the examples. You need a shell, the GNU coreutils package, and a file you are allowed to read.

  • Version used here: GNU coreutils 9.4, the version installed on the machine behind these examples.
  • Privilege: none. This is ordinary user-level tooling; sudo will not fix a bad input file or a malformed Base32 stream.

1. Check the installed command

$ command -v base32
/usr/bin/base32
$ base32 --version | head -n 1
base32 (GNU coreutils) 9.4
  • Input: with no file argument, or with - as the file, the manual page's base32 reads standard input.
  • Output: encoded or decoded data goes to standard output, so you can inspect the command before choosing a destination file.

Checkpoint

If command -v finds a different implementation, keep that in mind. Option details and error handling can differ between implementations, so do not silently assume another program has GNU coreutils behaviour.

2. Encode a small value

$ printf 'hello base32\n' | base32
NBSWY3DPEBRGC43FGMZAU===

Pipe data into base32 when it is already in a command's output. The newline in this example is part of the input, so it affects the encoded result.

  • Alphabet: letters and the digits 2 through 7, with = padding where needed.
  • It is encoding, not encryption. Anyone who receives the output can decode it, so do not use it to conceal passwords, keys or private data.
  • Wrapping: the default output wraps after 76 characters. A short value will not show this, but a larger file will contain newlines inserted for readability, and those are accepted during normal decoding.

3. Encode a file without overwriting it

$ base32 /path/to/input.bin > /path/to/input.bin.b32
$ test -s /path/to/input.bin.b32 && echo 'encoded output exists'
encoded output exists

The input is read, not changed. Shell redirection is the part that needs care: > truncates its destination before base32 starts. Never use the same path on both sides, such as base32 data > data, because the shell can empty the file before the program reads it.

For a destination that may already hold useful data, write to a temporary name and replace the old file only after a verification step:

$ base32 /path/to/input.bin > /path/to/input.bin.b32.new
$ test -s /path/to/input.bin.b32.new
$ mv /path/to/input.bin.b32.new /path/to/input.bin.b32

mv here changes the directory entry, not the original input. If encoding fails, remove the incomplete .new file and leave the existing output alone:

$ rm /path/to/input.bin.b32.new

Warning

Only run that removal when the path is exactly the temporary file you intended to create. Deleting a file is irreversible unless you have a separate backup.

4. Decode into a separate file

$ printf 'NBSWY3DPEBRGC43FGMZAU===\n' | base32 --decode
hello base32
$ base32 --decode /path/to/input.bin.b32 > /path/to/decoded.bin
$ cmp -- /path/to/input.bin /path/to/decoded.bin
$ echo "cmp status: $?"
cmp status: 0
  • Use --decode, or its short form -d, and redirect the decoded bytes to a new path.
  • A zero cmp status means the files match byte for byte. That is a stronger check than comparing displayed text, since it also catches differences in binary data and trailing newlines.
  • Keep input and output paths distinct here too. The same truncation rule applies to base32 --decode encoded.b32 > encoded.b32. If a destination already exists, use a .new path, run cmp or another suitable check, then move it into place.

5. Control wrapping when producing text

$ printf 'hello base32\n' | base32 --wrap=0
NBSWY3DPEBRGC43FGMZAU===
$ printf 'hello base32\n' | base32 --wrap=0 | wc -l
0
  • Set line width with --wrap=COLS, or -w COLS. The default is 76 characters; use zero to disable wrapping when another system expects one continuous line.
  • Why the second command prints zero: the output has no terminating newline when wrapping is disabled, easy to miss when composing a pipeline or a text file.
  • Pick based on the reader. If a human will read the result, the default wrapping is usually clearer. If a protocol specifies a line length, pass it explicitly rather than relying on the default.
  • Decoded bytes are unaffected. Line wrapping changes presentation, not the decoded bytes; newlines are accepted by the decoder as part of the normal encoded stream.

6. Handle malformed or noisy input

$ printf 'NBSWY3DPEBRGC43FGMZAU=== garbage\n' | base32 --decode > /tmp/base32-output
base32: invalid input
$ echo "status: $?"
status: 1

During decoding, GNU base32 accepts newlines and the formal Base32 alphabet. Other non-alphabet bytes make the input invalid by default: a useful boundary, so do not ignore unexpected data merely to make a pipeline appear successful.

The command can write some decoded bytes before reporting the problem, so do not treat a partially written destination as trustworthy. Decode to a temporary path, check the exit status, and only then publish the result. A failed decode has no automatic undo because standard output is just a byte stream.

If you have a known reason to recover data from a stream containing extra characters, add --ignore-garbage or -i:

$ printf 'NBSWY3DPEBRGC43FGMZAU=== garbage\n' | base32 --decode --ignore-garbage
hello base32

Tip

Use this option deliberately. It tells the decoder to skip non-alphabet characters; it does not prove the skipped text was harmless, nor does it repair an incorrectly copied Base32 value. Preserve the original noisy input so you can audit what was ignored.

7. Keep the boundary clear in scripts

$ if base32 /path/to/input.bin > /path/to/input.bin.b32.new; then
>     mv /path/to/input.bin.b32.new /path/to/input.bin.b32
> else
>     rm -f /path/to/input.bin.b32.new
>     printf '%s\n' 'base32 encoding failed' >&2
> fi

Check the command's exit status before moving a temporary output into place; this conditional only replaces the destination after successful encoding. For higher-assurance workflows, compare a decoded result with the original or verify a separately supplied checksum. Base32 itself provides no integrity check, authentication or secrecy: it only maps bytes to a restricted textual alphabet.

Done means

  • Version confirmed: the installed command is GNU coreutils 9.4.
  • Input and output understood: a file or standard input in, standard output out.
  • Redirection made safe: separate input, temporary and final paths, so shell redirection cannot erase the source.
  • Round trip verified: cmp or an equivalent check used when byte-for-byte recovery mattered.
  • Wrapping deliberate: --wrap=0 used only when a single output line was required.
  • Not a security boundary: Base32 treated as encoding, not encryption or integrity protection.