[][src]Crate safebox

The SafeBox lowers the risk of leaving copies of its content linger in RAM.

To zero a piece RAM requires a bit more than calling memset(0). There is few layers of optimizations and abstractions working against us:

  1. The compiler is free to forgo zeroing altogether. Since the value is never used again, the compiler assumes no side-effect, and will happily remove the code in the name of speed.
  2. The compiler is free to reorder memory operations.
  3. Similarly, the hardware is free to reorder memory operations.
  4. Furthermore, the hardware might not flush caches to RAM right away.

With the above taken care of, we must also enforce that the content cannot be copied in RAM inadvertently:

  1. Taking ownership of the content can move it anywhere, including from/to the stack/heap. Leaving a stray copy of the content in RAM behind.
  2. Similarly, a &mut access on the content allows a mem swap or mem replace.

And finally, the Operating System can be involved:

  1. The Operating System can move the RAM to the SWAP area on persistent storage.
  2. Any thread in the same memory space can read & write the memory at will.
  3. When hibernating the OS will likely copy the RAM content to persistent storage.

This crate solves 1) to 4) with volatile write and atomic fence. 5) and 6) are guarded behind unsafe functions. Of course, the programmer is responsible to maintain the invariant; but at last; it is requires using a visible unsafe block.

The Operating System side is ignored. 7) and 8) could be addressed via mlock and mprotect syscalls. And as for 9), you should use an encrypted storage anyway.


use safebox::SafeBox;
use rand::prelude::*;
let mut secret = SafeBox::new_slice(0_u8, 8);
unsafe {
unsafe {
    println!("My secret: {:?}", secret.get_ref());

Prints (non-deterministic):

My secret: [242, 144, 235, 196, 84, 35, 85, 232]

See SafeBox::new_slice_with for a more elegant random initialization.



A safe box for your secrets.



Set the memory behind a value to zero.