| Crates.io | encrypt_config |
| lib.rs | encrypt_config |
| version | 2.0.1 |
| created_at | 2023-12-18 04:56:04.03676+00 |
| updated_at | 2025-04-19 03:14:39.668216+00 |
| description | A Rust crate to manage, persist and encrypt your configurations. |
| homepage | |
| repository | https://github.com/kingwingfly/encrypt-config |
| max_upload_size | |
| id | 1073050 |
| size | 57,960 |
A rust crate to manage, persist and encrypt your configurations.
Explore the docs »
View Demo
·
Report Bug
·
Request Feature
[dependencies]
encrypt_config = { version = "2.0", features = ["full"] }
[profile.dev.package.num-bigint-dig]
opt-level = 3
On linux, the keys will expired or removed after reboot or long-term unused. So the rsa private key will be lost
which leads this crate unable to decrypt the encrypted config file. So we recommend to easily use PersistSource
instead of SecretSource on linux even other platforms, they are actually safe enough.
Sometimes, we need to store config in our application that we don't want to expose to the public. For example, the database password, the api key, etc.
One solution is to store them in the OS' secret manager, such as Keychain on macOS, Credential Manager on Windows, libsecret on Linux.
However, they usually have limitation on the secret length. For example, Keychain only allows 255 bytes for the secret, Credential Manager is even shorter. So we can't store a long secret in it.
Another solution is to store the secret in a file and encrypt it with a rsa public key, and store the private key in the OS' secret manager. This is what this crate does.
This crate provides 3 ways to manage your config:
NormalSource]: A normal source, not persisted or encryptedPersistSource]: A source that will be persisted to local file, not encryptedSecretSource]: A source that will be persisted to local file and encryptedThis crate also has some optional features:
persist: If enabled, you can use the [PersistSource] trait.secret: If enabled, you can use the [PersistSource] and the [SecretSource] trait.mock: If enabled, you can use the mock for testing, which will not use the OS' secret manager.default_config_dir: If enabled, the default config dir will be used. Implemented through dirs.Moreover, as development progresses, a memory cache design is added for persistent data access speeding up. This leads this crate actually behaving more like bevy_ecs's resource system (or dependencies injecion with only args retrieving implemented). The cache is released as an independent crate rom_cache.
The Config in this crate is a wrapper of rom_cache::Cache, only if the config is modified and marked dirty will the data be persisted to the storage.
# #[cfg(all(feature = "full", feature = "mock", feature = "default_config_dir"))]
# {
use encrypt_config::{Config, NormalSource, PersistSource, SecretSource};
use serde::{Deserialize, Serialize};
use std::sync::OnceLock;
#[derive(Default, NormalSource)]
struct NormalConfig {
count: usize,
}
#[derive(Default, Serialize, Deserialize, PersistSource)]
#[source(name = "persist_config.json")]
struct PersistConfig {
name: String,
age: usize,
}
#[derive(Default, Serialize, Deserialize, SecretSource)]
#[source(name = "secret_config", keyring_entry = "secret")]
struct SecretConfig {
password: String,
}
{
// Here we have 2 kinds of config at the same time at most, so N is 2
let cfg: Config<2> = Config::default();
{
let normal = cfg.get::<NormalConfig>();
// default value
assert_eq!(normal.count, 0);
}
{
let mut normal = cfg.get_mut::<NormalConfig>();
normal.count = 42;
assert_eq!(normal.count, 42);
}
{
let mut persist = cfg.get_mut::<PersistConfig>();
persist.name = "Louis".to_string();
persist.age = 22;
let mut secret = cfg.get_mut::<SecretConfig>();
secret.password = "123456".to_string();
}
// Changes will be saved automatically as Config dropped
}
{
// Assume this is a new config in the next start
// Here we have 1 kinds of config at the same time at most, so N is 1
let cfg: Config<1> = Config::default();
{
// normal config will not be saved
assert_eq!(cfg.get::<NormalConfig>().count, 0);
// persist config will be saved
assert_eq!(cfg.get::<PersistConfig>().name, "Louis");
// secret config will be encrypted
assert_eq!(cfg.get::<SecretConfig>().password, "123456");
}
// The secret config file should not be able to load directly
let encrypted_file = std::fs::File::open(SecretConfig::path()).unwrap();
assert!(serde_json::from_reader::<_, SecretConfig>(encrypted_file).is_err());
}
# }
Surely, you can also easily use methods provided by PersistSource and SecretSource
to load and save the config manually, instead of the complex Config cache.
For more examples, please refer to the tests, Example or Documentation
trait_upcasting stablized, MSRV is bumped to 1.86Config now behaves totally like a native cache. Changes will be saved as Config dropped automatically.Config now behaves more like a native cache. Changes will be saved as ConfigMut dropped automatically.Config in one go. But add_xx_sources are removed. By the way, one can defined their own sources by implementing Source trait while NormalSource PersistSource SecretSource are still provided.std::any and methods from dependencies injection.See the open issues for a full list of proposed features (and known issues).
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Distributed under the MIT License. See LICENSE.txt for more information.
Louis - 836250617@qq.com
Project Link: https://github.com/kingwingfly/encrypt-config