Expand description

RustCrypto: Constant-Time Base64

crate Docs Build Status Apache2/MIT licensed Rust Version Project Chat

Pure Rust implementation of Base64 (RFC 4648).

Implements multiple Base64 alphabets without data-dependent branches or lookup tables, thereby providing portable “best effort” constant-time operation.

Supports no_std environments and avoids heap allocations in the core API (but also provides optional alloc support for convenience).



This crate implements several Base64 alphabets in constant-time for sidechannel resistance, aimed at purposes like encoding/decoding the “PEM” format used to store things like cryptographic private keys (i.e. in the pem-rfc7468 crate).

The paper Util::Lookup: Exploiting key decoding in cryptographic libraries demonstrates how the leakage from non-constant-time Base64 parsers can be used to practically extract RSA private keys from SGX enclaves.

The padded variants require (=) padding. Unpadded variants expressly reject such padding.

Whitespace is expressly disallowed, with the exception of the Decoder::new_wrapped and Encoder::new_wrapped modes which provide fixed-width line wrapping.

Supported Base64 variants

  • Standard Base64: [A-Z], [a-z], [0-9], +, /
  • URL-safe Base64: [A-Z], [a-z], [0-9], -, _
  • bcrypt Base64: ., /, [A-Z], [a-z], [0-9]
  • crypt(3) Base64: ., -, [0-9], [A-Z], [a-z]

Minimum Supported Rust Version

This crate requires Rust 1.56 at a minimum.

We may change the MSRV in the future, but it will be accompanied by a minor version bump.


Licensed under either of:

at your option.


Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


Allocating (enable alloc crate feature)

use base64ct::{Base64, Encoding};

let bytes = b"example bytestring!";
let encoded = Base64::encode_string(bytes);
assert_eq!(encoded, "ZXhhbXBsZSBieXRlc3RyaW5nIQ==");

let decoded = Base64::decode_vec(&encoded).unwrap();
assert_eq!(decoded, bytes);

Heapless no_std usage

use base64ct::{Base64, Encoding};

const BUF_SIZE: usize = 128;

let bytes = b"example bytestring!";
assert!(Base64::encoded_len(bytes) <= BUF_SIZE);

let mut enc_buf = [0u8; BUF_SIZE];
let encoded = Base64::encode(bytes, &mut enc_buf).unwrap();
assert_eq!(encoded, "ZXhhbXBsZSBieXRlc3RyaW5nIQ==");

let mut dec_buf = [0u8; BUF_SIZE];
let decoded = Base64::decode(encoded, &mut dec_buf).unwrap();
assert_eq!(decoded, bytes);


Implemented using integer arithmetic alone without any lookup tables or data-dependent branches, thereby providing portable “best effort” constant-time operation.

Not constant-time with respect to message length (only data).

Adapted from the following constant-time C++ implementation of Base64:


Copyright (c) 2014 Steve “Sc00bz” Thomas (steve at tobtu dot com). Derived code is dual licensed MIT + Apache 2 (with permission from Sc00bz).


Standard Base64 encoding with = padding.
bcrypt Base64 encoding.
crypt(3) Base64 encoding.
crypt(3) Base64 encoding for the following schemes.
Standard Base64 encoding without padding.
URL-safe Base64 encoding with = padding.
URL-safe Base64 encoding without padding.
Stateful Base64 decoder with support for buffered, incremental decoding.
Stateful Base64 encoder with support for buffered, incremental encoding.
Invalid encoding of provided Base64 string.
Insufficient output buffer length.


Generic error, union of InvalidLengthError and InvalidEncodingError.
Line endings: variants of newline characters that can be used with Base64.


Base64 encoding trait.