PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
anonymizer.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
19#pragma once
20
22#include "tag_action.h"
23#include "uid_mapping.h"
24
27
28#include <kcenon/common/patterns/result.h>
29
30#include <chrono>
31#include <functional>
32#include <map>
33#include <memory>
34#include <optional>
35#include <string>
36#include <vector>
37
38namespace kcenon::pacs::security {
39
49enum class private_tag_action : std::uint8_t {
50 keep,
53};
54
90public:
91 // ========================================================================
92 // Construction
93 // ========================================================================
94
100
105
109 anonymizer(anonymizer&& other) noexcept;
110
114 auto operator=(const anonymizer& other) -> anonymizer&;
115
119 auto operator=(anonymizer&& other) noexcept -> anonymizer&;
120
124 ~anonymizer() = default;
125
126 // ========================================================================
127 // Anonymization Operations
128 // ========================================================================
129
142 [[nodiscard]] auto anonymize(core::dicom_dataset& dataset)
144
156 [[nodiscard]] auto anonymize_with_mapping(
157 core::dicom_dataset& dataset,
158 uid_mapping& mapping
160
161 // ========================================================================
162 // Profile Configuration
163 // ========================================================================
164
169 [[nodiscard]] auto get_profile() const noexcept -> anonymization_profile;
170
179
180 // ========================================================================
181 // Private Tag Handling
182 // ========================================================================
183
194
199 [[nodiscard]] auto get_private_tag_action() const noexcept
201
202 // ========================================================================
203 // Custom Tag Actions
204 // ========================================================================
205
214 void add_tag_action(core::dicom_tag tag, tag_action_config config);
215
220 void add_tag_actions(
221 const std::map<core::dicom_tag, tag_action_config>& actions
222 );
223
229 auto remove_tag_action(core::dicom_tag tag) -> bool;
230
235
244 [[nodiscard]] auto get_tag_action(core::dicom_tag tag) const
246
247 // ========================================================================
248 // Date Shifting
249 // ========================================================================
250
259 void set_date_offset(std::chrono::days offset);
260
265 [[nodiscard]] auto get_date_offset() const noexcept
266 -> std::optional<std::chrono::days>;
267
271 void clear_date_offset();
272
282 [[nodiscard]] static auto generate_random_date_offset(
283 std::chrono::days min_days = std::chrono::days{-365},
284 std::chrono::days max_days = std::chrono::days{365}
285 ) -> std::chrono::days;
286
287 // ========================================================================
288 // Encryption Configuration
289 // ========================================================================
290
296 [[nodiscard]] auto set_encryption_key(std::span<const std::uint8_t> key)
297 -> kcenon::common::VoidResult;
298
303 [[nodiscard]] auto has_encryption_key() const noexcept -> bool;
304
305 // ========================================================================
306 // Hash Configuration
307 // ========================================================================
308
317 void set_hash_salt(std::string salt);
318
323 [[nodiscard]] auto get_hash_salt() const
324 -> std::optional<std::string>;
325
326 // ========================================================================
327 // Audit and Reporting
328 // ========================================================================
329
338 void set_detailed_reporting(bool enable);
339
344 [[nodiscard]] auto is_detailed_reporting() const noexcept -> bool;
345
346 // ========================================================================
347 // Static Helpers
348 // ========================================================================
349
355 [[nodiscard]] static auto get_profile_actions(anonymization_profile profile)
356 -> std::map<core::dicom_tag, tag_action_config>;
357
362 [[nodiscard]] static auto get_hipaa_identifier_tags()
363 -> std::vector<core::dicom_tag>;
364
369 [[nodiscard]] static auto get_gdpr_personal_data_tags()
370 -> std::vector<core::dicom_tag>;
371
372private:
375
378
380 std::optional<std::chrono::days> date_offset_;
381
383 std::vector<std::uint8_t> encryption_key_;
384
386 std::optional<std::string> hash_salt_;
387
390
393
394 // Internal helpers
395 [[nodiscard]] auto apply_action(
396 core::dicom_dataset& dataset,
397 core::dicom_tag tag,
398 const tag_action_config& config,
399 uid_mapping* mapping
401
402 [[nodiscard]] auto shift_date(std::string_view date_string) const
403 -> std::string;
404
405 [[nodiscard]] auto hash_value(std::string_view value) const
406 -> std::string;
407
408 [[nodiscard]] auto encrypt_value(std::string_view value) const
410
412};
413
414} // namespace kcenon::pacs::security
DICOM de-identification profiles per PS3.15 Annex E.
void clear_custom_actions()
Clear all custom tag actions.
auto hash_value(std::string_view value) const -> std::string
~anonymizer()=default
Default destructor.
static auto get_hipaa_identifier_tags() -> std::vector< core::dicom_tag >
Get a list of HIPAA Safe Harbor identifier tags.
private_tag_action private_tag_action_
Action for private tags.
Definition anonymizer.h:389
void set_detailed_reporting(bool enable)
Enable detailed action recording.
std::optional< std::string > hash_salt_
Hash salt.
Definition anonymizer.h:386
auto apply_action(core::dicom_dataset &dataset, core::dicom_tag tag, const tag_action_config &config, uid_mapping *mapping) -> tag_action_record
void add_tag_action(core::dicom_tag tag, tag_action_config config)
Add or override a tag action.
void set_hash_salt(std::string salt)
Set salt for hash operations.
anonymizer(anonymization_profile profile=anonymization_profile::basic)
Construct with a specific profile.
static auto get_gdpr_personal_data_tags() -> std::vector< core::dicom_tag >
Get a list of GDPR personal data tags.
auto get_tag_action(core::dicom_tag tag) const -> tag_action_config
Get the effective action for a tag.
std::optional< std::chrono::days > date_offset_
Date offset for shifting.
Definition anonymizer.h:380
void set_profile(anonymization_profile profile)
Set a new profile.
auto get_date_offset() const noexcept -> std::optional< std::chrono::days >
Get the current date offset.
static auto get_profile_actions(anonymization_profile profile) -> std::map< core::dicom_tag, tag_action_config >
Get tags to process for a given profile.
std::vector< std::uint8_t > encryption_key_
Encryption key (if set)
Definition anonymizer.h:383
void clear_date_offset()
Clear the date offset (dates will be zeroed instead)
void add_tag_actions(const std::map< core::dicom_tag, tag_action_config > &actions)
Add multiple tag actions.
auto anonymize_with_mapping(core::dicom_dataset &dataset, uid_mapping &mapping) -> kcenon::common::Result< anonymization_report >
Anonymize with consistent UID mapping.
auto has_encryption_key() const noexcept -> bool
Check if encryption is configured.
auto get_hash_salt() const -> std::optional< std::string >
Get the current hash salt.
static auto generate_random_date_offset(std::chrono::days min_days=std::chrono::days{-365}, std::chrono::days max_days=std::chrono::days{365}) -> std::chrono::days
Generate a random date offset.
anonymization_profile profile_
Current anonymization profile.
Definition anonymizer.h:374
auto set_encryption_key(std::span< const std::uint8_t > key) -> kcenon::common::VoidResult
Set encryption key for encrypt actions.
void set_date_offset(std::chrono::days offset)
Set date offset for longitudinal consistency.
auto encrypt_value(std::string_view value) const -> kcenon::common::Result< std::string >
auto get_profile() const noexcept -> anonymization_profile
Get the current profile.
auto is_detailed_reporting() const noexcept -> bool
Check if detailed reporting is enabled.
bool detailed_reporting_
Whether to include detailed action records in report.
Definition anonymizer.h:392
auto get_private_tag_action() const noexcept -> private_tag_action
Get the current private tag action.
auto remove_tag_action(core::dicom_tag tag) -> bool
Remove a custom tag action (reverts to profile default)
std::map< core::dicom_tag, tag_action_config > custom_actions_
Custom tag actions (override profile defaults)
Definition anonymizer.h:377
auto anonymize(core::dicom_dataset &dataset) -> kcenon::common::Result< anonymization_report >
Anonymize a DICOM dataset.
auto operator=(const anonymizer &other) -> anonymizer &
Copy assignment.
void set_private_tag_action(private_tag_action action)
Set the action to take on private tags during anonymization.
DICOM Dataset - ordered collection of Data Elements.
DICOM Tag representation (Group, Element pairs)
anonymization_profile
DICOM de-identification profiles based on PS3.15 Annex E.
@ basic
Basic Profile - Remove direct identifiers.
@ shift_date
Shift dates by a fixed offset.
private_tag_action
Action to take on private tags during anonymization.
Definition anonymizer.h:49
@ keep
Preserve all private tags (default for backward compatibility)
@ remove_data
Remove private data elements but keep creators (for auditing)
@ remove_all
Remove all private data elements and their creators.
Configuration for a custom tag action.
Definition tag_action.h:148
Record of an action performed on a tag.
Definition tag_action.h:210
Tag action definitions for DICOM de-identification.
UID mapping for consistent de-identification across studies.