Cocoon Rust Package (Instantiating the Electrum Fork: Part One)

Programming Jul 10, 2021

This may be what's necessary in order to ensure that the container that we create to secure the environment we use to create the Bitcoin address (or that of any other cryptocurrency project), remains secure as we're running it.

Rust crate can be found here: https://docs.rs/cocoon/0.2.3/cocoon/

The problem is described as thus:

"Whenever you need to transmit and store data securely you reinvent the wheel: you have to take care of how to encrypt data properly, how to handle randomly generated buffers, then how to get data back, parse, and decrypt. Instead, you can use MiniCocoon and Cocoon."

Not sure what KDF is to be used for this, but in an instance where one only needs to use "simple sequential encryption/decryption operations", they claim that it is recommended to use "MiniCocoon".

Below is the following Rust code that they provide.

let mut data = "my secret data".to_owned().into_bytes();
let cocoon = MiniCocoon::from_key(b"0123456789abcdef0123456789abcdef", &[0; 32]);

let detached_prefix = cocoon.encrypt(&mut data)?;
assert_ne!(data, b"my secret data");

cocoon.decrypt(&mut data, &detached_prefix)?;
assert_eq!(data, b"my secret data");

This could've been something that would be useful if there was a better KDF used here instead of the PBKDF2-SHA256.

Not sure how viable it would be to swap out the KDF, but if this were something that could be done in the future - then perhaps it could be entertained. This shouldn't be too difficult if the source code can first be obtained (don't know enough about Rust package / create system yet to navigate those waters at this point in time).

Evaluating the Proposed Use Case Given

In the hosted package, the maintainers provide the following use case:

"You implement a database of secrets that must be stored in an encrypted file using a user password. There are a lot of ways how your database can be represented in memory and how it could be serialized. You handle these aspects on your own, e.g. you can use HashMap to manage data and use borsh, or bincode, to serialize the data. You can even compress a serialized buffer before encryption. In the end, you use Cocoon to put the final image into an encrypted container."

Then they provide code to associate with this as well.

use borsh::BorshSerialize;
use cocoon::{Cocoon, Error};

use std::collections::HashMap;
use std::fs::File;

// Your data can be represented in any way.
#[derive(BorshSerialize)]
struct Database {
    inner: HashMap<String, String>,
}

fn main() -> Result<(), Error> {
    let mut file = File::create("target/test.db")?;
    let mut db = Database { inner: HashMap::new() };

    // Over time you collect some kind of data.
    db.inner.insert("my.email@example.com".to_string(), "eKPV$PM8TV5A2".to_string());

    // You can choose how to serialize data. Also, you can compress it.
    let encoded = db.try_to_vec().unwrap();

    // Finally, you want to store your data secretly.
    // Supply some password to Cocoon: it can be any byte array, basically.
    // Don't use a hard-coded password in real life!
    // It could be a user-supplied password.
    let cocoon = Cocoon::new(b"secret password");

    // Dump the serialized database into a file as an encrypted container.
    let container = cocoon.dump(encoded, &mut file)?;

    Ok(())
}

Container Structure and Setup

The container is ephemeral, which is pretty great.

This is noted under the 'zeroization' section where it states, "The encryption key is wrapped into a zeroizing container (provided by zeroize crate), which means that the key is erased automatically once it is dropped."

The 'zeroization' crate being referenced here can be found here: https://docs.rs/zeroize/1.3.0/zeroize/

More information on how to 'zeroize' an application using Rust can be found here: http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html

This was originally written by Colin Percival, which is interesting (have had a few conversations with him; he's a dick - but he is the creator of the Scrypt algorithm).

Moving forward, here is the Rust code that is given.

use zeroize::Zeroize;

fn main() {
    // Protip: don't embed secrets in your source code.
    // This is just an example.
    let mut secret = b"Air shield password: 1,2,3,4,5".to_vec();
    // [ ... ] open the air shield here

    // Now that we're done using the secret, zero it out.
    secret.zeroize();
}

Moving forward (yet going back to the 'cocoon' container), a workflow is provided.

Below is the next step.

Once this step is fulfilled, the 'container parsing' process begins.

Upon completion of the final step, we master key is derived from the password and a salt - then the integrity of all parts are verified before the data is eventually decrypted.

Conclusion

This is something that will definitely be considered in the future moving forward as we consider how to create architectures that can be used to ensure that cryptocurrency like Bitcoin, Ethereum, etc., can be leveraged in a secure manner.

The plan in the future moving forward is to create a fork of the Electrum wallet that provides the type of security assurances that users deserve to have in order to promote higher standards of safety (as well as privacy) for cryptocurrency users.

Tags

cryptomedication

Happy to serve and help wherever I'm needed in the blockchain space. #Education #EthicalContent #BringingLibretotheForefront

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.