devolutions-crypto
Cryptographic library used in Devolutions products. It is made to be fast, easy to use and misuse-resistant.
Usage
Overview
The library is splitted into multiple modules, which are explained below. When
dealing with "managed" data, that includes an header and versionning, you deal
with structures like Ciphertext
, PublicKey
, etc.
These all implements TryFrom<&[u8]>
and Into<Vec<u8>>
which are the implemented way to serialize and deserialize data.
use TryFrom as _;
use generate_key;
use ;
let key: = generate_key;
let data = b"somesecretdata";
let encrypted_data: Ciphertext = encrypt.expect;
// The ciphertext can be serialized.
let encrypted_data_vec: = encrypted_data.into;
// This data can be saved somewhere, passed to another language or over the network
// ...
// When you receive the data as a byte array, you can deserialize it into a struct using TryFrom
let ciphertext = try_from.expect;
let decrypted_data = ciphertext.decrypt.expect;
assert_eq!;
Ciphertext
This module contains everything related to encryption. You can use it to encrypt and decrypt data using either a shared key of a keypair.
Either way, the encryption will give you a Ciphertext
, which has a method to decrypt it.
Symmetric
use generate_key;
use ;
let key: = generate_key;
let data = b"somesecretdata";
let encrypted_data: Ciphertext = encrypt.expect;
let decrypted_data = encrypted_data.decrypt.expect;
assert_eq!;
Asymmetric
Here, you will need a PublicKey
to encrypt data and the corresponding
PrivateKey
to decrypt it. You can generate them by using generate_keypair
or derive_keypair
in the Key module.
use ;
use ;
let keypair: KeyPair = generate_keypair;
let data = b"somesecretdata";
let encrypted_data: Ciphertext = encrypt_asymmetric.expect;
let decrypted_data = encrypted_data.decrypt_asymmetric.expect;
assert_eq!;
Key
For now, this module only deal with keypairs, as the symmetric keys are not wrapped yet.
Generation/Derivation
You have two ways to generate a KeyPair
: Using generate_keypair
will generate a random one, using derive_keypair
will derive one from another password or key along with derivation parameters(including salt). Except in specific circumstances, you should use generate_keypair
.
Asymmetric keys have two uses. They can be used to encrypt and decrypt data and to perform a key exchange.
generate_keypair
use ;
let keypair: KeyPair = generate_keypair;
derive_keypair
use Argon2Parameters;
use ;
let parameters: Argon2Parameters = Default default;
let keypair: KeyPair = derive_keypair.expect;
Key Exchange
The goal of using a key exchange is to get a shared secret key between two parties without making it possible for users listening on the conversation to guess that shared key.
- Alice and Bob generates a
KeyPair
each. - Alice and Bob exchanges their
PublicKey
. - Alice mix her
PrivateKey
with Bob'sPublicKey
. This gives her the shared key. - Bob mixes his
PrivateKey
with Alice'sPublicKey
. This gives him the shared key. - Both Bob and Alice has the same shared key, which they can use for symmetric encryption for further communications.
use ;
let bob_keypair: KeyPair = generate_keypair;
let alice_keypair: KeyPair = generate_keypair;
let bob_shared = mix_key_exchange.expect;
let alice_shared = mix_key_exchange.expect;
// They now have a shared secret!
assert_eq!;
PasswordHash
You can use this module to hash a password and validate it afterward. This is the recommended way to verify a user password on login.
use ;
let password = b"somesuperstrongpa$$w0rd!";
let hashed_password = hash_password;
assert!;
assert!;
SecretSharing
This module is used to generate a key that is splitted in multiple Share
and that requires a specific amount of them to regenerate the key.
You can think of it as a "Break The Glass" scenario. You can
generate a key using this, lock your entire data by encrypting it
and then you will need, let's say, 3 out of the 5 administrators to decrypt
the data. That data could also be an API key or password of a super admin account.
use ;
// You want a key of 32 bytes, splitted between 5 people, and I want a
// minimum of 3 of these shares to regenerate the key.
let shares: = generate_shared_key.expect;
assert_eq!;
let key = join_shares.expect;
Utils
These are a bunch of functions that can be useful when dealing with the library.
Key Generation
This is a method used to generate a random key. In almost all case, the length
parameter should be 32.
use generate_key;
let key = generate_key;
assert_eq!;
Key Derivation
This is a method used to generate a key from a password or another key. Useful for password-dependant cryptography. Salt should be a random 16 bytes array if possible and iterations should be 10000 or configurable by the user.
use ;
let key = b"this is a secret password";
let salt = generate_key;
let iterations = 10000;
let length = 32;
let new_key = derive_key;
assert_eq!;
Underlying algorithms
As of the current version:
- Symmetric cryptography uses XChaCha20Poly1305
- Asymmetric cryptography uses Curve25519.
- Asymmetric encryption uses ECIES.
- Key exchange uses x25519, or ECDH over Curve25519
- Password Hashing uses PBKDF2-HMAC-SHA2-256
- Secret Sharing uses Shamir Secret sharing over GF256