Skip to main content

Crate ore_rs

Crate ore_rs 

Source
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§

CipherText
A complete fixed-N BlockORE ciphertext: Left + Right.
Left
The Left half of a fixed-N BlockORE ciphertext: the per-block PRF₁ tags f and the per-block PRP outputs xt. Sufficient on its own to act as the “query” side of the comparator.
ParseError
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§

OreError
Errors returned by OreCipher initialisation and encryption.

Traits§

CipherTextBlock
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§

PlainText
Fixed-size byte array used as the input to the BlockORE encryption routines. N is the number of plaintext bytes (one byte per ORE block). The fixed-N encryption path caps N at 15 due to the AES-as-PRF input packing in scheme::bit2.