Expand description
An implementation of Oblivious RAM (ORAM) for the secure enclave setting.
⚠️ Warning: This implementation has not been audited. Use at your own risk!
§Overview
This crate implements an oblivious RAM protocol (ORAM) for (secure) enclave applications.
This crate assumes that ORAM clients are running inside a secure enclave architecture that provides memory encryption. It does not perform encryption-on-write and thus is not secure without memory encryption.
§Design
This crate implements the Path ORAM protocol, with oblivious client data structures based on the Oblix paper. See the Path ORAM retrospective paper for a high-level introduction to ORAM and Path ORAM, and for more detailed references.
§Example
The below example reads a database from memory into an ORAM, thus permitting secret-dependent accesses.
use oram::{Address, BlockSize, BlockValue, Oram, DefaultOram};
const BLOCK_SIZE: BlockSize = 64;
const DB_SIZE: Address = 64;
let mut rng = rand::rngs::OsRng;
// Initialize an ORAM to store 64 blocks of 64 bytes each.
let mut oram = DefaultOram::<BlockValue<BLOCK_SIZE>>::new(DB_SIZE, &mut rng)?;
// Read a database (here, an array of byte arrays) into the ORAM.
for (i, bytes) in DATABASE.iter().enumerate() {
oram.write(i as Address, BlockValue::new(*bytes), &mut rng)?;
}
// Now you can safely make secret-dependent accesses to your database.
let secret = 42;
let _ = oram.read(secret, &mut rng)?;
§Advanced
ORAMs can store arbitrary structs implementing OramBlock
.
We provide implementations of OramBlock
for u8
, u16
, u32
, u64
, i8
, i16
, i32
, i64
,
and BlockValue<const B: BlockSize>
.
The DefaultOram
used in the above example should have good performance in most use cases.
But the underlying algorithms have several tunable parameters that impact performance.
The following example instantiates the same ORAM struct as above, but using the PathOram
interface which exposes these parameters.
use oram::{Address, BlockSize, BlockValue, BucketSize,
Oram, PathOram, StashSize, RecursionCutoff};
use oram::path_oram::{DEFAULT_BLOCKS_PER_BUCKET, DEFAULT_RECURSION_CUTOFF,
DEFAULT_POSITIONS_PER_BLOCK, DEFAULT_STASH_OVERFLOW_SIZE};
const RECURSION_CUTOFF: RecursionCutoff = DEFAULT_RECURSION_CUTOFF;
const BUCKET_SIZE: BucketSize = DEFAULT_BLOCKS_PER_BUCKET;
const POSITIONS_PER_BLOCK: BlockSize = DEFAULT_POSITIONS_PER_BLOCK;
const INITIAL_STASH_OVERFLOW_SIZE: StashSize = DEFAULT_STASH_OVERFLOW_SIZE;
let mut oram = PathOram::<
BlockValue<BLOCK_SIZE>,
BUCKET_SIZE,
POSITIONS_PER_BLOCK,
>::new_with_parameters(DB_SIZE, &mut rng, INITIAL_STASH_OVERFLOW_SIZE, RECURSION_CUTOFF)?;
See PathOram
for an explanation of these parameters and their possible settings.
Re-exports§
pub use crate::path_oram::DefaultOram;
pub use crate::path_oram::PathOram;
Modules§
- linear_
time_ oram - A simple linear-time implementation of Oblivious RAM.
- path_
oram - An implementation of Path ORAM.
Structs§
- Block
Value - An
OramBlock
consisting of unstructured bytes.
Enums§
- Oram
Error - A list of error types which are produced during ORAM protocol execution.
Traits§
- Oram
- Represents an oblivious RAM (ORAM) mapping addresses of type
Address
to values of typeV: OramBlock
. - Oram
Block - A “trait alias” for ORAM blocks: the values read and written by ORAMs.
Type Aliases§
- Address
- The numeric type used to specify the size of an ORAM in blocks, and to index into the ORAM.
- Block
Size - The numeric type used to specify the size of an ORAM block in bytes.
- Bucket
Size - The numeric type used to specify the size of an ORAM bucket in blocks.
- Recursion
Cutoff - The numeric type used to specify the cutoff size
below which
PathOram
uses a linear position map instead of a recursive one. - Stash
Size - Numeric type used to represent the size of a Path ORAM stash in blocks.