Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
kcenon::logger::security::secure_key_storage Class Reference

Secure storage and retrieval of encryption keys. More...

#include <secure_key_storage.h>

Collaboration diagram for kcenon::logger::security::secure_key_storage:
Collaboration graph

Static Public Member Functions

static result< secure_keygenerate_key (size_t size=32)
 Generate a secure random key.
 
static common::VoidResult save_key (const secure_key &key, const std::filesystem::path &path, const std::filesystem::path &allowed_base="/var/log/keys")
 Save key to file with secure permissions.
 
static result< secure_keyload_key (const std::filesystem::path &path, size_t expected_size=32, const std::filesystem::path &allowed_base="/var/log/keys")
 Load key from file with permission verification.
 

Static Private Member Functions

static common::VoidResult validate_key_path (const std::filesystem::path &path, const std::filesystem::path &allowed_base)
 Validate key file path (prevent path traversal)
 

Detailed Description

Secure storage and retrieval of encryption keys.

Security features:

  • File permission verification (0600)
  • Path traversal prevention
  • Secure random generation
  • Memory cleanup after use

Definition at line 141 of file secure_key_storage.h.

Member Function Documentation

◆ generate_key()

static result< secure_key > kcenon::logger::security::secure_key_storage::generate_key ( size_t size = 32)
inlinestatic

Generate a secure random key.

Parameters
sizeKey size in bytes (default: 32 for AES-256)
Returns
Result containing the generated key or error

Definition at line 148 of file secure_key_storage.h.

148 {
149 secure_key key(size);
150
151#ifdef HAS_OPENSSL
152 // Use OpenSSL's cryptographically secure random generator
153 if (RAND_bytes(key.mutable_data().data(), size) != 1) {
154 return result<secure_key>{
156 "Failed to generate secure random key"};
157 }
158#else
159 // Fallback: use std::random_device (less secure on some platforms)
160 std::random_device rd;
161 for (size_t i = 0; i < size; ++i) {
162 key.mutable_data()[i] = static_cast<uint8_t>(rd() & 0xFF);
163 }
164#endif
165
166 return result<secure_key>(std::move(key));
167 }
@ size
Rotate based on file size only.

References kcenon::logger::encryption_failed, kcenon::logger::security::secure_key::mutable_data(), and kcenon::logger::size.

Here is the call graph for this function:

◆ load_key()

static result< secure_key > kcenon::logger::security::secure_key_storage::load_key ( const std::filesystem::path & path,
size_t expected_size = 32,
const std::filesystem::path & allowed_base = "/var/log/keys" )
inlinestatic

Load key from file with permission verification.

Parameters
pathFile path
expected_sizeExpected key size (default: 32 for AES-256)
allowed_baseBase directory for key storage
Returns
Result containing the loaded key or error

Definition at line 250 of file secure_key_storage.h.

254 {
255 // 1. Validate path
256 auto validation = validate_key_path(path, allowed_base);
257 if (validation.is_err()) {
258 return result<secure_key>{
259 get_logger_error_code(validation),
260 get_logger_error_message(validation)};
261 }
262
263 // 2. Check if file exists
264 if (!std::filesystem::exists(path)) {
265 return result<secure_key>{
267 "Key file does not exist"};
268 }
269
270 // 3. Verify file permissions (must not be readable by group/others)
271 try {
272 auto status = std::filesystem::status(path);
273 auto perms = status.permissions();
274
275 if ((perms & std::filesystem::perms::group_read) != std::filesystem::perms::none ||
276 (perms & std::filesystem::perms::others_read) != std::filesystem::perms::none) {
277 return result<secure_key>{
279 "Key file permissions are too permissive (must be 0600 or stricter)"};
280 }
281 } catch (const std::filesystem::filesystem_error& e) {
282 return result<secure_key>{
284 std::string("Failed to check file permissions: ") + e.what()};
285 }
286
287 // 4. Verify file size
288 size_t file_size = 0;
289 try {
290 file_size = std::filesystem::file_size(path);
291 } catch (const std::filesystem::filesystem_error& e) {
292 return result<secure_key>{
294 std::string("Failed to get file size: ") + e.what()};
295 }
296
297 if (file_size != expected_size) {
298 return result<secure_key>{
300 "Invalid key file size (expected " + std::to_string(expected_size) +
301 " bytes, got " + std::to_string(file_size) + ")"};
302 }
303
304 // 5. Read key from file
305 std::ifstream file(path, std::ios::binary);
306 if (!file) {
307 return result<secure_key>{
309 "Failed to open key file for reading"};
310 }
311
312 secure_key key(expected_size);
313 file.read(
314 reinterpret_cast<char*>(key.mutable_data().data()),
315 expected_size
316 );
317
318 if (file.fail()) {
319 return result<secure_key>{
321 "Failed to read key data"};
322 }
323
324 return result<secure_key>(std::move(key));
325 }
static common::VoidResult validate_key_path(const std::filesystem::path &path, const std::filesystem::path &allowed_base)
Validate key file path (prevent path traversal)
std::string get_logger_error_message(const common::VoidResult &result)
Get error message from a VoidResult.
logger_error_code get_logger_error_code(const common::VoidResult &result)

