Class: Familia::Encryption::Providers::SecureXChaCha20Poly1305Provider
- Inherits:
-
Familia::Encryption::Provider
- Object
- Familia::Encryption::Provider
- Familia::Encryption::Providers::SecureXChaCha20Poly1305Provider
- Defined in:
- lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb
Overview
Enhanced XChaCha20Poly1305Provider with improved memory security
While complete avoidance of Ruby strings for secrets is challenging due to RbNaCl's internal implementation, this provider implements several security improvements:
- Minimizes key lifetime in memory
- Uses immediate secure wiping after operations
- Avoids unnecessary key duplication
- Uses locked memory where possible (future enhancement)
Constant Summary collapse
- ALGORITHM =
'xchacha20poly1305-secure'.freeze
- NONCE_SIZE =
24- AUTH_TAG_SIZE =
16
Class Method Summary collapse
Instance Method Summary collapse
- #decrypt(ciphertext, key, nonce, auth_tag, additional_data = nil) ⇒ Object
-
#derive_key(master_key, context, personal: nil) ⇒ Object
Enhanced key derivation with immediate cleanup.
- #encrypt(plaintext, key, additional_data = nil) ⇒ Object
- #generate_nonce ⇒ Object
-
#secure_wipe(key) ⇒ Object
Clear key from memory (still no security guarantees in Ruby).
Constructor Details
This class inherits a constructor from Familia::Encryption::Provider
Class Method Details
.available? ⇒ Boolean
54 55 56 |
# File 'lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb', line 54 def self.available? !!defined?(RbNaCl) && !!defined?(FFI) end |
.priority ⇒ Object
58 59 60 |
# File 'lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb', line 58 def self.priority 110 # Higher than regular XChaCha20Poly1305Provider end |
Instance Method Details
#decrypt(ciphertext, key, nonce, auth_tag, additional_data = nil) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb', line 77 def decrypt(ciphertext, key, nonce, auth_tag, additional_data = nil) validate_key_length!(key) # Minimize key exposure by performing operation immediately begin result = perform_decryption(ciphertext, key, nonce, auth_tag, additional_data) ensure # Attempt to clear the key parameter (if mutable) secure_wipe(key) end result end |
#derive_key(master_key, context, personal: nil) ⇒ Object
Enhanced key derivation with immediate cleanup
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb', line 96 def derive_key(master_key, context, personal: nil) validate_key_length!(master_key) raw_personal = personal || Familia.config.encryption_personalization # Fail closed on a missing personalization rather than crashing with a # NoMethodError on nil (#311), mirroring XChaCha20Poly1305Provider. unless raw_personal.is_a?(String) && !raw_personal.empty? raise EncryptionError, 'encryption_personalization must be a non-empty string for key derivation' end raise EncryptionError, 'Personalization string must not contain null bytes' if raw_personal.include?("\0") personal_string = raw_personal.ljust(16, "\0") # Perform derivation and immediately clear intermediate values derived_key = RbNaCl::Hash.blake2b( context.force_encoding('BINARY'), key: master_key, digest_size: 32, personal: personal_string ) # Clear personalization string from memory personal_string.clear # Return derived key (caller responsible for secure cleanup) derived_key end |
#encrypt(plaintext, key, additional_data = nil) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb', line 62 def encrypt(plaintext, key, additional_data = nil) validate_key_length!(key) # Generate nonce first to avoid holding onto key longer than necessary nonce = generate_nonce # Minimize key exposure by performing operation immediately result = perform_encryption(plaintext, key, nonce, additional_data) # Attempt to clear the key parameter (if mutable) secure_wipe(key) result end |
#generate_nonce ⇒ Object
91 92 93 |
# File 'lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb', line 91 def generate_nonce RbNaCl::Random.random_bytes(NONCE_SIZE) end |
#secure_wipe(key) ⇒ Object
Clear key from memory (still no security guarantees in Ruby)
125 126 127 |
# File 'lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb', line 125 def secure_wipe(key) key&.clear end |