Crate nuts_container

Source
Expand description

§The basic container

This module contains types for the basic container handling. A Container acts like an encrypted block device, where you can read and write encrypted blocks of data. See the Container documentation for details.

The Container has no knowlege about the storage layer. Every type that implements the Backend trait can act as the storage layer for the Container. The Container receives (possibly) encrypted data from the backend and pushes (possibly) encrypted data back to the backend. See the backend crate documentation for details.

§Create a container

The Container::create() method is used to create a new container. It expects an instance of a type that implements the Create trait, which acts as a builder for the related Backend.

Example:

use nuts_container::*;
use nuts_memory::MemoryBackend;

// Create a container with a memory backend.
let backend = MemoryBackend::new();

// Let's create an encrypted container (with aes128-ctr).
// Because you are encrypting the container, you need to assign a
// password callback.
let kdf = Kdf::pbkdf2(Digest::Sha1, 65536, b"123");
let options = CreateOptionsBuilder::new(Cipher::Aes128Ctr)
    .with_password_callback(|| Ok(b"abc".to_vec()))
    .with_kdf(kdf.clone())
    .build::<MemoryBackend>()
    .unwrap();

// Create the container and fetch information.
// Here you can directly pass the backend instance to the create() method
// because MemoryBackend implements the Backend::CreateOptions trait.
let container = Container::<MemoryBackend>::create(backend, options).unwrap();
let info = container.info().unwrap();

assert_eq!(info.cipher, Cipher::Aes128Ctr);
assert_eq!(info.kdf, kdf);

§Open a container

The Container::open() method is used to open a container. It expects an instance of a type that implements the Open trait, which acts as a builder for the related Backend.

Example:

use nuts_container::*;
use nuts_memory::MemoryBackend;

let (backend, kdf) = {
    // In this example you create a container in a separate block.
    // So, the created container is closed again when leaving the scope.
    let backend = MemoryBackend::new();
    let kdf = Kdf::pbkdf2(Digest::Sha1, 65536, b"123");
    let options = CreateOptionsBuilder::new(Cipher::Aes128Ctr)
        .with_password_callback(|| Ok(b"abc".to_vec()))
        .with_kdf(kdf.clone())
        .build::<MemoryBackend>()
        .unwrap();

    // Create the container.
    let container = Container::<MemoryBackend>::create(backend, options).unwrap();
    let backend = container.into_backend();

    (backend, kdf)
};

// Open the container and fetch information.
// Here you can directly pass the backend instance to the open() method
// because MemoryBackend implements the Backend::OpenOptions trait.
let options = OpenOptionsBuilder::new()
    .with_password_callback(|| Ok(b"abc".to_vec()))
    .build::<MemoryBackend>()
    .unwrap();
let container = Container::<MemoryBackend>::open(backend, options).unwrap();
let info = container.info().unwrap();

assert_eq!(info.cipher, Cipher::Aes128Ctr);
assert_eq!(info.kdf, kdf);

§Read from a container

use nuts_container::*;
use nuts_memory::MemoryBackend;

// Create a container with a memory backend.
let mut backend = MemoryBackend::new();

// Insert a block into the backend.
// Note that the insert() method is a part of the MemoryBackend and directly
// inserts a block into the backend (bypassing the crypto capabilities of the
// container).
let id = backend.insert().unwrap();

// Create the container.
let options = CreateOptionsBuilder::new(Cipher::None)
    .build::<MemoryBackend>()
    .unwrap();
let mut container = Container::<MemoryBackend>::create(backend, options).unwrap();

// Read full block.
let mut buf = [b'x'; 512];
assert_eq!(container.read(&id, &mut buf).unwrap(), 512);
assert_eq!(buf, [0; 512]);

// Read block into a buffer which is smaller than the block-size.
// The buffer is filled with the first 400 bytes from the block.
let mut buf = [b'x'; 400];
assert_eq!(container.read(&id, &mut buf).unwrap(), 400);
assert_eq!(buf, [0; 400]);

// Read block into a buffer which is bigger than the block-size.
// The first 512 bytes are filled with the content of the block,
// the remaining 8 bytes are not touched.
let mut buf = [b'x'; 520];
assert_eq!(container.read(&id, &mut buf).unwrap(), 512);
assert_eq!(buf[..512], [0; 512]);
assert_eq!(buf[512..], [b'x'; 8]);

