25 unstable releases (5 breaking)

0.7.5 Nov 8, 2024
0.7.2 Sep 27, 2024
0.6.8 Jul 31, 2024
0.5.0 Mar 5, 2024
0.2.1 Oct 13, 2023

#165 in Cryptography

Download history 142/week @ 2024-07-29 1/week @ 2024-08-05 7/week @ 2024-08-12 14/week @ 2024-08-26 177/week @ 2024-09-02 214/week @ 2024-09-16 248/week @ 2024-09-23 42/week @ 2024-09-30 10/week @ 2024-10-07 164/week @ 2024-10-14 145/week @ 2024-10-21 14/week @ 2024-10-28 129/week @ 2024-11-04 13/week @ 2024-11-11

307 downloads per month
Used in 2 crates

MIT license

295KB
5.5K SLoC

nuts-container: A secure storage library.

Introduction

The nuts library implements a secure storage library, where data are stored in a container. The container is divided into encrypted blocks. So a nuts container looks like a block device. All the things (e.g. keys) you need to open it are stored in the container itself. The library has a rich API, so it can be easily integrated into you application.

The container does not manage the encrypted data itself. It is transferred to a backend that is solely responsible for the persistent storage of the blocks. In this way, the data can easily be stored on different media or in different formats. The keys remain in the container and do not have to be stored in the backend.

Features

The following encryption algorithms are supported:

  • AES128-GCM
  • AES128-CTR
  • AES192-GCM
  • AES192-CTR
  • AES256-GCM
  • AES256-CTR
  • None (which basically disables encryption)

The actual key used for encryption of the blocks (and further information) is encrypted with a PBKDF2 derivated wrapping key, which is based on a password provided by the user.

You have a self-contained container, which means that all information you need to open the container are stored in the first block. Some basic information (like used cipher & wrapping key algorithm) are stored unencrypted, but most of the information are also encrypted in the header.

Examples

// Create a new container

use nuts_container::container::*;
use nuts_container::memory::MemoryBackend;

// Create a container with a memory backend.
// This backend stores the encrypted blocks in memory.
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 an existing container

use nuts_container::container::*;
use nuts_container::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
    // but the memory-backend still has stored its data.
    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);
  • nuts-directory A sample implementation of a backend where all the data are stored in a directory hierarchy.
  • nuts-archive An application on top of nuts-container where files are stored in a tar like archive.
  • nuts-tool A commandline applicatin used to maintain a nuts-container and its application.

License

You can check out the full license here.

This project is licensed under the terms of the MIT license.

Dependencies

~1.8–6MB
~140K SLoC