familia 2.0.0.pre4 → 2.0.0.pre6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rubocop_todo.yml +17 -17
- data/CLAUDE.md +11 -8
- data/Gemfile +5 -1
- data/Gemfile.lock +19 -3
- data/README.md +36 -157
- data/docs/overview.md +359 -0
- data/docs/wiki/API-Reference.md +347 -0
- data/docs/wiki/Connection-Pooling-Guide.md +437 -0
- data/docs/wiki/Encrypted-Fields-Overview.md +101 -0
- data/docs/wiki/Expiration-Feature-Guide.md +596 -0
- data/docs/wiki/Feature-System-Guide.md +600 -0
- data/docs/wiki/Features-System-Developer-Guide.md +892 -0
- data/docs/wiki/Field-System-Guide.md +784 -0
- data/docs/wiki/Home.md +106 -0
- data/docs/wiki/Implementation-Guide.md +276 -0
- data/docs/wiki/Quantization-Feature-Guide.md +721 -0
- data/docs/wiki/RelatableObjects-Guide.md +563 -0
- data/docs/wiki/Security-Model.md +183 -0
- data/docs/wiki/Transient-Fields-Guide.md +280 -0
- data/lib/familia/base.rb +18 -27
- data/lib/familia/connection.rb +6 -5
- data/lib/familia/{datatype → data_type}/commands.rb +2 -5
- data/lib/familia/{datatype → data_type}/serialization.rb +8 -10
- data/lib/familia/data_type/types/counter.rb +38 -0
- data/lib/familia/{datatype → data_type}/types/hashkey.rb +20 -2
- data/lib/familia/{datatype → data_type}/types/list.rb +17 -18
- data/lib/familia/data_type/types/lock.rb +43 -0
- data/lib/familia/{datatype → data_type}/types/sorted_set.rb +17 -17
- data/lib/familia/{datatype → data_type}/types/string.rb +11 -3
- data/lib/familia/{datatype → data_type}/types/unsorted_set.rb +17 -18
- data/lib/familia/{datatype.rb → data_type.rb} +12 -14
- data/lib/familia/encryption/encrypted_data.rb +137 -0
- data/lib/familia/encryption/manager.rb +119 -0
- data/lib/familia/encryption/provider.rb +49 -0
- data/lib/familia/encryption/providers/aes_gcm_provider.rb +123 -0
- data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +184 -0
- data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +138 -0
- data/lib/familia/encryption/registry.rb +50 -0
- data/lib/familia/encryption.rb +178 -0
- data/lib/familia/encryption_request_cache.rb +68 -0
- data/lib/familia/errors.rb +17 -3
- data/lib/familia/features/encrypted_fields/concealed_string.rb +295 -0
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +221 -0
- data/lib/familia/features/encrypted_fields.rb +28 -0
- data/lib/familia/features/expiration.rb +107 -77
- data/lib/familia/features/quantization.rb +5 -9
- data/lib/familia/features/relatable_objects.rb +2 -4
- data/lib/familia/features/safe_dump.rb +14 -17
- data/lib/familia/features/transient_fields/redacted_string.rb +159 -0
- data/lib/familia/features/transient_fields/single_use_redacted_string.rb +62 -0
- data/lib/familia/features/transient_fields/transient_field_type.rb +139 -0
- data/lib/familia/features/transient_fields.rb +47 -0
- data/lib/familia/features.rb +40 -24
- data/lib/familia/field_type.rb +273 -0
- data/lib/familia/horreum/{connection.rb → core/connection.rb} +6 -15
- data/lib/familia/horreum/{commands.rb → core/database_commands.rb} +20 -21
- data/lib/familia/horreum/core/serialization.rb +535 -0
- data/lib/familia/horreum/{utils.rb → core/utils.rb} +9 -12
- data/lib/familia/horreum/core.rb +21 -0
- data/lib/familia/horreum/{settings.rb → shared/settings.rb} +10 -4
- data/lib/familia/horreum/subclass/definition.rb +469 -0
- data/lib/familia/horreum/{class_methods.rb → subclass/management.rb} +27 -250
- data/lib/familia/horreum/{related_fields_management.rb → subclass/related_fields_management.rb} +15 -10
- data/lib/familia/horreum.rb +30 -22
- data/lib/familia/logging.rb +14 -14
- data/lib/familia/settings.rb +39 -3
- data/lib/familia/utils.rb +45 -0
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +3 -2
- data/try/core/base_enhancements_try.rb +115 -0
- data/try/core/connection_try.rb +0 -1
- data/try/core/create_method_try.rb +240 -0
- data/try/core/database_consistency_try.rb +299 -0
- data/try/core/errors_try.rb +25 -5
- data/try/core/familia_extended_try.rb +3 -4
- data/try/core/familia_try.rb +1 -2
- data/try/core/persistence_operations_try.rb +297 -0
- data/try/core/pools_try.rb +2 -2
- data/try/core/secure_identifier_try.rb +0 -1
- data/try/core/settings_try.rb +0 -1
- data/try/core/utils_try.rb +0 -1
- data/try/{datatypes → data_types}/boolean_try.rb +1 -2
- data/try/data_types/counter_try.rb +93 -0
- data/try/{datatypes → data_types}/datatype_base_try.rb +2 -3
- data/try/{datatypes → data_types}/hash_try.rb +1 -2
- data/try/{datatypes → data_types}/list_try.rb +1 -2
- data/try/data_types/lock_try.rb +133 -0
- data/try/{datatypes → data_types}/set_try.rb +1 -2
- data/try/{datatypes → data_types}/sorted_set_try.rb +1 -2
- data/try/{datatypes → data_types}/string_try.rb +1 -2
- data/try/debugging/README.md +32 -0
- data/try/debugging/cache_behavior_tracer.rb +91 -0
- data/try/debugging/debug_aad_process.rb +82 -0
- data/try/debugging/debug_concealed_internal.rb +59 -0
- data/try/debugging/debug_concealed_reveal.rb +61 -0
- data/try/debugging/debug_context_aad.rb +68 -0
- data/try/debugging/debug_context_simple.rb +80 -0
- data/try/debugging/debug_cross_context.rb +62 -0
- data/try/debugging/debug_database_load.rb +64 -0
- data/try/debugging/debug_encrypted_json_check.rb +53 -0
- data/try/debugging/debug_encrypted_json_step_by_step.rb +62 -0
- data/try/debugging/debug_exists_lifecycle.rb +54 -0
- data/try/debugging/debug_field_decrypt.rb +74 -0
- data/try/debugging/debug_fresh_cross_context.rb +73 -0
- data/try/debugging/debug_load_path.rb +66 -0
- data/try/debugging/debug_method_definition.rb +46 -0
- data/try/debugging/debug_method_resolution.rb +41 -0
- data/try/debugging/debug_minimal.rb +24 -0
- data/try/debugging/debug_provider.rb +68 -0
- data/try/debugging/debug_secure_behavior.rb +73 -0
- data/try/debugging/debug_string_class.rb +46 -0
- data/try/debugging/debug_test.rb +46 -0
- data/try/debugging/debug_test_design.rb +80 -0
- data/try/debugging/encryption_method_tracer.rb +138 -0
- data/try/debugging/provider_diagnostics.rb +110 -0
- data/try/edge_cases/hash_symbolization_try.rb +0 -1
- data/try/edge_cases/json_serialization_try.rb +0 -1
- data/try/edge_cases/reserved_keywords_try.rb +42 -11
- data/try/encryption/config_persistence_try.rb +192 -0
- data/try/encryption/encryption_core_try.rb +328 -0
- data/try/encryption/instance_variable_scope_try.rb +31 -0
- data/try/encryption/module_loading_try.rb +28 -0
- data/try/encryption/providers/aes_gcm_provider_try.rb +178 -0
- data/try/encryption/providers/xchacha20_poly1305_provider_try.rb +169 -0
- data/try/encryption/roundtrip_validation_try.rb +28 -0
- data/try/encryption/secure_memory_handling_try.rb +125 -0
- data/try/features/encrypted_fields_core_try.rb +125 -0
- data/try/features/encrypted_fields_integration_try.rb +216 -0
- data/try/features/encrypted_fields_no_cache_security_try.rb +219 -0
- data/try/features/encrypted_fields_security_try.rb +377 -0
- data/try/features/encryption_fields/aad_protection_try.rb +138 -0
- data/try/features/encryption_fields/concealed_string_core_try.rb +250 -0
- data/try/features/encryption_fields/context_isolation_try.rb +141 -0
- data/try/features/encryption_fields/error_conditions_try.rb +116 -0
- data/try/features/encryption_fields/fresh_key_derivation_try.rb +128 -0
- data/try/features/encryption_fields/fresh_key_try.rb +168 -0
- data/try/features/encryption_fields/key_rotation_try.rb +123 -0
- data/try/features/encryption_fields/memory_security_try.rb +37 -0
- data/try/features/encryption_fields/missing_current_key_version_try.rb +23 -0
- data/try/features/encryption_fields/nonce_uniqueness_try.rb +56 -0
- data/try/features/encryption_fields/secure_by_default_behavior_try.rb +310 -0
- data/try/features/encryption_fields/thread_safety_try.rb +199 -0
- data/try/features/encryption_fields/universal_serialization_safety_try.rb +174 -0
- data/try/features/expiration_try.rb +0 -1
- data/try/features/feature_dependencies_try.rb +159 -0
- data/try/features/quantization_try.rb +0 -1
- data/try/features/real_feature_integration_try.rb +148 -0
- data/try/features/relatable_objects_try.rb +0 -1
- data/try/features/safe_dump_advanced_try.rb +0 -1
- data/try/features/safe_dump_try.rb +0 -1
- data/try/features/transient_fields/redacted_string_try.rb +248 -0
- data/try/features/transient_fields/refresh_reset_try.rb +164 -0
- data/try/features/transient_fields/simple_refresh_test.rb +50 -0
- data/try/features/transient_fields/single_use_redacted_string_try.rb +310 -0
- data/try/features/transient_fields_core_try.rb +181 -0
- data/try/features/transient_fields_integration_try.rb +260 -0
- data/try/helpers/test_helpers.rb +67 -0
- data/try/horreum/base_try.rb +157 -3
- data/try/horreum/enhanced_conflict_handling_try.rb +176 -0
- data/try/horreum/field_categories_try.rb +118 -0
- data/try/horreum/field_definition_try.rb +96 -0
- data/try/horreum/initialization_try.rb +1 -2
- data/try/horreum/relations_try.rb +1 -2
- data/try/horreum/serialization_persistent_fields_try.rb +165 -0
- data/try/horreum/serialization_try.rb +41 -7
- data/try/memory/memory_basic_test.rb +73 -0
- data/try/memory/memory_detailed_test.rb +121 -0
- data/try/memory/memory_docker_ruby_dump.sh +80 -0
- data/try/memory/memory_search_for_string.rb +83 -0
- data/try/memory/test_actual_redactedstring_protection.rb +38 -0
- data/try/models/customer_safe_dump_try.rb +1 -2
- data/try/models/customer_try.rb +1 -2
- data/try/models/datatype_base_try.rb +1 -2
- data/try/models/familia_object_try.rb +0 -1
- metadata +131 -23
- data/lib/familia/horreum/serialization.rb +0 -445
data/docs/wiki/Home.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# Familia v2.0 Documentation
|
2
|
+
|
3
|
+
Welcome to the comprehensive documentation for Familia v2.0. This wiki covers all major features including security, connection management, architecture, and object relationships.
|
4
|
+
|
5
|
+
## 📚 Documentation Structure
|
6
|
+
|
7
|
+
### 🔐 Security & Data Protection
|
8
|
+
|
9
|
+
1. **[Encrypted Fields Overview](Encrypted-Fields-Overview.md)** - Persistent encrypted storage with modular providers
|
10
|
+
2. **[Transient Fields Guide](Transient-Fields-Guide.md)** - Non-persistent secure data handling with RedactedString
|
11
|
+
3. **[Security Model](Security-Model.md)** - Cryptographic design and Ruby memory limitations
|
12
|
+
|
13
|
+
### 🏗️ Architecture & System Design
|
14
|
+
|
15
|
+
4. **[Feature System Guide](Feature-System-Guide.md)** - Modular architecture with dependencies and conflict resolution _(new!)_
|
16
|
+
5. **[Connection Pooling Guide](Connection-Pooling-Guide.md)** - Provider pattern for efficient Redis/Valkey pooling _(new!)_
|
17
|
+
6. **[RelatableObjects Guide](RelatableObjects-Guide.md)** - Object relationships and ownership system _(new!)_
|
18
|
+
|
19
|
+
### 🛠️ Implementation & Usage
|
20
|
+
|
21
|
+
7. **[Implementation Guide](Implementation-Guide.md)** - Configuration, providers, and advanced usage
|
22
|
+
8. **[API Reference](API-Reference.md)** - Complete class and method documentation
|
23
|
+
|
24
|
+
### 🚀 Operations (As Needed)
|
25
|
+
|
26
|
+
9. **[Migration Guide](Migration-Guide.md)** - Upgrading existing fields _(coming soon)_
|
27
|
+
10. **[Key Management](Key-Management.md)** - Rotation and best practices _(coming soon)_
|
28
|
+
|
29
|
+
## 🚀 Quick Start Examples
|
30
|
+
|
31
|
+
### Encrypted Fields (Persistent)
|
32
|
+
```ruby
|
33
|
+
class User < Familia::Horreum
|
34
|
+
feature :encrypted_fields
|
35
|
+
encrypted_field :secret_recipe
|
36
|
+
end
|
37
|
+
|
38
|
+
# Configure encryption
|
39
|
+
Familia.configure do |config|
|
40
|
+
config.encryption_keys = { v1: ENV['FAMILIA_ENCRYPTION_KEY'] }
|
41
|
+
config.current_key_version = :v1
|
42
|
+
end
|
43
|
+
|
44
|
+
user = User.new(secret_recipe: "donna's cookies")
|
45
|
+
user.save
|
46
|
+
user.secret_recipe # => "donna's cookies" (automatically decrypted)
|
47
|
+
```
|
48
|
+
|
49
|
+
### Feature System (Modular)
|
50
|
+
```ruby
|
51
|
+
class Customer < Familia::Horreum
|
52
|
+
feature :safe_dump # API-safe serialization
|
53
|
+
feature :expiration # TTL support
|
54
|
+
feature :encrypted_fields # Secure storage
|
55
|
+
|
56
|
+
field :name, :email
|
57
|
+
encrypted_field :api_key
|
58
|
+
default_expiration 24.hours
|
59
|
+
safe_dump_fields :name, :email
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
### Connection Pooling (Performance)
|
64
|
+
```ruby
|
65
|
+
# Configure connection provider for multi-database pooling
|
66
|
+
Familia.connection_provider = lambda do |uri|
|
67
|
+
parsed = URI.parse(uri)
|
68
|
+
pool_key = "#{parsed.host}:#{parsed.port}/#{parsed.db || 0}"
|
69
|
+
|
70
|
+
@pools[pool_key] ||= ConnectionPool.new(size: 10) do
|
71
|
+
Redis.new(host: parsed.host, port: parsed.port, db: parsed.db || 0)
|
72
|
+
end
|
73
|
+
|
74
|
+
@pools[pool_key].with { |conn| conn }
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
### Object Relationships (RelatableObjects)
|
79
|
+
```ruby
|
80
|
+
class Customer < Familia::Horreum
|
81
|
+
feature :relatable_object
|
82
|
+
self.logical_database = 0
|
83
|
+
field :name, :email
|
84
|
+
end
|
85
|
+
|
86
|
+
class Domain < Familia::Horreum
|
87
|
+
feature :relatable_object
|
88
|
+
self.logical_database = 0
|
89
|
+
field :name, :dns_zone
|
90
|
+
end
|
91
|
+
|
92
|
+
# Create objects with automatic ID generation
|
93
|
+
customer = Customer.new(name: "Acme Corp")
|
94
|
+
domain = Domain.new(name: "acme.com")
|
95
|
+
|
96
|
+
# Establish ownership
|
97
|
+
Customer.owners.set(domain.objid, customer.objid)
|
98
|
+
domain.owner?(customer) # => true
|
99
|
+
```
|
100
|
+
|
101
|
+
|
102
|
+
## Related Resources
|
103
|
+
|
104
|
+
- [Familia README](https://github.com/delano/familia) - Main project documentation
|
105
|
+
- [Issue #57](https://github.com/delano/familia/issues/57) - Original feature proposal
|
106
|
+
- [Issue #58](https://github.com/delano/familia/issues/58) - Wiki documentation tracking
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# Implementation Guide
|
2
|
+
|
3
|
+
## Architecture Overview
|
4
|
+
|
5
|
+
The encrypted fields feature uses a modular provider system with field transformation hooks:
|
6
|
+
|
7
|
+
```
|
8
|
+
User Input → Field Setter → Provider Selection → Encryption → Redis/Valkey
|
9
|
+
Redis/Valkey → Algorithm Detection → Decryption → Field Getter → User Output
|
10
|
+
```
|
11
|
+
|
12
|
+
### Provider Architecture
|
13
|
+
|
14
|
+
```
|
15
|
+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
16
|
+
│ Manager │ │ Registry │ │ Providers │
|
17
|
+
│ │ │ │ │ │
|
18
|
+
│ - encrypt() │───→│ - get() │───→│ XChaCha20Poly │
|
19
|
+
│ - decrypt() │ │ - register() │ │ AES-GCM │
|
20
|
+
│ - derive_key() │ │ - priority │ │ (Future: More) │
|
21
|
+
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
22
|
+
```
|
23
|
+
|
24
|
+
## Core Components
|
25
|
+
|
26
|
+
### 1. Registry System
|
27
|
+
|
28
|
+
The Registry manages available encryption providers and selects the best one:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
module Familia::Encryption::Registry
|
32
|
+
# Auto-register available providers by priority
|
33
|
+
def self.setup!
|
34
|
+
|
35
|
+
# Get provider instance by algorithm
|
36
|
+
def self.get(algorithm)
|
37
|
+
|
38
|
+
# Get highest-priority available provider
|
39
|
+
def self.default_provider
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
### 2. Manager Class
|
44
|
+
|
45
|
+
The Manager handles encryption/decryption operations with provider delegation:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
class Familia::Encryption::Manager
|
49
|
+
# Use specific algorithm or auto-select best
|
50
|
+
def initialize(algorithm: nil)
|
51
|
+
|
52
|
+
# Encrypt with context-specific key derivation
|
53
|
+
def encrypt(plaintext, context:, additional_data: nil)
|
54
|
+
|
55
|
+
# Decrypt with automatic algorithm detection
|
56
|
+
def decrypt(encrypted_json, context:, additional_data: nil)
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
### 3. Provider Interface
|
61
|
+
|
62
|
+
All providers implement a common interface:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
class Provider
|
66
|
+
ALGORITHM = 'algorithm-name'
|
67
|
+
|
68
|
+
def self.available? # Check if dependencies are met
|
69
|
+
def self.priority # Higher = preferred (XChaCha20: 100, AES: 50)
|
70
|
+
|
71
|
+
def encrypt(plaintext, key, additional_data)
|
72
|
+
def decrypt(ciphertext, key, nonce, auth_tag, additional_data)
|
73
|
+
def derive_key(master_key, context)
|
74
|
+
def generate_nonce
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
78
|
+
### 4. Key Derivation
|
79
|
+
|
80
|
+
Each field gets a unique encryption key using provider-specific methods:
|
81
|
+
|
82
|
+
```
|
83
|
+
Master Key + Field Context → Provider KDF → Field-Specific Key
|
84
|
+
|
85
|
+
XChaCha20-Poly1305: BLAKE2b with personalization
|
86
|
+
AES-256-GCM: HKDF-SHA256
|
87
|
+
```
|
88
|
+
|
89
|
+
## Implementation Steps
|
90
|
+
|
91
|
+
### Step 1: Enable Encryption
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
class MyModel < Familia::Horreum
|
95
|
+
# Add the feature (optional if globally enabled)
|
96
|
+
feature :encryption
|
97
|
+
|
98
|
+
# Define encrypted fields
|
99
|
+
encrypted_field :sensitive_data
|
100
|
+
encrypted_field :api_key
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
### Step 2: Configure Keys
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
# config/initializers/familia.rb
|
108
|
+
Familia.configure do |config|
|
109
|
+
config.encryption_keys = {
|
110
|
+
v1: ENV['FAMILIA_ENCRYPTION_KEY_V1']
|
111
|
+
}
|
112
|
+
config.current_key_version = :v1
|
113
|
+
end
|
114
|
+
|
115
|
+
# Validate configuration at startup
|
116
|
+
Familia::Encryption.validate_configuration!
|
117
|
+
```
|
118
|
+
|
119
|
+
### Step 3: Generate Keys
|
120
|
+
|
121
|
+
```bash
|
122
|
+
# Generate a secure 256-bit key (32 bytes)
|
123
|
+
$ openssl rand -base64 32
|
124
|
+
# => base64_encoded_key_here
|
125
|
+
|
126
|
+
# Add to environment
|
127
|
+
$ echo "FAMILIA_ENCRYPTION_KEY_V1=base64_encoded_key_here" >> .env
|
128
|
+
```
|
129
|
+
|
130
|
+
### Step 4: Install Optional Dependencies
|
131
|
+
|
132
|
+
For best security and performance, install RbNaCl:
|
133
|
+
|
134
|
+
```bash
|
135
|
+
# Add to Gemfile
|
136
|
+
gem 'rbnacl', '~> 7.1', '>= 7.1.1'
|
137
|
+
|
138
|
+
# Install
|
139
|
+
$ bundle install
|
140
|
+
```
|
141
|
+
|
142
|
+
Without RbNaCl, Familia falls back to OpenSSL AES-256-GCM (still secure but lower priority).
|
143
|
+
|
144
|
+
## Advanced Usage
|
145
|
+
|
146
|
+
### Custom Field Names
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
encrypted_field :favorite_snack, as: :top_secret_snack_preference
|
150
|
+
```
|
151
|
+
|
152
|
+
### Passphrase Protection
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
class Vault < Familia::Horreum
|
156
|
+
encrypted_field :secret
|
157
|
+
|
158
|
+
def unlock(passphrase)
|
159
|
+
# Passphrase becomes part of encryption context
|
160
|
+
self.secret(passphrase_value: passphrase)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
```
|
164
|
+
|
165
|
+
### Batch Operations
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
# Efficient bulk encryption
|
169
|
+
customers = Customer.batch_create([
|
170
|
+
{ email: 'user1@example.com', favorite_snack: 'chocolate chip cookies' },
|
171
|
+
{ email: 'user2@example.com', favorite_snack: 'leftover pizza' }
|
172
|
+
])
|
173
|
+
```
|
174
|
+
|
175
|
+
## Provider-Specific Features
|
176
|
+
|
177
|
+
### XChaCha20-Poly1305 Provider (Recommended)
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
# Enable with RbNaCl gem
|
181
|
+
gem 'rbnacl', '~> 7.1'
|
182
|
+
|
183
|
+
# Benefits:
|
184
|
+
# - Extended nonce (192 bits vs 96 bits)
|
185
|
+
# - Better resistance to nonce reuse
|
186
|
+
# - BLAKE2b key derivation with personalization
|
187
|
+
# - Priority: 100 (highest)
|
188
|
+
```
|
189
|
+
|
190
|
+
### AES-256-GCM Provider (Fallback)
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
# Always available with OpenSSL
|
194
|
+
# - 256-bit keys, 96-bit nonces
|
195
|
+
# - HKDF-SHA256 key derivation
|
196
|
+
# - Priority: 50
|
197
|
+
# - Good compatibility, proven security
|
198
|
+
```
|
199
|
+
|
200
|
+
## Performance Optimization
|
201
|
+
|
202
|
+
### Provider Benchmarking
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
# Compare provider performance
|
206
|
+
results = Familia::Encryption.benchmark(iterations: 1000)
|
207
|
+
puts results
|
208
|
+
# => {
|
209
|
+
# "xchacha20poly1305" => { time: 0.45, ops_per_sec: 4444, priority: 100 },
|
210
|
+
# "aes-256-gcm" => { time: 0.52, ops_per_sec: 3846, priority: 50 }
|
211
|
+
# }
|
212
|
+
```
|
213
|
+
|
214
|
+
### Key Derivation Monitoring
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
# Monitor key derivations (should increment with each operation)
|
218
|
+
puts Familia::Encryption.derivation_count.value
|
219
|
+
# => 42
|
220
|
+
|
221
|
+
# Reset counter for testing
|
222
|
+
Familia::Encryption.reset_derivation_count!
|
223
|
+
```
|
224
|
+
|
225
|
+
### Memory Management
|
226
|
+
|
227
|
+
**⚠️ Important**: Ruby provides no memory safety guarantees. See security warnings in provider files.
|
228
|
+
|
229
|
+
- Keys are cleared from variables after use (best effort)
|
230
|
+
- No protection against memory dumps or GC copying
|
231
|
+
- Plaintext exists in Ruby strings during processing
|
232
|
+
|
233
|
+
## Testing
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
# Test helper
|
237
|
+
RSpec.configure do |config|
|
238
|
+
config.include Familia::EncryptionTestHelpers
|
239
|
+
|
240
|
+
config.around(:each, :encryption) do |example|
|
241
|
+
with_test_encryption_keys { example.run }
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# In tests
|
246
|
+
it "encrypts sensitive fields", :encryption do
|
247
|
+
user = User.create(favorite_snack: "leftover pizza")
|
248
|
+
|
249
|
+
# Verify encryption in Redis
|
250
|
+
raw_value = redis.hget(user.rediskey, "favorite_snack")
|
251
|
+
expect(raw_value).not_to include("leftover pizza")
|
252
|
+
expect(JSON.parse(raw_value)).to have_key("ciphertext")
|
253
|
+
end
|
254
|
+
```
|
255
|
+
|
256
|
+
## Troubleshooting
|
257
|
+
|
258
|
+
### Common Issues
|
259
|
+
|
260
|
+
1. **"No encryption key configured"**
|
261
|
+
- Ensure `FAMILIA_ENCRYPTION_KEY` is set
|
262
|
+
- Check `Familia.config.encryption_keys`
|
263
|
+
|
264
|
+
2. **"Decryption failed"**
|
265
|
+
- Verify correct key version
|
266
|
+
- Check if data was encrypted with different key
|
267
|
+
|
268
|
+
3. **Performance degradation**
|
269
|
+
- Enable key caching
|
270
|
+
- Consider installing libsodium gem
|
271
|
+
|
272
|
+
## Next Steps
|
273
|
+
|
274
|
+
- [Security Model](Security-Model) - Understand the cryptographic design
|
275
|
+
- [Key Management](Key-Management) - Rotation and best practices
|
276
|
+
- [Migration Guide](Migration-Guide) - Upgrade existing fields
|