Skip to content

Commit

Permalink
Merge pull request #4 from unbekanntes-pferd/0.3.0
Browse files Browse the repository at this point in the history
0.3.0: refactor chunked encryption, generic implementation
  • Loading branch information
unbekanntes-pferd committed Jan 5, 2023
2 parents 12fc6ac + ad43863 commit efb8a8f
Show file tree
Hide file tree
Showing 5 changed files with 569 additions and 253 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/testing.yml
Expand Up @@ -2,7 +2,7 @@ name: Rust

on:
push:
branches: [ "master" ]
branches: [ "*" ]
pull_request:
branches: [ "master" ]

Expand All @@ -18,5 +18,7 @@ jobs:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
- name: Lint (clippy)
run: cargo clippy -- -D warnings
- name: Run tests
run: cargo test --verbose
4 changes: 2 additions & 2 deletions Cargo.toml
@@ -1,20 +1,20 @@
[package]
name = "dco3_crypto"
version = "0.2.0"
version = "0.3.0"
edition = "2021"
authors = ["Octavio Simone"]
repository = "https://github.com/unbekanntes-pferd/dco3-crypto"
homepage = "https://github.com/unbekanntes-pferd/dco3-crypto"
license = "MIT"
readme = "README.md"
license-file = "LICENSE"
keywords = ["dracoon", "cryptography", "openssl"]
description = "Symmetric and asymmetric encryption for DRACOON in Rust."


# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
log = "0.4.17"
serde_json = "1.0.89"
serde = { version = "1.0.149", features = ["serde_derive"] }
openssl = { version = "0.10", features = ["vendored"] }
183 changes: 177 additions & 6 deletions README.md
Expand Up @@ -3,7 +3,7 @@
<p align="center">
DRACOON Crypto utils in Rust
<br />
<a href="https://github.com/unbekanntes-pferd/dco3-crypto"><strong>Explore the docs »</strong></a>
<a href="https://docs.rs/dco3_crypto/latest/dco3_crypto"><strong>Documentation »</strong></a>
<br />
<a href="https://github.com/unbekanntes-pferd/dco3-crypto/issues">Report Bug</a>
</p>
Expand All @@ -15,30 +15,201 @@

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?

- Chunked encryption / decryption is currently not generic and requires openssl crate
- make Crypter generic, so that other libraries can be used
- 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 binds to the latest openssl version and is compiled in vendored mode (see [openssl](https://crates.io/crates/openssl) for details).
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.2.0"
dco3_crypto = "0.3.0"
```

## Documentation

[Documentation](https://docs.rs/dco3_crypto/latest/dco3_crypto)
All documentation is provided via docs on [docs.rs](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
- 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 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();

```

0 comments on commit efb8a8f

Please sign in to comment.