[][src]Crate arx_kw

ARX-KW

crates.io Docs.rs Rust Report Card dependency status Build Status codecov MIT license

This library features implementations of the ARX-KW family of novel Key Wrap constructions.

The version number for this crate will be incremented in compliance with Semantic Versioning.


Background

ARX-KW was first presented in this paper written by Satō Shinichi and submitted to the IACR Cryptology ePrint Archive in January 2020. As the name suggests, these constructions make extensive use of add-rotate-xor algorithms: each of the four variants specified involves both the SipHash-2-4 pseudorandom function with 128-bit output and a stream cipher from the ChaCha family of stream ciphers.

ARX-KW is a cipher for deteministic, authenticated encryption which aims to provide strong authenticity and confidentiality while minimizing the storage overhead and simplicity of use when compared to existing constructions using the ChaCha cipher which require either keeping state for a nonce and a block counter or having a substantial storage overhead in order to manage the nonce statelessly.

ARX-KW has a static overhead of 128 bits for each of its four variants without the need to keep state for the nonce used by ChaCha, making the storage overhead only 50% for a 256-bit key


Use

When

As noted above, the ARX-KW constructions are Key Wrap algorithms, designed and intended to protect other cryptographic keys using symmetric encryption. It is important to note that as ARX-KW, like all Key Wrap constructions, was designed with the expectation that its input data is highly entropic, as is the case with secret keys. This is because it is a deterministic encryption scheme and will always yield the same ciphertext output for a given input; if used to encrypt low-entropy data (as with general-purpose encryption schemes), it is vulnerable to "leakage", described here:

Deterministic encryption can leak information to an eavesdropper, who may recognize known ciphertexts. For example, when an adversary learns that a given ciphertext corresponds to some interesting message, they can learn something every time that ciphertext is transmitted. To gain information about the meaning of various ciphertexts, an adversary might perform a statistical analysis of messages transmitted over an encrypted channel, or attempt to correlate ciphertexts with observed actions (e.g., noting that a given ciphertext is always received immediately before a submarine dive).

If used to store secret key material (by nature high entropy), this is not an issue as an attacker gains no information about the key encapsulated within.

Features

Nightly

Use the nightly feature to enable SIMD parallelization of the ChaCha computations (nightly Rust required):

Cargo.toml

[dependencies]
arx-kw = {version = "0.3", features = ["nightly"]}

Variants

The four variants are gated under individual features ("e", "g", "ex", and "gx") for conditional compilation if not all are going to be used. All are enabled by default, but for example if you only want to use the gx::GX variant:

Cargo.toml

[dependencies]
arx-kw = { version = "0.3", default-features=false, features=["gx"] }

How

Each public module of this crate contains a struct corresponding to one of the four specified ARX-KW-8-2-4 variants: ARX-8-2-4-E, ARX-8-2-4-G, ARX-8-2-4-EX, and ARX-8-2-4-GX. If you're not sure which to use, gx::GX is recommended. The functionality is provided by the ArxKW trait, so that will need to be in scope to use the ArxKW::encrypt/ArxKW::encrypt_blob and ArxKW::decrypt/ArxKW::decrypt_blob methods. The ConstantTimeEq trait from the subtle crate is re-exported by this crate and is implemented on the AuthTag type as well as those covered by the blanket implementations subtle provides.

Eq and PartialEq are by design not implemented for AuthTag to discourage equality checking that is not O(1), but the internal [u8;16] is public should you want to live






