Skip to main content

Crate magic_cap

Crate magic_cap 

Source
Expand description

§Magic Cap

Provides low-level primitives for working with a “magic cap”, which is a small string (~70 bytes) that can be turned back into the corresponding plaintext when presented alongside the correct ciphertext.

The repository README has diagrams https://github.com/magic-cap/magic-cap

This is a release-early library that has not yet received cryptographic (or other) audits. We do appreciate feedback, but you own both pieces if you deploy to production :)

§Overview

Magic Cap turns the problem of having a lot of secret data (e.g. Sintel.mp4) into a tiny problem of only a little (fixed) amount of data (“the cap”).

The resulting (fixed, tiny) Magic Cap string can combined with the data file for the secret data; either part by itself cannot learn the secret data.

The “Magic Cap” string is short (70 bytes) and can fit in TPMs or other secure storage. Any interesting uses come when thinking about separating the Data (ciphertext + metadata) from the Magic Cap in time or space or both.

§Using the Crate

A “Magic Cap” is represented by the struct ImmutableReadCap in Rust code. This implements Display and From for converting to the human-usable strings, which are UTF8 characters with URL-safe Base64 encoded data which looks like this:

mcap0r1EmWRHtNLvG4J2xkLZ2Qd3GFcwRXJfxJ2X40xj8nJac5U7RTaKClMp1YsJXPMw47w

Breaking this down, we have:

  • mcap – all Magic Caps start with this
  • 0 – a version identifier (only “0” exists, and is not yet stable)
  • r – the kind of Cap this is (“r” for Read and “v” for Verify are valid for version 0)
  • rest is url-safe base64 encoded binary data, dependant on the version

The entire Magic Cap should be treated as a secret – because it is! It is an identifier you can later use to retrieve the original plaintext (and share offline, etc – more on those features later)

There is a reduced-power string called a Verify Cap which can be directly derived from the Read Cap (offline, with no server interaction). This Verify Cap can confirm that the ciphertext is valid, and could be decrypted by the Read Cap but cannot itself see any of the data. These look like:

mcap0v-Gshm9tyvjXDnfWpLWKMgjcK0AOdC-O12vvLW5rxeV4

Notice the v instead of r at the start of the string.

§Examples

One way to create an ImmutableReadCap is to stream plaintext to it using the Write trait to an ImmutableBuilder. For example:

let plaintext: Vec<u8> = "attack at dawn".into();
let mut ciphertext: Vec<u8> = vec!();

// create an encrypted immutable + associated ReadCap
let mut cryptor = ImmutableBuilder::new(4096, &mut ciphertext).unwrap();
cryptor.write(&plaintext).unwrap();
// .write() may be called any number of times with any size data
let (cap, ciphertext) = cryptor.done().unwrap();
println!("ciphertext: {} bytes", ciphertext.len());

// using the encrypted immutable and ReadCap, get back the ciperhtext
let ctext = ciphertext.as_slice();
let immutable = Immutable::read(Cursor::new(ctext)).unwrap();
let decrypted: Vec<u8> = cap.decrypt(&immutable).unwrap();
assert_eq!(plaintext, decrypted);

Another way is to create a completely in-memory Immutable and corresponding ImmutableCap::Read. This example also demonstrates using the ImmutableVerifyCap to verify the ciphertext.

let plaintext: Vec<u8> = "attack at dawn".into();

if let Ok((ImmutableCap::Read(readcap), immutable)) = Immutable::encrypt(plaintext.as_slice(), 4096) {
    println!("Read Cap: {:?}", readcap);

    let verifycap: ImmutableVerifyCap = readcap.into();
    if ! verifycap.corresponds_to(&immutable) {
        println!("Verify Cap does not match data");
    }
}

Modules§

err

Structs§

EncryptedImmutableMemory
Store all of the ciphertext on the heap
EncryptedImmutableReader
Access all ciphertext via a Read provider
Immutable
Represents everything to do with an Immutable except the ImmutableCap itself. That is, this represents the Immutable’s metadata and a way to access the ciphertext.
ImmutableBuilder
Manage context to incrementally encrypt to an underlying Write
ImmutableCiphertextStream
ImmutableMetadata
A struct representing (unencrypted!) metadata about the data.
ImmutableReadCap
A Cap that is able to both verify the ciphertext and decrypt it
ImmutableVerifyCap
A Cap that is able to confirm the ciphertext is valid, but cannot decrypt any of it.

Enums§

ImmutableCap

Traits§

EncryptedImmutable
Specification of how to access all ciphertext, whcih are stored in blocks.
ImmutableVerifier
ReadCap