Crate base64

Correct, fast, and configurable base64 decoding and encoding. Base64 transports binary data efficiently in contexts where only plain text is allowed.

Usage

Use an Engine to decode or encode base64, configured with the base64 alphabet and padding behavior best suited to your application.

Engine setup

There is more than one way to encode a stream of bytes as “base64”. Different applications use different encoding [alphabets][alphabet::Alphabet] and [padding behaviors][engine::general_purpose::GeneralPurposeConfig].

Encoding alphabet

Almost all base64 [alphabets][alphabet::Alphabet] use A-Z, a-z, and 0-9, which gives nearly 64 characters (26 + 26 + 10 = 62), but they differ in their choice of their final 2.

Most applications use the [standard][alphabet::STANDARD] alphabet specified in RFC 4648. If that’s all you need, you can get started quickly by using the pre-configured [STANDARD][engine::general_purpose::STANDARD] engine, which is also available in the prelude module as shown here, if you prefer a minimal use footprint.

use base64::prelude::*;

# fn main() -> Result<(), base64::DecodeError> {
assert_eq!(BASE64_STANDARD.decode(b"+uwgVQA=")?, b"\xFA\xEC\x20\x55\0");
assert_eq!(BASE64_STANDARD.encode(b"\xFF\xEC\x20\x55\0"), "/+wgVQA=");
# Ok(())
# }

Other common alphabets are available in the alphabet module.

URL-safe alphabet

The standard alphabet uses + and / as its two non-alphanumeric tokens, which cannot be safely used in URL’s without encoding them as %2B and %2F.

To avoid that, some applications use a [“URL-safe” alphabet][alphabet::URL_SAFE], which uses - and _ instead. To use that alternative alphabet, use the [URL_SAFE][engine::general_purpose::URL_SAFE] engine. This example doesn't use prelude to show what a more explicit use would look like.

use base64::{engine::general_purpose::URL_SAFE, Engine as _};

# fn main() -> Result<(), base64::DecodeError> {
assert_eq!(URL_SAFE.decode(b"-uwgVQA=")?, b"\xFA\xEC\x20\x55\0");
assert_eq!(URL_SAFE.encode(b"\xFF\xEC\x20\x55\0"), "_-wgVQA=");
# Ok(())
# }

Padding characters

Each base64 character represents 6 bits (2⁶ = 64) of the original binary data, and every 3 bytes of input binary data will encode to 4 base64 characters (8 bits × 3 = 6 bits × 4 = 24 bits).

When the input is not an even multiple of 3 bytes in length, canonical base64 encoders insert padding characters at the end, so that the output length is always a multiple of 4:

use base64::{engine::general_purpose::STANDARD, Engine as _};

assert_eq!(STANDARD.encode(b""),    "");
assert_eq!(STANDARD.encode(b"f"),   "Zg==");
assert_eq!(STANDARD.encode(b"fo"),  "Zm8=");
assert_eq!(STANDARD.encode(b"foo"), "Zm9v");

Canonical encoding ensures that base64 encodings will be exactly the same, byte-for-byte, regardless of input length. But the = padding characters aren’t necessary for decoding, and they may be omitted by using a [NO_PAD][engine::general_purpose::NO_PAD] configuration:

use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _};

assert_eq!(STANDARD_NO_PAD.encode(b""),    "");
assert_eq!(STANDARD_NO_PAD.encode(b"f"),   "Zg");
assert_eq!(STANDARD_NO_PAD.encode(b"fo"),  "Zm8");
assert_eq!(STANDARD_NO_PAD.encode(b"foo"), "Zm9v");

The pre-configured NO_PAD engines will reject inputs containing padding = characters. To encode without padding and still accept padding while decoding, create an [engine][engine::general_purpose::GeneralPurpose] with that [padding mode][engine::DecodePaddingMode].

# use base64::{engine::general_purpose::STANDARD_NO_PAD, Engine as _};
assert_eq!(STANDARD_NO_PAD.decode(b"Zm8="), Err(base64::DecodeError::InvalidPadding));

Further customization

Decoding and encoding behavior can be customized by creating an [engine][engine::GeneralPurpose] with an [alphabet][alphabet::Alphabet] and [padding configuration][engine::GeneralPurposeConfig]:

use base64::{engine, alphabet, Engine as _};

// bizarro-world base64: +/ as the first symbols instead of the last
let alphabet =
    alphabet::Alphabet::new("+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
    .unwrap();

// a very weird config that encodes with padding but requires no padding when decoding...?
let crazy_config = engine::GeneralPurposeConfig::new()
    .with_decode_allow_trailing_bits(true)
    .with_encode_padding(true)
    .with_decode_padding_mode(engine::DecodePaddingMode::RequireNone);

let crazy_engine = engine::GeneralPurpose::new(&alphabet, crazy_config);

let encoded = crazy_engine.encode(b"abc 123");

Memory allocation

The [decode][Engine::decode()] and [encode][Engine::encode()] engine methods allocate memory for their results – decode returns a Vec<u8> and encode returns a String. To instead decode or encode into a buffer that you allocated, use one of the alternative methods:

Decoding

Method Output Allocates memory
Engine::decode returns a new Vec<u8> always
Engine::decode_vec appends to provided Vec<u8> if Vec lacks capacity
Engine::decode_slice writes to provided &[u8] never

Encoding

Method Output Allocates memory
Engine::encode returns a new String always
Engine::encode_string appends to provided String if String lacks capacity
Engine::encode_slice writes to provided &[u8] never

Input and output

The base64 crate can [decode][Engine::decode()] and [encode][Engine::encode()] values in memory, or [DecoderReader][read::DecoderReader] and [EncoderWriter][write::EncoderWriter] provide streaming decoding and encoding for any [readable][std::io::Read] or [writable][std::io::Write] byte stream.

Decoding

# use std::io;
use base64::{engine::general_purpose::STANDARD, read::DecoderReader};

# fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut input = io::stdin();
let mut decoder = DecoderReader::new(&mut input, &STANDARD);
io::copy(&mut decoder, &mut io::stdout())?;
# Ok(())
# }

Encoding

# use std::io;
use base64::{engine::general_purpose::STANDARD, write::EncoderWriter};

# fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut output = io::stdout();
let mut encoder = EncoderWriter::new(&mut output, &STANDARD);
io::copy(&mut io::stdin(), &mut encoder)?;
# Ok(())
# }

Display

If you only need a base64 representation for implementing the [Display][std::fmt::Display] trait, use [Base64Display][display::Base64Display]:

use base64::{display::Base64Display, engine::general_purpose::STANDARD};

let value = Base64Display::new(b"\0\x01\x02\x03", &STANDARD);
assert_eq!("base64: AAECAw==", format!("base64: {}", value));

Panics

If length calculations result in overflowing usize, a panic will result.

Modules