Ḑ̷͉͎̺̳̭͖̗̦̪͓̂͗͒̓̅̆̋̐́̓̓̎̊͐̍̂̈͂̇͆̇͐̉̈̄̈́̈́̓̓̾͒̕͠à̸̢̛̤̠̺̩̱̤̭̪̮̙͈̱̀̍͂̋̓̓͊̈́͊̋̀̾͌͂͘͘̚n̶̡̡̢̪̼̲̫̪̯͖̟͕͚̬̠̥̫̱̮̖̼̪͚̜͙̥̬̙̪̩̮̞̰̼̲̭̏̀̀ģ̸̨̧̳̟͙͙̳̘̥͖̮̼̻͍̯̦̖͋͆̃̏͛̒̌̅͊̃̿̄̒̋͜͜͝͝ͅ ̸̧̟̼͉̳̰̥̮̙͈͖͙͎͇̙͍͚͔͒͋͋̋̒̚͠ͅͅͅè̵̡̘̲̪͔̪̥̹̟̾̅̓͛̐̐̽̅͌̊̓̔̍̓̿̊̆̂̈́͑̽̅̿̚͝͝r̵̛̭̺̠̙̞̫̗̞̪̗̹͎͌͌͌̒̏̌̅̇̉̑̂͋̅̅̀̔̉̾̋̅̏̓͘̚ờ̸̢̡̢̥̟̗̘͉̠̣͕̮͈͍͉̳̫̲̖͖̻̝̯̟͂̊̈́͑̇́͛̏͜͠u̷̎͋͂̽̉͒́̈́̑̋́̌͂̿̋̆́͜͝͝͝s̸̡̡̡̞̞͇͖̖͍̝͖̣̪͓͖̥̟͙̫̪̗͙̯̞͍̽̃̆̒̐̐̊̓̾̚̚ͅĺ̴͕͖͎̣̞͕̙̹̓͒y̷̢̠̠͇͉̘̠̩̳̲͗̑͐̿̿̐͗͊̀̽̀͐̀̿̔̈́͘͝͝







Encrypt a key

extern crate hex;
use hex::FromHex;

use arx_kw::{
    ArxKW,
    gx::GX,
    ConstantTimeEq, // From the subtle crate, allows for equality checking in constant time
                    // (impl'd for AuthTag and re-exported by this crate)
    assert_ct_eq,
};

// Encrypt a key using ARX-KW-8-2-4-GX with the encrypt_blob method

// The values used here are from the test vectors in the original ARX-KW paper.
/* 
 * Inputs
 */ 
// The encryption key we are using to wrap the plaintext secret key
let key = <[u8; 32]>::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")?; 
// The plaintext secret key we want to store/transport securely
let plaintext = <[u8; 32]>::from_hex("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")?; 

/*
 * Expected output: 
 * A Vec<u8> containing the authentication tag followed by the ciphertext containing the
 * wrapped key. We can treat this as an opaque blob when using the encrypt_blob and decrypt_blob
 * methods, meaning we don't have to manually manage authentication tags or nonces.
 */
let blob_expected = <[u8; 48]>::from_hex("016325cf6a3c4b2e3b039675e1ccbc652f83f391c97f3606ccd5709c6ee15d66cd7e65a2aeb7dc3066636e8f6b0d39c3")?;

/*
 * Key wrapping performed in one line, simply passing the 
 * encryption key and the plaintext to be encrypted.
 */
let blob = GX::encrypt_blob(&key, &plaintext)?; 
assert_ct_eq!(blob, &blob_expected);

/*
 * Decryption likewise is done in one line, passing the key and the blob to be decrypted.
 * The authentication tag is checked to match the ciphertext
 * during decryption and will return an error if the tags do not match.
 * Returns the decrypted plaintext if successful, otherwise an error.
 */
let decrypted_plaintext = GX::decrypt_blob(&key, &blob)?;
assert_ct_eq!(plaintext, &decrypted_plaintext);

Modules

e

Module containing items related to the ARX-KW-8-2-4-E variant

ex

Module containing items related to the ARX-KW-8-2-4-EX variant

g

Module containing items related to the ARX-KW-8-2-4-G variant

gx

Module containing items related to the ARX-KW-8-2-4-GX variant

Macros

assert_ct_eq

Macro which provides an equivalent of assert_eq in constant time using the ConstantTimeEq trait. Accordingly, ConstantTimeEq must be in scope and implemented on the types of $x and $y for this to work. It is implemented for AuthTag and many primitives.

Structs

AuthTag

The type used as the authentication tag (unencrypted data to be stored alongside encrypted keys) This is the same for all variants at time of writing (a single, static 128 bits), making for a 50% storage overhead for a 256-bit key like those used for ChaCha

Choice

The Choice struct represents a choice for use in conditional assignment.

Enums

ArxKwError

The error type used by this crate.

InvalidLengthError

An error denoting that a value was of an invalid length. Typically this will be used as a variant of ArxKwError rather than on its own.

Traits

ArxKW

Provides encryption and decryption capabilites

ConstantTimeEq

An Eq-like trait that produces a Choice instead of a bool.