Module: SymmetricEncryption
- Defined in:
- lib/symmetric_encryption/railtie.rb,
lib/symmetric_encryption.rb,
lib/symmetric_encryption/cipher.rb,
lib/symmetric_encryption/reader.rb,
lib/symmetric_encryption/writer.rb,
lib/symmetric_encryption/version.rb,
lib/symmetric_encryption/symmetric_encryption.rb,
lib/rails/generators/symmetric_encryption/config/config_generator.rb,
lib/rails/generators/symmetric_encryption/new_keys/new_keys_generator.rb
Overview
Encrypt using 256 Bit AES CBC symmetric key and initialization vector The symmetric key is protected using the private key below and must be distributed separately from the application
Defined Under Namespace
Modules: Generators Classes: Cipher, Railtie, Reader, Writer
Constant Summary collapse
- VERSION =
"0.9.1"
- MAGIC_HEADER =
'@EnC'
- MAGIC_HEADER_SIZE =
MAGIC_HEADER.size
- MAGIC_HEADER_UNPACK =
"a#{MAGIC_HEADER_SIZE}v"
- @@cipher =
Defaults
nil
- @@secondary_ciphers =
[]
Class Method Summary collapse
-
.cipher(version = 0) ⇒ Object
Returns the Primary Symmetric Cipher being used If a version is supplied, then the cipher matching that version will be returned or nil if no match was found.
-
.cipher=(cipher) ⇒ Object
Set the Primary Symmetric Cipher to be used.
-
.decrypt(str) ⇒ Object
AES Symmetric Decryption of supplied string Returns decrypted string Returns nil if the supplied str is nil Returns “” if it is a string and it is empty.
-
.encrypt(str) ⇒ Object
AES Symmetric Encryption of supplied string Returns result as a Base64 encoded string Returns nil if the supplied str is nil Returns “” if it is a string and it is empty.
-
.encrypted?(encrypted_data) ⇒ Boolean
Returns [true|false] as to whether the data could be decrypted Parameters: encrypted_data: Encrypted string.
-
.generate_symmetric_key_files(filename = nil, environment = nil) ⇒ Object
Generate new random symmetric keys for use with this Encryption library.
-
.load!(filename = nil, environment = nil) ⇒ Object
Load the Encryption Configuration from a YAML file filename: Name of file to read.
-
.random_password ⇒ Object
Generate a 22 character random password.
-
.secondary_ciphers ⇒ Object
Returns the Primary Symmetric Cipher being used.
-
.secondary_ciphers=(secondary_ciphers) ⇒ Object
Set the Secondary Symmetric Ciphers Array to be used.
-
.try_decrypt(str) ⇒ Object
Invokes decrypt Returns decrypted String Return nil if it fails to decrypt a String.
Class Method Details
.cipher(version = 0) ⇒ Object
Returns the Primary Symmetric Cipher being used If a version is supplied, then the cipher matching that version will be returned or nil if no match was found
32 33 34 35 36 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 32 def self.cipher(version = 0) raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher return @@cipher if version.nil? || (version == 0) || (@@cipher.version == version) secondary_ciphers.find {|c| c.version == version} end |
.cipher=(cipher) ⇒ Object
Set the Primary Symmetric Cipher to be used
Example: For testing purposes the following test cipher can be used:
SymmetricEncryption.cipher = SymmetricEncryption::Cipher.new(
:key => '1234567890ABCDEF1234567890ABCDEF',
:iv => '1234567890ABCDEF',
:cipher => 'aes-128-cbc'
)
24 25 26 27 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 24 def self.cipher=(cipher) raise "Cipher must be similar to SymmetricEncryption::Ciphers" unless cipher.respond_to?(:encrypt) && cipher.respond_to?(:decrypt) @@cipher = cipher end |
.decrypt(str) ⇒ Object
AES Symmetric Decryption of supplied string
Returns decrypted string
Returns nil if the supplied str is nil
Returns "" if it is a string and it is empty
Note: If secondary ciphers are supplied in the configuration file the
first key will be used to decrypt 'str'. If it fails each cipher in the
order supplied will be tried.
It is slow to try each cipher in turn, so should be used during migrations
only
Raises: OpenSSL::Cipher::CipherError when ‘str’ was not encrypted using the supplied key and iv
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 66 def self.decrypt(str) raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher # Decode data first based on encoding setting case @@cipher.encoding when :base64, :base64strict str = ::Base64.decode64(str) if str end begin @@cipher.decrypt(str) rescue OpenSSL::Cipher::CipherError => exc @@secondary_ciphers.each do |cipher| begin return cipher.decrypt(str) rescue OpenSSL::Cipher::CipherError end end raise exc end end |
.encrypt(str) ⇒ Object
AES Symmetric Encryption of supplied string
Returns result as a Base64 encoded string
Returns nil if the supplied str is nil
Returns "" if it is a string and it is empty
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 92 def self.encrypt(str) raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher # Encrypt data as a binary string if result = @@cipher.encrypt(str) # Now encode data based on encoding setting case @@cipher.encoding when :base64 # Base 64 Encoding of binary data ::Base64.encode64(result) when :base64strict ::Base64.encode64(result).gsub(/\n/, '') else result end end end |
.encrypted?(encrypted_data) ⇒ Boolean
Returns [true|false] as to whether the data could be decrypted
Parameters:
encrypted_data: Encrypted string
130 131 132 133 134 135 136 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 130 def self.encrypted?(encrypted_data) raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher # For now have to decrypt it fully result = try_decrypt(encrypted_data) !(result.nil? || result == '') end |
.generate_symmetric_key_files(filename = nil, environment = nil) ⇒ Object
Generate new random symmetric keys for use with this Encryption library
Note: Only the current Encryption key settings are used
Creates Symmetric Key .key
and initilization vector .iv
which is encrypted with the above Public key
Existing key files will be renamed if present
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 172 def self.generate_symmetric_key_files(filename=nil, environment=nil) config = read_config(filename, environment) cipher_cfg = config[:ciphers].first key_filename = cipher_cfg[:key_filename] iv_filename = cipher_cfg[:iv_filename] cipher = cipher_cfg[:cipher] raise "The configuration file must contain a 'private_rsa_key' parameter to generate symmetric keys" unless config[:private_rsa_key] rsa_key = OpenSSL::PKey::RSA.new(config[:private_rsa_key]) # Generate a new Symmetric Key pair key_pair = SymmetricEncryption::Cipher.random_key_pair(cipher || 'aes-256-cbc', !iv_filename.nil?) # Save symmetric key after encrypting it with the private RSA key, backing up existing files if present File.rename(key_filename, "#{key_filename}.#{Time.now.to_i}") if File.exist?(key_filename) File.open(key_filename, 'wb') {|file| file.write( rsa_key.public_encrypt(key_pair[:key]) ) } if iv_filename File.rename(iv_filename, "#{iv_filename}.#{Time.now.to_i}") if File.exist?(iv_filename) File.open(iv_filename, 'wb') {|file| file.write( rsa_key.public_encrypt(key_pair[:iv]) ) } end puts("Generated new Symmetric Key for encryption. Please copy #{key_filename} and #{iv_filename} to the other web servers in #{environment}.") end |
.load!(filename = nil, environment = nil) ⇒ Object
Load the Encryption Configuration from a YAML file
filename:
Name of file to read.
Mandatory for non-Rails apps
Default: Rails.root/config/symmetric-encryption.yml
environment:
Which environments config to load. Usually: production, development, etc.
Default: Rails.env
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 146 def self.load!(filename=nil, environment=nil) config = read_config(filename, environment) # Check for hard coded key, iv and cipher if config[:key] @@cipher = Cipher.new(config) @@secondary_ciphers = [] else private_rsa_key = config[:private_rsa_key] @@cipher, *@@secondary_ciphers = config[:ciphers].collect do |cipher_conf| cipher_from_encrypted_files(private_rsa_key, cipher_conf) end end true end |
.random_password ⇒ Object
Generate a 22 character random password
197 198 199 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 197 def self.random_password Base64.encode64(OpenSSL::Cipher.new('aes-128-cbc').random_key)[0..-4] end |
.secondary_ciphers ⇒ Object
Returns the Primary Symmetric Cipher being used
48 49 50 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 48 def self.secondary_ciphers @@secondary_ciphers end |
.secondary_ciphers=(secondary_ciphers) ⇒ Object
Set the Secondary Symmetric Ciphers Array to be used
39 40 41 42 43 44 45 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 39 def self.secondary_ciphers=(secondary_ciphers) raise "secondary_ciphers must be a collection" unless secondary_ciphers.respond_to? :each secondary_ciphers.each do |cipher| raise "secondary_ciphers can only consist of SymmetricEncryption::Ciphers" unless cipher.respond_to?(:encrypt) && cipher.respond_to?(:decrypt) end @@secondary_ciphers = secondary_ciphers end |
.try_decrypt(str) ⇒ Object
Invokes decrypt
Returns decrypted String
Return nil if it fails to decrypt a String
Useful for example when decoding passwords encrypted using a key from a different environment. I.e. We cannot decode production passwords in the test or development environments but still need to be able to load YAML config files that contain encrypted development and production passwords
118 119 120 121 122 123 124 125 |
# File 'lib/symmetric_encryption/symmetric_encryption.rb', line 118 def self.try_decrypt(str) raise "Call SymmetricEncryption.load! or SymmetricEncryption.cipher= prior to encrypting or decrypting data" unless @@cipher begin decrypt(str) rescue OpenSSL::Cipher::CipherError nil end end |