§Write into a container

use nuts_container::*;
use nuts_memory::MemoryBackend;

// In this example you create a container in a separate block.
// So, the created container is closed again when leaving the scope.
let mut backend = MemoryBackend::new();

// Insert a block into the backend.
// Note that the insert() method is a part of the MemoryBackend and directly
// inserts a block into the backend (bypassing the crypto capabilities of the
// container).
let id = backend.insert().unwrap();

// Create the container.
let options = CreateOptionsBuilder::new(Cipher::None)
    .build::<MemoryBackend>()
    .unwrap();
let mut container = Container::<MemoryBackend>::create(backend, options).unwrap();

// Write a full block. The whole block is filled with 'x'.
assert_eq!(container.write(&id, &[b'x'; 512]).unwrap(), 512);

let mut buf = [0; 512];
assert_eq!(container.read(&id, &mut buf).unwrap(), 512);
assert_eq!(buf, [b'x'; 512]);

// Write a block from a buffer which is smaller than the block-size.
// The first bytes of the block are filled with the data from the buffer,
// the remaining space is padded with '0'.
assert_eq!(container.write(&id, &[b'x'; 400]).unwrap(), 400);

let mut buf = [0; 512];
assert_eq!(container.read(&id, &mut buf).unwrap(), 512);
assert_eq!(buf[..400], [b'x'; 400]);
assert_eq!(buf[400..], [0; 112]);

// Write a block from a buffer which is bigger than the block-size.
// The block is filled with the first data from the buffer.
assert_eq!(container.write(&id, &[b'x'; 520]).unwrap(), 512);

let mut buf = [0; 512];
assert_eq!(container.read(&id, &mut buf).unwrap(), 512);
assert_eq!(buf, [b'x'; 512]);

§The header of a container

The header of the container stores all data necessary to open the container again. There are:

  • The Cipher: The cipher defines the cipher used for encryption and decryption of the individual blocks of the container.

    If the cipher is set to Cipher::None, then encryption is disabled and all the data are stored unencrypted in the container.

    If encryption is enabled (with a cipher which is not Cipher::None), then the blocks of the container are encrypted with a master-key stored and secured in the header of the container. This part of the header (other sensible data are also stored there) is called secret and is encrypted with the wrapping-key derivited by the key derivation function (Kdf). So, with a user supplied passphrase you are derivating the wrapping-key, which decrypts the secret part of the header, where the master-key (used for en-/decryption of the data blocks) is stored.

  • The key derivation function (Kdf) defines a way to create a key from a user supplied passphrase. In the next step this key is used to encrypt resp. decrypt the secret part of the header.

  • The secret is the encrypted part of the header and contains sensible data of the container. The secret is encrypted with a wrapping-key, which is the output of the Kdf. The secret contains:

    • master-key: The master-key is used for encryption of the blocks of the container.
    • top-id: The top-id points to some kind of super-block. During service-creation the super-block is aquired (if requested by the service) and its id (the top-id) is stored in the secret.
    • settings of the backend: The backend of the container stores its runtime information in the secret. It gets it back when opening the backend again. See Backend::Settings for more information.

Structs§

Container
The Container type.
CreateOptions
Options used to create a new container.
CreateOptionsBuilder
Utility used to create a CreateOptions instance.
Info
Information from the container.
ModifyOptions
Options used to modify a container.
ModifyOptionsBuilder
Utility used to create a ModifyOptions instance.
OpenOptions
Options used to open a container.
OpenOptionsBuilder
Utility used to create a OpenOptions instance.

Enums§

BufferError
Errors while (de-) serializing binary data.
Cipher
Supported cipher algorithms.
CipherError
Cipher related error codes.
Digest
Supported message digests.
Error
Error type used by this module.
HeaderError
Header related errors.
Kdf
Supported key derivation functions.
KdfError
Kdf related error codes.
MigrationError
PasswordError
Password related error codes.

Constants§

LATEST_REVISION

Traits§

Migration
Service
A service running on top of a Container.
ServiceFactory
Factory used to instantiate a service.

Type Aliases§

ContainerResult