Crate libes

source ·
Expand description

libes

Crates.io GitHub last commit Crates.io docs.rs Libraries.io

library of encryption schemes is a collection of ECIES variants.

The goal of this is library is to become a one-stop shop for everything ECIES.

For project details like ECIES variant flowcharts, explanations, license, and release tracks please see the README.md on GitHub.

⚠️ Beta Release Track - Not Production Ready ⚠️

During beta development, versions 0.2+.Z, backwards compatibility for decryption is guaranteed.

This means that data encrypted using library version X.Y.Z can be decrypted using any superseding library version as long as X is the same, even if the algorithm used for encryption was yanked it will still be available for decryption until X is incremented.

The public API structure will not change, but algorithms that are potentially found to be broken for any reason will be immediately removed and the library will be released with an incremented Y in X.Y.Z, and versions implementing that algorithm will be yanked.

The private API is still under development, so make sure that you always use the latest version 0.Y.Z to receive all patches that are released. An incremented Z in X.Y.Z will not require any modifications in your code, of course with the exception for an algorithm being yanked.

The mechanics of libes

Internally, libes is built up using generics. This allows the library to add support for algorithms with only a couple lines of code per algorithm to glue the dependency providing that algorithm with the private trait system. Then all the procedures are automatically & appropriately implemented with the help of generics & constraints. This significantly reduces the risk for human error, and ensures that the behavior is uniform between all supported algorithms.

Externally, this is abstracted for the user with the struct Ecies<K, E, A> where:

  • K is an Elliptic Curve algorithm from key
  • E is an Encryption algorithm from enc
  • A is an Authentication algorithm from auth

Ecies<K, E, A> can be instantiated using the associated function new(recipient_public_key), and then the method encrypt(plaintext) will become available to use for encryption. The instantiated struct can be safely reused to encrypt multiple messages for the same recipient. The struct also has an associated function decrypt(recipient_secret_key, ciphertext) for decryption.

The library user is responsible for choosing K & E that are compatible with A, otherwise encryption and/or decryption functionality will not be available on the struct.

Compatibility can be determined by checking whether K & E implement:

Short usage guide

  1. We decide that we want to use the ECIES-AEAD variant
  2. We need to choose an Elliptic Curve algorithm from key and an Encryption algorithm from enc that are compatible with ECIES-AEAD
  3. Both key::X25519 and enc::XChaCha20Poly1305 implement EciesAeadEncryptionSupport and EciesAeadDecryptionSupport, so we can choose to use those algorithms
  4. We will use auth::Aead to mark that it is our Authentication algorithm of choice
  5. We enable the corresponding features for the libes dependency to compile our chosen functionality
    • [dependencies.libes]
      version = "0" # For the Beta Release Track, always use the latest major version 0
      features = ["ECIES-AEAD", "x25519", "XChaCha20-Poly1305"]
      

Code example

Receiver

// Create an alias for Ecies with our chosen algorithms
type MyEcies = Ecies<key::X25519, enc::XChaCha20Poly1305, auth::Aead>;

// Generate an appropriate elliptic key pair
let secret_key = x25519_dalek::StaticSecret::new(rand_core::OsRng);
let public_key = x25519_dalek::PublicKey::from(&secret_key);

// Convert public_key to bytes
let public_key_bytes = public_key.to_bytes().to_vec();

// Send public_key_bytes to the message sender

~~~ Network ~~~

Sender

// Create an alias for Ecies with our chosen algorithms
type MyEcies = Ecies<key::X25519, enc::XChaCha20Poly1305, auth::Aead>;

// Instantiate Ecies using the received public_key_bytes
let encryptor = MyEcies::try_new(public_key_bytes)?;

// Encrypt the message
let message = b"Hello Alice, this is Bob.";
let encrypted_message = encryptor.encrypt(message)?;

// Send encrypted_message to the message recipient

~~~ Network ~~~

Receiver

// Create an alias for Ecies with our chosen algorithms
type MyEcies = Ecies<key::X25519, enc::XChaCha20Poly1305, auth::Aead>;

// Decrypt the message
let decrypted_message = MyEcies::decrypt(&secret_key, &encrypted_message)?;

Algorithm support

Matrix entries are of form Encryption & Decryption or Encryption/Decryption

Elliptic Curve Support Matrix

Algorithm/ECIES VariantECIES-MACECIES-AEADECIES-SYN
x25519🚀🚀🚀
ed25519🚀🚀🚀
K-256 / secp256k1🚀🚀🚀
P-256 / secp256r1🚀🚀🚀
P-384 / secp384r1🚀🚀🚀
P-521 / secp521r1🤔🤔🤔

Encryption Support Matrix

Algorithm/ECIES VariantECIES-MACECIES-AEADECIES-SYN
ChaCha20-Poly1305🚀🚀🚀
XChaCha20-Poly1305🚀🚀🚀
AES128-GCM🚫1🚫1🚫1
AES256-GCM🚀🚀🚀

Authentication Support Matrix

Algorithm/ECIES VariantECIES-MAC
HMAC-SHA256🚀
HMAC-SHA512🤔

  1. AES128-GCM uses a 128-bit key and a 96-bit nonce, and when using a CSPRNG as the de-facto source to generate them, the collision risk in a 224-bit space is unsatisfactory. Due to this encryption is not implemented, along with decryption in order to not encourage using this variant in other libraries. Note: like AES128-GCM, AES256-GCM and some other encryption algorithms in this library also use a 96-bit nonce, but unlike AES256-GCM they have larger keys like 256 bits, which when combined with a 96-bit nonce makes the collision risk acceptable. 

Modules

  • Markers for Authentication algorithms supported by libes
  • Markers for Encryption algorithms supported by libes
  • Markers for Elliptic Curve algorithms supported by libes
  • Support marker traits

Structs

  • Generic ECIES instance

Enums