4 releases (2 breaking)

0.5.0 Sep 3, 2022
0.4.0 Sep 3, 2022
0.3.2 Sep 3, 2022
0.2.1 Sep 2, 2022
0.1.0 Sep 1, 2022

#609 in Build Utils

Download history 81/week @ 2023-11-20 9/week @ 2023-11-27 1/week @ 2023-12-04 68/week @ 2023-12-18 5/week @ 2023-12-25 55/week @ 2024-02-05 14/week @ 2024-02-12 148/week @ 2024-02-26 41/week @ 2024-03-04

203 downloads per month

MIT/Apache

10KB

envcrypt

envcrypt on crates.io envcrypt on docs.rs envcrypt on deps.rs

Drop-in replacements for env! and option_env! that encrypt your variables at compile-time and decrypt them at runtime.

While it's still possible to reverse-engineer the values, envcrypt prevents strings <my-binary> from trivially finding embedded secrets. See details for more information.

Usage

The envc! and option_envc! macros can be used as drop-in replacements for env! and option_env!, respectively.

As a replacement for env!

use envcrypt::envc;

let my_super_secret_key: &'static str = envc!("SECRET_KEY");
// ...do stuff with your secret key

As a replacement for option_env!

use envcrypt::option_envc;

if let Some(optional_value) = option_envc!("OPTIONAL_SECRET_KEY") {
  // ...do stuff
}

With dotenvy:

.env:

CLIENT_SECRET="my_client_secret"
SOME_TOKEN="some_token"

build.rs:

use dotenvy::dotenv_iter;

fn main(){
 println!("cargo:rerun-if-changed=.env");

 for item in dotenv_iter().unwrap() {
   let (key, value) = item.unwrap();
   println!("cargo:rustc-env=${key}=${value}");
 }

}

main.rs:

use envcrypt::envc;

let client_secret: &'static str = envc!("CLIENT_SECRET");

Details

Encryption is powered by RustCrypto using ChaCha20Poly1305 encryption.

While this is a secure algorithm, it is used in a highly insecure way, which makes it unsuitable for use-cases requiring real cryptographic security. envcrypt works by encrypting an environment variable at compile time and then embedding the encrypted variable along with the encryption key in your binary.

This means that a hacker can still decrypt your secrets, but it's not as trivial as running strings.

Here's an analogy: instead of leaving your front door open (embedding naked strings in your binary), you close and lock the door and put the key under the mat (embedding the encryption key). A criminal can still easily break in to your house, but simply having the door closed and locked will be enough to deter most people.

You can check for yourself that your secrets are not visible in the binary by running strings on the compiled output:

$ cat envcrypt-test/src/main.rs

use envcrypt::envc;

fn main() {
    println!("{}", envc!("ENCRYPTED_KEY"));
    println!("{}", env!("NAKED_KEY"));
}

$ cat envcrypt-test/build.rs

fn main() {
    println!("cargo:rustc-env=ENCRYPTED_KEY=ENCRYPTED_VALUE");
    println!("cargo:rustc-env=NAKED_KEY=NAKED_VALUE");
}

$ cargo build -p envcrypt-test
   Compiling envcrypt v0.2.0 (path/to/envcrypt)
   Compiling envcrypt-test v0.0.0 (path/to/envcrypt/envcrypt-test)
    Finished dev [unoptimized + debuginfo] target(s) in 1.73s


$ strings - target/debug/envcrypt-test | rg VALUE
NAKED_VALUE

Here are instructions for running strings yourself on MacOS, Linux, and Windows.

Dependencies

~1MB
~16K SLoC