Module: Familia::Encryption
- Defined in:
- lib/familia/encryption.rb,
lib/familia/encryption/manager.rb,
lib/familia/encryption/provider.rb,
lib/familia/encryption/registry.rb,
lib/familia/encryption_request_cache.rb,
lib/familia/encryption/providers/aes_gcm_provider.rb,
lib/familia/encryption/providers/xchacha20_poly1305_provider.rb,
lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb
Defined Under Namespace
Modules: Providers Classes: Manager, Provider, Registry
Constant Summary collapse
- EncryptedData =
Data.define(:algorithm, :nonce, :ciphertext, :auth_tag, :key_version)
Class Method Summary collapse
-
.benchmark(iterations: 1000) ⇒ Object
Benchmark available providers.
-
.clear_request_cache! ⇒ Object
Clear all cached keys and disable caching.
-
.decrypt(encrypted_json, context:, additional_data: nil) ⇒ Object
Quick decryption (auto-detects algorithm from data).
-
.derivation_count ⇒ Object
Derivation counter for monitoring no-caching behavior.
-
.encrypt(plaintext, context:, additional_data: nil) ⇒ Object
Quick encryption with auto-selected best provider.
-
.encrypt_with(algorithm, plaintext, context:, additional_data: nil) ⇒ Object
Encrypt with specific algorithm.
-
.hardware_acceleration? ⇒ Boolean
Check if we’re using hardware acceleration.
-
.manager(algorithm: nil) ⇒ Object
Get or create a manager with specific algorithm.
-
.reset_derivation_count! ⇒ Object
-
.secure_wipe(key) ⇒ Object
Clear key from memory (no security guarantees in Ruby).
-
.status ⇒ Object
Get info about current encryption setup.
-
.validate_configuration! ⇒ Object
-
.with_request_cache ⇒ Object
Enable request-scoped caching (opt-in for performance).
Class Method Details
.benchmark(iterations: 1000) ⇒ Object
Benchmark available providers
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 |
# File 'lib/familia/encryption.rb', line 123 def benchmark(iterations: 1000) require 'benchmark' test_data = 'x' * 1024 # 1KB test context = 'benchmark:test' results = {} Registry.providers.each do |algo, provider_class| next unless provider_class.available? mgr = Manager.new(algorithm: algo) time = Benchmark.realtime do iterations.times do encrypted = mgr.encrypt(test_data, context: context) mgr.decrypt(encrypted, context: context) end end results[algo] = { time: time, ops_per_sec: (iterations * 2 / time).round, priority: provider_class.priority } end results end |
.clear_request_cache! ⇒ Object
Clear all cached keys and disable caching
29 30 31 32 33 34 35 36 |
# File 'lib/familia/encryption_request_cache.rb', line 29 def clear_request_cache! if (cache = Thread.current[:familia_request_cache]) cache.each_value { |key| secure_wipe(key) } cache.clear end Thread.current[:familia_request_cache_enabled] = false Thread.current[:familia_request_cache] = nil end |
.decrypt(encrypted_json, context:, additional_data: nil) ⇒ Object
Quick decryption (auto-detects algorithm from data)
75 76 77 |
# File 'lib/familia/encryption.rb', line 75 def decrypt(encrypted_json, context:, additional_data: nil) manager.decrypt(encrypted_json, context: context, additional_data: additional_data) end |
.derivation_count ⇒ Object
Derivation counter for monitoring no-caching behavior
89 90 91 |
# File 'lib/familia/encryption.rb', line 89 def derivation_count @derivation_count ||= Concurrent::AtomicFixnum.new(0) end |
.encrypt(plaintext, context:, additional_data: nil) ⇒ Object
Quick encryption with auto-selected best provider
70 71 72 |
# File 'lib/familia/encryption.rb', line 70 def encrypt(plaintext, context:, additional_data: nil) manager.encrypt(plaintext, context: context, additional_data: additional_data) end |
.encrypt_with(algorithm, plaintext, context:, additional_data: nil) ⇒ Object
Encrypt with specific algorithm
80 81 82 83 84 85 86 |
# File 'lib/familia/encryption.rb', line 80 def encrypt_with(algorithm, plaintext, context:, additional_data: nil) manager(algorithm: algorithm).encrypt( plaintext, context: context, additional_data: additional_data ) end |
.hardware_acceleration? ⇒ Boolean
Check if we’re using hardware acceleration
117 118 119 120 |
# File 'lib/familia/encryption.rb', line 117 def hardware_acceleration? provider = Registry.default_provider provider && provider.class.name.include?('Hardware') end |
.manager(algorithm: nil) ⇒ Object
Get or create a manager with specific algorithm
64 65 66 67 |
# File 'lib/familia/encryption.rb', line 64 def manager(algorithm: nil) @managers ||= {} @managers[algorithm] ||= Manager.new(algorithm: algorithm) end |
.reset_derivation_count! ⇒ Object
93 94 95 |
# File 'lib/familia/encryption.rb', line 93 def reset_derivation_count! derivation_count.value = 0 end |
.secure_wipe(key) ⇒ Object
Clear key from memory (no security guarantees in Ruby)
98 99 100 |
# File 'lib/familia/encryption.rb', line 98 def secure_wipe(key) key&.clear end |
.status ⇒ Object
Get info about current encryption setup
103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/familia/encryption.rb', line 103 def status Registry.setup! if Registry.providers.empty? { default_algorithm: Registry.default_provider&.algorithm, available_algorithms: Registry.available_algorithms, preferred_available: Registry.default_provider&.class&.name, using_hardware: hardware_acceleration?, key_versions: encryption_keys.keys, current_version: current_key_version } end |
.validate_configuration! ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/familia/encryption.rb', line 150 def validate_configuration! raise EncryptionError, 'No encryption keys configured' if encryption_keys.empty? raise EncryptionError, 'No current key version set' unless current_key_version current_key = encryption_keys[current_key_version] raise EncryptionError, "Current key version not found: #{current_key_version}" unless current_key begin Base64.strict_decode64(current_key) rescue ArgumentError raise EncryptionError, 'Current encryption key is not valid Base64' end Registry.setup! raise EncryptionError, 'No encryption providers available' unless Registry.default_provider end |
.with_request_cache ⇒ Object
Enable request-scoped caching (opt-in for performance)
20 21 22 23 24 25 26 |
# File 'lib/familia/encryption_request_cache.rb', line 20 def with_request_cache Thread.current[:familia_request_cache_enabled] = true Thread.current[:familia_request_cache] = {} yield ensure clear_request_cache! end |