Class: Rails::Credentials::Conflict::EncryptionService

Inherits:
Object
  • Object
show all
Defined in:
lib/rails/credentials/conflict/encryption_service.rb,
sig/rails/credentials/conflict/encryption_service.rbs

Overview

Encrypts and decrypts Rails credentials content using AES-128-GCM.

The encryption key is read from either an environment variable (default RAILS_MASTER_KEY) or a key file on disk.

Constant Summary collapse

CIPHER =

Returns:

  • (String)
"aes-128-gcm"

Instance Method Summary collapse

Constructor Details

#initialize(key_path, env_key: "RAILS_MASTER_KEY") ⇒ EncryptionService

Returns a new instance of EncryptionService.

Parameters:

  • key_path (String, Pathname)
  • env_key: (String) (defaults to: "RAILS_MASTER_KEY")


15
16
17
18
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 15

def initialize(key_path, env_key: "RAILS_MASTER_KEY")
  @key_path = key_path
  @env_key = env_key
end

Instance Method Details

#decrypt(encrypted_content) ⇒ String

Decrypts and verifies encrypted_content. Returns an empty string for nil or empty input.

Parameters:

  • encrypted_content (String, nil)

Returns:

  • (String)


22
23
24
25
26
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 22

def decrypt(encrypted_content)
  return "" if encrypted_content.nil? || encrypted_content.empty?

  encryptor.decrypt_and_verify(encrypted_content)
end

#encrypt(content) ⇒ String

Encrypts and signs content, returning the ciphertext.

Parameters:

  • content (String)

Returns:

  • (String)


29
30
31
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 29

def encrypt(content)
  encryptor.encrypt_and_sign(content)
end

#encryptorActiveSupport::MessageEncryptor

Returns:

  • (ActiveSupport::MessageEncryptor)


40
41
42
43
44
45
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 40

def encryptor
  @encryptor ||= ActiveSupport::MessageEncryptor.new(
    [read_key].pack("H*"),
    cipher: CIPHER
  )
end

#key_from_envString?

Returns:

  • (String, nil)


53
54
55
56
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 53

def key_from_env
  value = ENV[@env_key]&.strip
  value unless value.nil? || value.empty?
end

#key_from_fileString?

Returns:

  • (String, nil)


58
59
60
61
62
63
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 58

def key_from_file
  return nil unless File.exist?(@key_path)

  value = File.read(@key_path).strip
  value.empty? ? nil : value
end

#read_keyString

Returns:

  • (String)


47
48
49
50
51
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 47

def read_key
  key_from_env || key_from_file || raise(
    Error, "Encryption key not found. Set #{@env_key} env variable or create #{@key_path}"
  )
end

#save_encrypted(content, destination_path) ⇒ Integer

Encrypts content and writes it to destination_path in binary mode.

Parameters:

  • content (String)
  • destination_path (String, Pathname)

Returns:

  • (Integer)


34
35
36
# File 'lib/rails/credentials/conflict/encryption_service.rb', line 34

def save_encrypted(content, destination_path)
  File.binwrite(destination_path, encrypt(content))
end