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

Modules

Structs

Enums

Traits

Type Aliases