[![License BSD-2-Clause](https://img.shields.io/badge/License-BSD--2--Clause-blue.svg)](https://opensource.org/licenses/BSD-2-Clause) [![License MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![AppVeyor CI](https://ci.appveyor.com/api/projects/status/github/KizzyCode/recordbox-rust?svg=true)](https://ci.appveyor.com/project/KizzyCode/recordbox-rust) [![docs.rs](https://docs.rs/recordbox/badge.svg)](https://docs.rs/recordbox) [![crates.io](https://img.shields.io/crates/v/recordbox.svg)](https://crates.io/crates/recordbox) [![Download numbers](https://img.shields.io/crates/d/recordbox.svg)](https://crates.io/crates/recordbox) [![Dependency status](https://deps.rs/crate/recordbox/0.1.1/status.svg)](https://deps.rs/crate/recordbox/0.1.1) # `recordbox` Welcome to `recordbox` 🎉 This crate offers a simple API to encrypt `id:payload`-style records like network packets or files etc. ## Why? Records are pretty common and often consist of two main elements: 1. An ID which identifies/addresses the record; e.g. a filename or a sequence number (even if implicit) or an entry UUID etc. 2. The associated payload This crate offers an easy and uniform API to encrypt a record payload and tie the resulting ciphertext to the record ID, so that you don't have to implement the same basics by yourself everytime. ## Encryption There are three different kinds of boxes; which one is the best depends on your usecase: ### `Recordbox` The most versatile format is the `Recordbox`. It works by using a SIV implementation which uses the ID as associated data and a fixed nonce. #### Advantages: - Resilient: Due to the nature of SIV constructions, it is completely fine to reuse a record ID for different record payloads. This is useful if the record IDs are not unique (e.g. filenames), and it provides an additional security boundary if your implementation cannot guarantee that a record ID will never be reused. - Versatile: You can basically use any kind of record ID and payload with this box. - Deterministic: Because the same ID+plaintext-combination will always result in the same ciphertext, it is easy to implement a fast reverse lookup and subsequently stuff like deduplication etc, #### Disadvantages: - Not randomized: Because the implementation uses a fixed nonce, the same ID+plaintext-combination will always result in the same ciphertext. This may leak information about equal records and in certain circumstances can be enough to completely break a protocol. - Slow: Most if not all current SIV constructions are significantly slower than e.g. AES-GCM. Even though in most cases this is not a problem, it can be a dealbreaker in certain settings. ### `UniqueRecordbox` The `UniqueRecordbox` is a randomized record box which uses the record ID as (indirect) nonce. It works by deriving a record-specific subkey from the provided key and the record ID and a deterministic or fixed nonce. This is similar to the XChaCha-construction and allows the use of arbitrarily long record IDs (as long as they are unique for each record payload). #### Advantages: - Versatile: You can basically use any kind of record ID and payload with this box. - Fast (for large records): Because this box allows the use of simple AEAD constructions, the encryption of large record payloads is usually significantly faster than if using a SIV construction. #### Disadvantages: - Fragile: Because the key is derived directly from the record ID, you __MUST NEVER__ reuse a record ID for a different record payload. This has proven to be pretty difficult in certain circumstances; especially if you cannot implement a reliable monotonic counter or create sufficiently large random record IDs. - Slow (for small records): Because this box uses a rather expensive subkey derivation, it might not be the best choice if you need to work with a lot of small record payloads. #### Note: This is a fallback scheme because as of today, SIV implementations are not easily available in every language. However in most circumstances you should probably either use a `Recordbox` if you can afford a few more CPU cycles or a `FastRecordBox` if performance is critical. ### `FastRecordBox` The `FastRecordBox` is a randomized record box which directly maps the record ID into a nonce (i.e. _without_ deriving a record-specific subkey). #### Advantages: - Fast: Because this box does not perform any expensive subkey derivation and allows the use of simple AEAD constructions, this is the fastest box scheme available. - Quite Common: Under the hood, this scheme usually translates to a direct invocation of the AEAD construction, which makes it easy to implement it yourself if necessary. ##### Disadvantages: - Fragile: Because the nonce is created directly from the record ID, you __MUST NEVER__ reuse a record ID for a different record payload. This has proven to be pretty difficult in certain circumstances; especially if you cannot implement a reliable monotonic counter. - Short record IDs only: Usually nonces are pretty short (8 to 12 bytes). Therefore, to avoid collisions, there __MUST__ be an injective mapping from each `Self` to the nonce. This also means that your record IDs usually cannot be larger than 8 to 12 bytes. ## TODO - [ ] Provide implementations for the `RecordBox` - [ ] Provide implementations for the `UniqueRecordBox` - [x] Provide implementations for the `FastRecordBox`