Expand description
ore-rs is a library to encrypt numeric types in a way that allows the numeric ordering of the unencrypted values to be “revealed” during a query enabling range queries to be performed on encrypted data.
This is an implementation of the BlockORE Encryption scheme developed by Lewi-Wu in 2016. It is used extensively in the CipherStash searchable encryption platform.
§Usage
This crate is on crates.io and can be
used by adding ore-rs to your dependencies in your project’s Cargo.toml.
[dependencies]
ore-rs = "0.1"§Example: Encrypt a number with ORE.
To encrypt a number you need to initalize an OreCipher as well as use the OreEncrypt trait
which comes with implementations for u32 and u64.
To initalize the Cipher, you must decide on the scheme you want to use. There is only one ORE Scheme right now so that’s easy but in the future more schemes will become available.
An OreCipher also requires 2 keys (16-bytes each) and an 8-byte seed.
use ore_rs::{
OreCipher, // Main ORE Cipher trait
OreEncrypt, // Traits for encrypting primitive types (e.g. u64)
scheme::bit2::OreAes128ChaCha20 // Specific scheme we want to use
};
use hex_literal::hex;
// Initalize an ORE Cipher with the OreAes128ChaCha20 scheme
let k1: [u8; 16] = hex!("00010203 04050607 08090a0b 0c0d0e0f");
let k2: [u8; 16] = hex!("00010203 04050607 08090a0b 0c0d0e0f");
let ore: OreAes128ChaCha20 = OreCipher::init(&k1, &k2).unwrap();
// Encryption takes a mutable reference to the cipher and returns a `Result`
let a = 456u64.encrypt(&ore).unwrap();Note that a cipher must be mutable as it manages internal state.
§Example: Comparing 2 CipherTexts
The result of an encryption is called a CipherText and is represented by the type
CipherText<S, N> where S is the scheme used and N is the number of blocks is the size
of the input type (in bytes) divided by 8. (e.g. for u64 N=8).
Comparisons can only be performed between ciphertexts of the same size and underlying scheme.
let a = 456u64.encrypt(&ore).unwrap();
let b = 1024u64.encrypt(&ore).unwrap();
// This is fine
let result = a > b; // false because 456 < 1024// This isn't
let a = 456u64.encrypt(&ore).unwrap();
let b = 1024u32.encrypt(&ore).unwrap(); // note the u32
let result = a > b; // compilation error§Serializing/Deserializing
Note: this library doesn’t use Serde due to some complexities with GenericArray used in the AES library. This may change in the future.
To serialize a CipherText<S, N> to a vector of bytes:
let a = 456u64.encrypt(&ore).unwrap();
let bytes: Vec<u8> = a.to_bytes();To deserialize, you must specify the CipherText type (including number of blocks) you are deserializing into:
let ct = CipherText::<OreAes128ChaCha20, 8>::from_bytes(&bytes).unwrap();Re-exports§
pub use crate::OreCipher;
Modules§
- scheme
- Concrete BlockORE schemes. The crate currently exposes one scheme,
bit2, which uses a 2-bit indicator function with AES-128 as the PRF and Knuth-shuffle as the per-block PRP. Future schemes (different indicator widths or primitive choices) would land alongside it as sibling submodules.
Structs§
- Cipher
Text - A complete fixed-N BlockORE ciphertext: Left + Right.
- Left
- The Left half of a fixed-N BlockORE ciphertext: the per-block PRF₁ tags
fand the per-block PRP outputsxt. Sufficient on its own to act as the “query” side of the comparator. - Parse
Error - Error returned when a serialised ciphertext can’t be parsed (wrong length, malformed block, etc.).
- Right
- The Right half of a fixed-N BlockORE ciphertext: a per-ciphertext nonce and per-block masked truth-table rows. Combined with a Left from another ciphertext this drives the comparator.
Enums§
Traits§
- Cipher
Text Block - Trait implemented by per-block ciphertext components (Left and Right
blocks). Provides a fixed serialised size and byte conversions used by
OreOutput. - OreCipher
- A BlockORE cipher: a key-bound object that can encrypt fixed-N plaintexts to ciphertexts whose byte-wise comparison matches the plaintext order.
- OreEncrypt
- Type-directed entry point for encrypting plaintext values with a given
OreCipher. - OreOutput
- The trait of any encryption output (either Left, Right or combined).
Type Aliases§
- Plain
Text - Fixed-size byte array used as the input to the BlockORE encryption
routines.
Nis the number of plaintext bytes (one byte per ORE block). The fixed-N encryption path capsNat 15 due to the AES-as-PRF input packing inscheme::bit2.