References kcenon::logger::file_open_failed, kcenon::logger::file_permission_denied, kcenon::logger::file_read_failed, kcenon::logger::get_logger_error_code(), kcenon::logger::get_logger_error_message(), kcenon::logger::insecure_permissions, kcenon::logger::invalid_key_size, kcenon::logger::security::secure_key::mutable_data(), and validate_key_path().

Here is the call graph for this function:

◆ save_key()

static common::VoidResult kcenon::logger::security::secure_key_storage::save_key ( const secure_key & key,
const std::filesystem::path & path,
const std::filesystem::path & allowed_base = "/var/log/keys" )
inlinestatic

Save key to file with secure permissions.

Parameters
keyThe key to save
pathFile path (must be in allowed directory)
allowed_baseBase directory for key storage
Returns
Success or error

Definition at line 176 of file secure_key_storage.h.

180 {
181 // 1. Validate path
182 auto validation = validate_key_path(path, allowed_base);
183 if (validation.is_err()) {
184 return validation;
185 }
186
187 // 2. Ensure parent directory exists
188 try {
189 auto parent = path.parent_path();
190 if (!parent.empty() && !std::filesystem::exists(parent)) {
191 std::filesystem::create_directories(parent);
192 }
193 } catch (const std::filesystem::filesystem_error& e) {
196 std::string("Failed to create key directory: ") + e.what()
197 );
198 }
199
200 // 3. Write key to file
201 std::ofstream file(path, std::ios::binary | std::ios::trunc);
202 if (!file) {
205 "Failed to open key file for writing"
206 );
207 }
208
209 file.write(
210 reinterpret_cast<const char*>(key.data().data()),
211 key.size()
212 );
213
214 if (file.fail()) {
217 "Failed to write key data"
218 );
219 }
220
221 file.close();
222
223 // 4. Set secure file permissions (0600 = owner read/write only)
224 try {
225 std::filesystem::permissions(
226 path,
227 std::filesystem::perms::owner_read |
228 std::filesystem::perms::owner_write,
229 std::filesystem::perm_options::replace
230 );
231 } catch (const std::filesystem::filesystem_error& e) {
232 // Permission setting failed, delete the insecure file
233 std::filesystem::remove(path);
236 std::string("Failed to set secure permissions: ") + e.what()
237 );
238 }
239
240 return common::ok();
241 }
VoidResult ok()
common::VoidResult make_logger_void_result(logger_error_code code, const std::string &message="")

References kcenon::logger::security::secure_key::data(), kcenon::logger::file_permission_denied, kcenon::logger::file_write_failed, kcenon::logger::make_logger_void_result(), kcenon::common::ok(), kcenon::logger::security::secure_key::size(), and validate_key_path().

Here is the call graph for this function:

◆ validate_key_path()

static common::VoidResult kcenon::logger::security::secure_key_storage::validate_key_path ( const std::filesystem::path & path,
const std::filesystem::path & allowed_base )
inlinestaticprivate

Validate key file path (prevent path traversal)

Parameters
pathPath to validate
allowed_baseBase directory that path must be within
Returns
Success or error

Definition at line 334 of file secure_key_storage.h.

337 {
338 try {
339 // Convert both paths to absolute canonical form
340 auto canonical_path = std::filesystem::weakly_canonical(path);
341 auto canonical_base = std::filesystem::weakly_canonical(allowed_base);
342
343 // Check if path starts with allowed_base
344 auto [mismatch_iter, _] = std::mismatch(
345 canonical_base.begin(), canonical_base.end(),
346 canonical_path.begin(), canonical_path.end()
347 );
348
349 if (mismatch_iter != canonical_base.end()) {
352 "Key path must be within allowed directory: " +
353 canonical_base.string()
354 );
355 }
356
357 return common::ok();
358 } catch (const std::filesystem::filesystem_error& e) {
361 std::string("Path validation failed: ") + e.what()
362 );
363 }
364 }

References kcenon::logger::make_logger_void_result(), kcenon::common::ok(), and kcenon::logger::path_traversal_detected.

Referenced by load_key(), and save_key().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following file: