dco3-crypto

DRACOON Crypto utils in Rust
Documentation ยป
Report Bug

# dco3-crypto ## What is this? Work in progress Crypto library for DRACOON based on openssl crate. **Breaking changes** are most likely at this early stage - the library is under heavy development and depends on requirements from `dco3` (currently private API wrapper for DRACOON). Changes will be documented in the [release notes](https://github.com/unbekanntes-pferd/dco3-crypto/releases). ### What does work? - Asymmetric encryption / decryption of file keys (RSA) - Keypair generation (RSA) - Keypair encryption / decryption (RSA) - Symmetric encryption / decryption of messages (AES256 GCM) - on the fly encryption / decryption - chunked encryption / decryption ### What is planned? - Refactor asymmetric encryption (split keypair generation from other operations) - Use other libraries like ring as alternative to openssl bindings - Add feature flags to cargo build - Add e2e tests using encryption data from other SDKs / libs and ensure compatibility in pipeline ### What is shipped? Using the crate currently binds to the latest openssl version and is compiled in vendored mode (see [openssl](https://crates.io/crates/openssl) for details). ### How to use? See [crates.io](https://crates.io/crates/dco3_crypto) TL;DR Add the following line to your Cargo.toml file (dependencies): ```toml dco3_crypto = "0.4.1" ``` ## Documentation [Documentation](https://docs.rs/dco3_crypto/latest/dco3_crypto) All detailed documentation is provided via docs on [docs.rs](https://docs.rs/dco3_crypto/latest/dco3_crypto) ## TL; DR usage ### Required imports The lib consists of several traits that are all (currently only) implemented by the `DracoonCrypto` struct. Therefore, the minimum required import is *always* `DracoonCrypto` and the relevant required trait (`DracoonRSACrypto`, `Encrypt`, `Decrypt`, `ChunkedEncryption`, `Encrypter`, `Decrypter`). #### Asymmetric encryption In order to - generate a (plain) user keypair - en/decrypt a user keypair - decrypt a private only - encrypt a file key with a public key (user keypair) - decrypt a file key with a private key (user keypair) Generate a plain user keypair: ```rust use dco3_crypto::{DracoonCrypto, DracoonRSACrypto, UserKeypairVersion}; // RSA2048 is only supported for legacy compatibility // always use UserKeypairVersion::RSA4096 let new_keypair = DracoonCrypto::create_plain_user_keypair(UserKeyPairVersion::RSA4096).unwrap(); ``` Encrypt a plain user keypair: ```rust use dco3_crypto::{DracoonCrypto, DracoonRSACrypto, UserKeypairVersion}; let new_keypair = DracoonCrypto::create_plain_user_keypair(UserKeyPairVersion::RSA4096).unwrap(); let secret ="VerySecret123!"; let enc_keypair = DracoonCrypto::encrypt_private_key(secret, new_keypair).unwrap(); ``` Decrypt a private key only (for public share use): ```rust use dco3_crypto::{DracoonCrypto, DracoonRSACrypto, UserKeypairVersion}; let new_keypair = DracoonCrypto::create_plain_user_keypair(UserKeyPairVersion::RSA4096).unwrap(); let secret ="VerySecret123!"; let enc_keypair = DracoonCrypto::encrypt_private_key(secret, new_keypair).unwrap(); let plain_private_key = DracoonCrypto::decrypt_private_key_only(secret, enc_keypair.private_key_container).unwrap(); ``` Decrypt a protected user keypair: ```rust use dco3_crypto::{DracoonCrypto, DracoonRSACrypto, UserKeypairVersion}; let new_keypair = DracoonCrypto::create_plain_user_keypair(UserKeyPairVersion::RSA4096).unwrap(); let secret ="VerySecret123!"; let enc_keypair = DracoonCrypto::encrypt_private_key(secret, new_keypair).unwrap(); let plain_keypair = DracoonCrypto::decrypt_private_key(secret, enc_keypair).unwrap(); ``` Encrypt a file key using either a plain user keypair or a public key container: ```rust use dco3_crypto::{DracoonCrypto, DracoonRSACrypto, UserKeypairVersion, Encrypt}; let new_keypair = DracoonCrypto::create_plain_user_keypair(UserKeyPairVersion::RSA4096).unwrap(); // encrypt a message to get a plain file key for demo purposes let message = b"Secret message"; let (enc_message, plain_file_key) = DracoonCrypto::encrypt(message.to_vec()).unwrap(); // the function also accepts a public key container as argument let enc_file_key = DracoonCrypto::encrypt_file_key(plain_file_key, plain_keypair).unwrap(); ``` Decrypt the file key using a plain user keypair: ```rust use dco3_crypto::{DracoonCrypto, DracoonRSACrypto, UserKeypairVersion, Encrypt}; let new_keypair = DracoonCrypto::create_plain_user_keypair(UserKeyPairVersion::RSA4096).unwrap(); // encrypt a message to get a plain file key for demo purposes let message = b"Secret message"; let (enc_message, plain_file_key) = DracoonCrypto::encrypt(message.to_vec()).unwrap(); // the function also accepts a public key container as argument let enc_file_key = DracoonCrypto::encrypt_file_key(plain_file_key, plain_keypair).unwrap(); // this code is for demo purposes - plain_keypair is consumed above and needs to be // instantiated again let plain_file_key = DracoonCrypto::decrypt_file_key(enc_file_key, plain_keypair).unwrap(); ``` #### Symmetric encryption Symmetric encryption is represented by the following traits: - Encrypt: needed for in-memory encryption - Decrypt: needed for in-memory decryption - Decrypter: needed to build a decrypter capable of chunked decryption - Encrypter: needed to build an encrypter capable of chunked encryption - ChunkedEncryption: needed for both en- and decryption when using a decrypter / encrypter Encrypt a message on the fly: ```rust use dco3_crypto::{DracoonCrypto, Encrypt}; // encrypt a message to get a plain file key for demo purposes let message = b"Secret message"; let (enc_message, plain_file_key) = DracoonCrypto::encrypt(message.to_vec()).unwrap(); // to encrypt the file key, see asymmetric encryption above ``` Decrypt a message on the fly: ```rust use dco3_crypto::{DracoonCrypto, Encrypt, Decrypt}; // encrypt a message to get a plain file key for demo purposes let message = b"Secret message"; let (enc_message, plain_file_key) = DracoonCrypto::encrypt(message.to_vec()).unwrap(); // to decrypt / encrypt the file key, see asymmetric encryption above let plain_message = DracoonCrypto::decrypt(&enc_message, plain_file_key); ``` Encrypt in chunks: ```rust use dco3_crypto::{DracoonCrypto, Encrypter, ChunkedEncryption}; let mut message = b"Encrypt this very long message in chunks and decrypt it"; let buff_len = message.len() + 1; let mut buf = vec![0u8; buff_len]; let mut encrypter = DracoonCrypto::encrypter(&mut buf).unwrap(); let mut count: usize = 0; // chunks of 8 bytes const CHUNKSIZE: usize = 8; let mut chunks = message.chunks(CHUNKSIZE); while let Some(chunk) = chunks.next() { count += encrypter.update(&chunk).unwrap(); }; count += encrypter.finalize().unwrap(); let enc_message = encrypter.get_message(); let plain_file_key = encrypter.get_plain_file_key(); ``` Decrypt in chunks: ```rust // importing Encrypt is only necessary for the inital message encryption use dco3_crypto::{DracoonCrypto, Encrypt, Decrypter, ChunkedEncryption}; use openssl::symm::Cipher; let message = b"Encrypt this very long message in chunks and decrypt it"; let (message, plain_file_key) = DracoonCrypto::encrypt(message.to_vec()).unwrap(); let buff_len = message.len() + 1; let mut chunks = message.chunks(5); let mut buf = vec![0u8; buff_len]; let mut decrypter = DracoonCrypto::decrypter(plain_file_key, &mut buf).unwrap(); let mut count: usize = 0; while let Some(chunk) = chunks.next() { count += decrypter.update(&chunk).unwrap(); } count += decrypter.finalize().unwrap(); let plain_message = std::str::from_utf8(decrypter.get_message()).unwrap(); ```