12 releases (5 stable)

2.0.1 May 13, 2024
2.0.0 Jul 27, 2023
1.1.0 May 3, 2023
1.0.2 Nov 16, 2022
0.2.0 Jun 1, 2022

#151 in Cryptography

Download history 2048/week @ 2024-07-22 3471/week @ 2024-07-29 3440/week @ 2024-08-05 4250/week @ 2024-08-12 3266/week @ 2024-08-19 2852/week @ 2024-08-26 3076/week @ 2024-09-02 1397/week @ 2024-09-09 1940/week @ 2024-09-16 2426/week @ 2024-09-23 1668/week @ 2024-09-30 1784/week @ 2024-10-07 2510/week @ 2024-10-14 2063/week @ 2024-10-21 1601/week @ 2024-10-28 1429/week @ 2024-11-04

7,649 downloads per month
Used in 10 crates (via stronghold_engine)

Apache-2.0

145KB
4K SLoC

Rust 3.5K SLoC // 0.1% comments Coq 429 SLoC // 0.0% comments Shell 26 SLoC

Stronghold new runtime

This crate provides multiple ways to store data securely whether in ram, disk or fragmented into a non contiguous data structure. All these types of memories implement the LockedMemory trait which enables one to allocate or unlock the data stored. A Buffer type which implements basic security measures is also provided to temporarily store data for any computation.

Buffer

Memory which contains some "minimal" security measures such as:

  • Guard areas
  • Canaries
  • Constant time comparisons
  • Zeroes out the memory when dropped
  • Access control of memory pages
  • System flags against memory dumps

Values in protected memory are stored in clear. Those values are accessible by getting a reference through borrow() or borrow_mut(). Since the values are stored in clear instances of Buffer should be as short-lived as possible.

The main functions of Buffer are alloc(), borrow(), borrow_mut.

LockedMemory

Locked memory is used to store sensitive data for longer period of times.

You can create a LockedMemory instance using alloc() or give it a new value with update(). As the trait name mentions, the data stored in LockedMemory is locked and you can retrieve using unlock(). Unlocked data will be returned in a Buffer.

When allocating a LockedMemory you have to choose how it will be stored and how it will be locked. There are 3 types that implement LockedMemory: RamMemory, FileMemory and NonContiguousMemory.

RamMemory

Data will be stored in ram memory with the same security measures as the Buffer type. Additionally the user can choose to have its data encrypted by providing an encryption key.

Note: RamMemory with non encrypted data is essentially a wrapper of the Buffer type.

FileMemory

Data is stored in disk memory and can be encrypted.

Security measures to protect the files:

  • Access control of the files (os-dependent)
  • Data is mixed with noise
  • File is zeroed and removed when dropped

Note: usually disk memory is more vulnerable than ram memory but we believe that using diverse types of memories increases the data security.

NonContiguousMemory

Data is split into two shards using the Boojum scheme. Basically the data is split into two:

  • one shard is random data
  • other shard is data xored with a hash of the first shard

Data is reconstructed by xoring the second shard with a hash of the first shard.

Non contiguous memory improves security through forcing an attacker to recover multiple pieces to get the original data. User can choose to have data split in ram memory or in ram and disk (to diversify memory storage).

Moreover the shards can be refreshed regularly. Values of the shards will be modified separately such that the original data can still be reconstructed.

Note: data in shard is xored with a hash digest, hence the data stored in non contiguous memory can only have size of a hash digest. This may seem restrictive but it fits well when following the usage recommendation described in the next section.

Usage recommendation

Our recommendation on how to use the crate to store sensitive data.

  • Data is stored encrypted in RamMemory
  • The encryption key is stored in NonContiguousMemory over ram and disk

Hence data security depends on the strength of the encryption scheme and the 'obfuscation' of the encryption key in non contiguous memory.

Objectives

  • Stable LockedMemory API
  • Implementation
    • Buffer
    • RamMemory
    • FileMemory
      • data mixed with noise
    • NonContiguousMemory
  • Tests
    • Functional correctness
    • Security
      • zeroize
      • access to the locked memory
  • Benchmarks
  • no-std

Dependencies

~4–44MB
~622K SLoC