Conceal is a modern, header-only C++ library for safely wrapping sensitive values.
It prevents accidental leaks of secrets (like passwords or tokens) by ensuring that printing or serializing a Conceal<T> never reveals the underlying value, while still allowing seamless use of the wrapped type in your code.
This project is for educational and experimental purposes only and is not intended for production use.
It is meant to explore the topic of accidental data leaks in C++.
This library does not provide cryptographic security or memory erasure.
- Type-safe wrapper for any type (
Conceal<T>) - Prevents accidental leaks: printing or serializing a
Conceal<T>never reveals the value - Seamless usage: implicit conversion and operators for easy integration
- JSON support: integrates with nlohmann/json by default
- Header-only: just include and use, no build step required
#include <conceal/conceal.hpp>
#include <iostream>
#include <cassert>
#include <sstream>
int main() {
conceal::Conceal<std::string> secret("my_password");
// Use as a normal string
assert(secret->size() == 11);
// Printing never reveals the value
std::ostringstream oss;
oss << secret;
assert(oss.str() == "<hidden>");
}-
Add to your CMake project:
add_subdirectory(path/to/conceal) target_link_libraries(your_target PRIVATE conceal)
-
JSON support
-
nlohmann/json will be required and automatically linked.
-
To disable JSON support, set the option in your
CMakeLists.txt:set(CONCEAL_USE_JSON OFF)
-
Or from the command line:
cmake .. -DCONCEAL_USE_JSON=OFF
-
-
Custom hidden message
- By default, the hidden message is
<hidden>. - To override it, set the option in your CMakeLists.txt
set(CONCEAL_HIDDEN_MSG "***SECRET***")
-Or from the command line:
cmake .. -DCONCEAL_HIDDEN_MSG="***SECRET***" - By default, the hidden message is
-
Copy
include/conceal/conceal.hppinto your project. -
By default, JSON support is not enabled. To enable JSON support, define the macro
CONCEAL_USE_JSONbefore including the header:#define CONCEAL_USE_JSON // You can also override the default hidden message #define CONCEAL_HIDDEN_MSG "***SECRET***" #include <conceal/conceal.hpp>
#include <conceal/conceal.hpp>
#include <nlohmann/json.hpp>
#include <iostream>
#include <string>
#include <cassert>
#include <sstream>
struct User {
int id;
std::string username;
conceal::Conceal<std::string> password;
friend void to_json(nlohmann::json& j, const User& user) {
j = nlohmann::json{{"id", user.id}, {"username", user.username}, {"password", user.password}};
// password will always be serialized as null
}
friend void from_json(const nlohmann::json& j, User& user) {
j.at("id").get_to(user.id);
j.at("username").get_to(user.username);
if (j.contains("password")) j.at("password").get_to(user.password);
}
};
int main() {
User admin{1, "admin", conceal::Conceal<std::string>{"super_secret"}};
// Print user (password is hidden)
std::ostringstream oss1;
oss1 << admin.password;
assert(oss1.str() == "<hidden>");
// Serialize to JSON (password is hidden)
nlohmann::json j = admin;
assert(j["password"].is_null());
// Deserialize from JSON
std::string json_payload = R"({"id":2,"username":"guest","password":"guestpass"})";
User guest = nlohmann::json::parse(json_payload).get<User>();
std::ostringstream oss2;
oss2 << guest.password;
assert(oss2.str() == "<hidden>");
assert(*guest.password == "guestpass");
}To build and run tests/examples with CMake:
git clone https://github.com/Jarsop/conceal.git
cd conceal
cmake -B build -S .
cmake --build build
# Run example
./build/examples/conceal_example
# Run tests
ctest --test-dir buildDependencies:
- nlohmann/json (for JSON support, enabled by default)
- GoogleTest (optional, for tests)
Conceal<T>()Conceal<T>(const T&)Conceal<T>(T&&)- Copy/move constructors and assignment
- Implicit conversion to/from
T - Comparison operators
- Stream output (
<<) always prints<hidden> - JSON serialization always outputs
null(by default)
Q: Can I use Conceal with any type?
A: Yes, as long as the type is copyable/movable. It works with standard and user-defined types.
Q: Does Conceal provide cryptographic security?
A: No. Conceal is for accidental leak prevention (e.g., logs, serialization). It does not encrypt or securely erase memory.
Q: How do I access the real value?
A: Use implicit conversion or dereference:
std::string s = secret; // or
std::string s = *secret;MIT License