Class: RailsAi::Security::APIKeyManager

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_ai/security/api_key_manager.rb

Class Method Summary collapse

Class Method Details

.decrypt(encrypted_data, key_name = 'RAILS_AI_SECRET') ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/rails_ai/security/api_key_manager.rb', line 30

def decrypt(encrypted_data, key_name = 'RAILS_AI_SECRET')
  return encrypted_data if encrypted_data.nil? || encrypted_data.empty?
  
  begin
    data = Base64.strict_decode64(encrypted_data)
    iv = data[0, 16]
    encrypted = data[16..-1]
    
    key = derive_key(key_name)
    cipher = OpenSSL::Cipher.new('AES-256-CBC')
    cipher.decrypt
    cipher.key = key
    cipher.iv = iv
    
    cipher.update(encrypted) + cipher.final
  rescue => e
    Rails.logger.error "Decryption failed: #{e.message}" if defined?(Rails) && Rails.logger
    encrypted_data
  end
end

.encrypt(plaintext, key_name = 'RAILS_AI_SECRET') ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rails_ai/security/api_key_manager.rb', line 16

def encrypt(plaintext, key_name = 'RAILS_AI_SECRET')
  return plaintext if plaintext.nil? || plaintext.empty?
  
  key = derive_key(key_name)
  iv = SecureRandom.random_bytes(16)
  cipher = OpenSSL::Cipher.new('AES-256-CBC')
  cipher.encrypt
  cipher.key = key
  cipher.iv = iv
  
  encrypted = cipher.update(plaintext) + cipher.final
  Base64.strict_encode64(iv + encrypted)
end

.generate_secure_key(length = 32) ⇒ Object



51
52
53
# File 'lib/rails_ai/security/api_key_manager.rb', line 51

def generate_secure_key(length = 32)
  SecureRandom.hex(length)
end

.hash_key(key) ⇒ Object



55
56
57
58
# File 'lib/rails_ai/security/api_key_manager.rb', line 55

def hash_key(key)
  return nil if key.nil? || key.empty?
  Digest::SHA256.hexdigest(key)
end

.rotate_key(old_key, new_key) ⇒ Object



67
68
69
70
71
72
# File 'lib/rails_ai/security/api_key_manager.rb', line 67

def rotate_key(old_key, new_key)
  # Implementation for key rotation
  # This would typically involve re-encrypting all data with the new key
  Rails.logger.info "Key rotation requested" if defined?(Rails) && Rails.logger
  true
end

.secure_fetch(key_name) ⇒ Object



10
11
12
13
14
# File 'lib/rails_ai/security/api_key_manager.rb', line 10

def secure_fetch(key_name)
  key = ENV[key_name]
  raise "Missing required environment variable: #{key_name}" if key.nil? || key.empty?
  key
end

.secure_retrieve(key) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rails_ai/security/api_key_manager.rb', line 90

def secure_retrieve(key)
  # Retrieve and decrypt stored value
  return nil unless defined?(Rails) && Rails.cache
  
  store_data = Rails.cache.read("secure_#{key}")
  return nil if store_data.nil?
  
  # Check TTL if present
  if store_data[:ttl] && (Time.now.to_i - store_data[:created_at]) > store_data[:ttl]
    Rails.cache.delete("secure_#{key}")
    return nil
  end
  
  decrypt(store_data[:encrypted])
end

.secure_store(key, value, ttl = nil) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/rails_ai/security/api_key_manager.rb', line 74

def secure_store(key, value, ttl = nil)
  # Store encrypted value with optional TTL
  encrypted_value = encrypt(value)
  store_data = {
    encrypted: encrypted_value,
    created_at: Time.now.to_i,
    ttl: ttl
  }
  
  if defined?(Rails) && Rails.cache
    Rails.cache.write("secure_#{key}", store_data, expires_in: ttl)
  end
  
  store_data
end

.validate_key_format(key, expected_pattern = nil) ⇒ Object



60
61
62
63
64
65
# File 'lib/rails_ai/security/api_key_manager.rb', line 60

def validate_key_format(key, expected_pattern = nil)
  return false if key.nil? || key.empty?
  return true if expected_pattern.nil?
  
  key.match?(expected_pattern)
end