Package: devolutions-crypto
devolutions-cryptoCryptographic library used in Devolutions products. It is made to be fast, easy to use and misuse-resistant.DocumentationUsageOverviewCiphertext ModuleSymmetric EncryptionAsymmetric EncryptionKey ModuleKey Generation/DerivationKey ExchangePasswordHash ModuleSecretSharing ModuleSignature ModuleGenerating Key PairsSigning dataSignature VerificationUtils ModuleKey GenerationKey DerivationOverviewThe 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 likeCiphertext,PublicKey, etc.These all implementsTryFrom<&[u8]>andInto<Vec<u8>>which are the implemented way to serialize and deserialize data.usestd::convert::TryFromas_;usedevolutions_crypto::utils::generate_key;usedevolutions_crypto::ciphertext::{encrypt,CiphertextVersion,Ciphertext};letkey:Vec<u8>=generate_key(32);letdata=b"somesecretdata";letencrypted_data:Ciphertext=encrypt(data,&key,CiphertextVersion::Latest).expect("encryption shouldn't fail");// The ciphertext can be serialized.letencrypted_data_vec:Vec<u8>=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 TryFromletciphertext=Ciphertext::try_from(encrypted_data_vec.as_slice()).expect("deserialization shouldn't fail");letdecrypted_data=ciphertext.decrypt(&key).expect("The decryption shouldn't fail");assert_eq!(decrypted_data,data);CiphertextThis 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 aCiphertext, which has a method to decrypt it.Symmetricusedevolutions_crypto::utils::generate_key;usedevolutions_crypto::ciphertext::{encrypt,CiphertextVersion,Ciphertext};letkey:Vec<u8>=generate_key(32);letdata=b"somesecretdata";letencrypted_data:Ciphertext=encrypt(data,&key,CiphertextVersion::Latest).expect("encryption shouldn't fail");letdecrypted_data=encrypted_data.decrypt(&key).expect("The decryption shouldn't fail");assert_eq!(decrypted_data,data);AsymmetricHere, you will need aPublicKeyto encrypt data and the correspondingPrivateKeyto decrypt it. You can generate them by usinggenerate_keypairin theKey module.usedevolutions_crypto::key::{generate_keypair,KeyVersion,KeyPair};usedevolutions_crypto::ciphertext::{encrypt_asymmetric,CiphertextVersion,Ciphertext};letkeypair:KeyPair=generate_keypair(KeyVersion::Latest);letdata=b"somesecretdata";letencrypted_data:Ciphertext=encrypt_asymmetric(data,&keypair.public_key,CiphertextVersion::Latest).expect("encryption shouldn't fail");letdecrypted_data=encrypted_data.decrypt_asymmetric(&keypair.private_key).expect("The decryption shouldn't fail");assert_eq!(decrypted_data,data);KeyFor now, this module only deal with keypairs, as the symmetric keys are not wrapped yet.Generation/DerivationUsinggenerate_keypairwill generate a random keypair.Asymmetric keys have two uses. They can be used toencrypt and decrypt dataand to perform akey exchange.generate_keypairusedevolutions_crypto::key::{generate_keypair,KeyVersion,KeyPair};letkeypair:KeyPair=generate_keypair(KeyVersion::Latest);Key ExchangeThe 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 aKeyPaireach.Alice and Bob exchanges theirPublicKey.Alice mix herPrivateKeywith Bob'sPublicKey. This gives her the shared key.Bob mixes hisPrivateKeywith 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.usedevolutions_crypto::key::{generate_keypair,mix_key_exchange,KeyVersion,KeyPair};letbob_keypair:KeyPair=generate_keypair(KeyVersion::Latest);letalice_keypair:KeyPair=generate_keypair(KeyVersion::Latest);letbob_shared=mix_key_exchange(&bob_keypair.private_key,&alice_keypair.public_key).expect("key exchange should not fail");letalice_shared=mix_key_exchange(&alice_keypair.private_key,&bob_keypair.public_key).expect("key exchange should not fail");// They now have a shared secret!assert_eq!(bob_shared,alice_shared);PasswordHashYou can use this module to hash a password and validate it afterward. This is the recommended way to verify a user password on login.usedevolutions_crypto::password_hash::{hash_password,PasswordHashVersion};letpassword=b"somesuperstrongpa$$w0rd!";lethashed_password=hash_password(password,10000,PasswordHashVersion::Latest);assert!(hashed_password.verify_password(b"somesuperstrongpa$$w0rd!"));assert!(!hashed_password.verify_password(b"someweakpa$$w0rd!"));SecretSharingThis module is used to generate a key that is splitted in multipleShareand 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.usedevolutions_crypto::secret_sharing::{generate_shared_key,join_shares,SecretSharingVersion,Share};// 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.letshares:Vec<Share>=generate_shared_key(5,3,32,SecretSharingVersion::Latest).expect("generation shouldn't fail with the right parameters");assert_eq!(shares.len(),5);letkey=join_shares(&shares[2..5]).expect("joining shouldn't fail with the right shares");SignatureThis module is used to sign data using a keypair to certify its authenticity.Generating Key Pairsusedevolutions_crypto::signing_key::{generate_signing_keypair,SigningKeyVersion,SigningKeyPair,SigningPublicKey};letkeypair:SigningKeyPair=generate_signing_keypair(SigningKeyVersion::Latest);Signing Datausedevolutions_crypto::signature::{sign,Signature,SignatureVersion};letsignature:Signature=sign(b"this is some test data",&keypair,SignatureVersion::Latest);Verifying the signatureusedevolutions_crypto::signature::{sign,Signature,SignatureVersion};assert!(signature.verify(b"this is some test data",&public_key));UtilsThese are a bunch of functions that can
be useful when dealing with the library.Key GenerationThis is a method used to generate a random key. In almost all case, thelengthparameter should be 32.usedevolutions_crypto::utils::generate_key;letkey=generate_key(32);assert_eq!(32,key.len());Key DerivationThis 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.usedevolutions_crypto::utils::{generate_key,derive_key};letkey=b"this is a secret password";letsalt=generate_key(16);letiterations=10000;letlength=32;letnew_key=derive_key(key,&salt,iterations,length);assert_eq!(32,new_key.len());Underlying algorithmsAs of the current version:Symmetric cryptography uses XChaCha20Poly1305Asymmetric cryptography uses Curve25519.Asymmetric encryption uses ECIES.Key exchange uses x25519, or ECDH over Curve25519Password Hashing uses PBKDF2-HMAC-SHA2-256Secret Sharing uses Shamir Secret sharing over GF256