1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
//! # Staticrypt
//!
//! The name is an abbreviation of "Static Encryption" - a Rust proc macro library to encrypt text
//! literals or binary data using [`Aes256Gcm`].
//!
//! The crate is intended to be a successor to [`litcrypt`](https://docs.rs/litcrypt/latest/litcrypt/),
//! and expand on the overall idea of the library.
//!
//! Like litcrypt, staticrypt works by encrypting the given data at compile time. In its place, it
//! leaves the encrypted contents and a 96 bit nonce (unique for every encrypted item), protecting
//! your data from static analysis tools.
//!
//! In contrast to to litcrypt's `lc`, staticrypt's [`sc`] supports all valid Rust string literals,
//! including those with escape sequences, unicode characters, etc.
//!
//! To initialize staticrypt in a crate, the [`use_staticrypt`] macro needs to be called first. See
//! its doc page for more info on initial setup.
//!
//! ## Example
//!
//! ```rust
//! use staticrypt::*;
//!
//! // Needs to be present at the root of the crate.
//! use_staticrypt!();
//!
//! fn main() {
//! // Protect sensitive information from static analysis / tampering
//! println!("The meaning of life is {}", sc!("42"));
//! }
//! ```
//!
//! Everything inside the [`sc`] macro will be encrypted at compile time. You can verify that none
//! of the strings are present in cleartext using something like `strings`:
//!
//! ```shell
//! strings target/debug/my_app | grep 42
//! ```
//!
//! If the output is blank / does not contain the string you are looking for, then your app is safe
//! from static analysis tools.
//!
//! ## DISCLAIMER
//!
//! Although using tools like staticrypt makes it very difficult for attackers to view or alter
//! your data, it does _not_ make it impossible. You should develop your programs with the
//! assumption that a sufficiently determined attacker will be able to reverse engineer your
//! encryption and gain access to any data present in your binary, so it is **highly discouraged** to
//! use this crate to embed sensitive information like API keys, passwords, private keys etc. in your
//! application. You have been warned!
use ;
/// Initializes the use of staticrypt. Should be used at the top level of a crate, i.e. in your
/// `main.rs` or `lib.rs` (wherever `crate` is pointing to).
///
/// This macro will declare a global const named `STATICRYPT_ENCRYPT_KEY` which contains the key
/// used to decrypt contents encrypted with staticrypt. The key itself is not encrypted.
///
/// The key is derived from the seed stored in the environment variable `STATICRYPT_SEED`. If
/// `STATICRYPT_SEED` is missing, or fewer than 32 characters long, it will be padded with randomly
/// generated bytes until it is of length 32.
///
/// If you desire your builds to be reproducible, set `STATICRYPT_SEED` to contain 32 characters.
/// This way, both the generated key and all nonces will be predictable.
pub use use_staticrypt;
/// Encrypts the contained literal string using [`Aes256Gcm`] with the key embedded using
/// [`use_staticrypt`] and a randomly generated nonce (derived from the `STATICRYPT_SEED` env
/// variable at compile time).
///
/// Example:
///
/// ```rust
/// use staticrypt::*;
///
/// use_staticrypt!();
///
/// fn main() {
/// // "My secret text" will be encrypted in the resulting binary
/// let encrypted = sc!("My secret text");
///
/// assert_eq!(encrypted, "My secret text");
///
/// // Also works with unicode / non-standard characters, and escape sequences:
/// let encrypted = sc!("My\0 nonstandard \u{0256} Text \"with escapes\"");
///
/// assert_eq!(encrypted, "My\0 nonstandard \u{0256} Text \"with escapes\"");
/// }
///
/// ```
pub use sc;
/// Reads and encrypts the specified file contents using [`Aes256Gcm`] with the key embedded using
/// [`use_staticrypt`] and a randomly generated nonce (derived from the `STATICRYPT_SEED` env
/// variable at compile time).
///
/// Note that `sc_bytes` does not do any parsing by default, so it always outputs a
/// [`Vec<u8>`](std::vec::Vec).
///
/// Example:
///
/// ```rust
/// use staticrypt::*;
///
/// use_staticrypt!();
///
/// fn main() {
/// let encrypted = String::from_utf8(sc_bytes!("./testfile.txt"))
/// .expect("Should be valid UTF-8");
///
/// assert_eq!(encrypted, "Hello, staticrypt!\n");
/// }
/// ```
pub use sc_bytes;
/// Reads and encrypts the contents of the specified environment variable using [`Aes256Gcm`] with
/// the key embedded using [`use_staticrypt`] and a randomly generated nonce (derived from the
/// `STATICRYPT_SEED` variable at compile time).
///
/// The contents of the environment variable are read at compile time.
///
/// Example:
///
/// ```rust
/// use staticrypt::*;
///
/// use_staticrypt!();
///
/// fn main() {
/// let encrypted = sc_env!("MY_SECRET_VAR");
///
/// assert_eq!(encrypted, "super secret env");
/// }
/// ```
pub use sc_env;
use_staticrypt!;
/// Decrypt an input with a given nonce and key using [`Aes256Gcm`].
///
/// Note that manually calling this function should not be necessary, as the [`sc`] macro already
/// does this behind the scenes.
///
/// # Panics
///
/// This function will panic if the decryption fails. This could happen e.g. due to file corruption
/// of the resulting binary.