encrust 0.4.0

Obfuscate data in memory to hide it until needed
Documentation

Encrust

Hide data at run time by obfuscating ("encrusting") it when it is not in use.

Encrust obfuscates the underlying data, and only exposes it when needed. This crate does not provide any security as the seed needed to decrust the data is stored next to the data, and no integrity checks are performed.

The crate also provides macros for hashing strings and byte arrays at compile time, so the original strings or bytes do not need to be included in the executable. The hash macros require the hashstrings feature, which is enabled by default.

Macros

Encrust contains several macros for embedding encrusted values in executables. Encrusting happens at compile time, and the plain values are not included in the binary.

use encrust::{encrust, encrust_file_bytes, encrust_file_cstring, encrust_file_string};

let mut encrusted_int = encrust!(1u32);
assert_eq!(*encrusted_int.decrust(), 1u32);

let mut encrusted_string = encrust!("Strings can also be encrusted.");
assert_eq!("Strings can also be encrusted.", &*encrusted_string.decrust());

let mut encrusted_array = encrust!([1u8, 2u8, 3u8]);
assert_eq!(&[1u8, 2u8, 3u8], &*encrusted_array.decrust());

// Read `Cargo.toml` into a `String`, array of `u8`, and `CString` and encrust.
let mut cargo_toml = encrust_file_string!("Cargo.toml");
let mut cargo_toml_bytes = encrust_file_bytes!("Cargo.toml");
let mut cargo_toml_cstring = encrust_file_cstring!("Cargo.toml");

Supported data types

Data type Decrusted deref target Example encrust! invocation
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize Same integer type encrust!(123u32) Note that the suffix with the integer type is required.
String str encrust!("secret")
CString [u8] encrust!(c"secret")
[u8; N] byte string [u8; N] encrust!(b"secret")
[T; N] where T: InPlaceEncrust numeric array [T; N] encrust!([1u8, 2u8, 3u8])
[[T; N]; M] where T: InPlaceEncrust nested numeric array [[T; N]; M] encrust!([[1u8, 2u8], [3u8, 4u8]])

Run-time Encrusting

use encrust::Encrusted;

use rand::{rng, Rng};

let mut value = Encrusted::new(String::from("runtime value"), rng().next_u64());

{
    let mut decrusted = value.decrust();
    assert_eq!("runtime value", &*decrusted);
    decrusted.make_ascii_uppercase();
}

assert_eq!("RUNTIME VALUE", &*value.decrust());

hashstrings macros

The hashstrings feature contains macros to include hashes of strings and byte arrays without including the data itself.

use encrust::{hashstring, hashstring_ci, hashbytes};

let hashed_string = hashstring!("Case sensitive string, hashed");
assert!(hashed_string == "Case sensitive string, hashed");
assert!(hashed_string != "cAsE SeNSItIvE StRinG, HASHED");

let case_insensitive_hashed_string = hashstring_ci!("Case insensitive string, hashed");
assert!(case_insensitive_hashed_string == "Case insensitive string, hashed");
assert!(case_insensitive_hashed_string == "cASe INsenSItiVE StRiNg, hasHed");

let hashed_bytes = hashbytes!([0, 1, 2, 3, 4, 5]);
assert!(hashed_bytes == &[0, 1, 2, 3, 4, 5]);

Limitations

Encrust currently supports only certain simple data structures; most container types are not supported. Some metadata is not encrusted. For Vec and String, the buffer contents are encrusted, but the pointer, length, and capacity fields are not.

Encrusted data is zeroized prior to being dropped. If you need to perform operations with the data before dropping it, wrap the encrusted data in another type and implement Drop for that outer type. The outer Drop implementation can decrust the data before the inner Encrusted value is zeroized.

Encrust is intended for obfuscation within one application, not for communicating secrets between applications. Use a cryptographic protocol for secure communication.

License: MIT