Rails Encryption and Decryption Algorithm

I would like to encrypt and decrypt a single value of the model attribute string using AES .

I'm interested in Rails , what is the easiest way to get it? Is there an AES gem library that can be used directly? And how to use it?

Basically, I need to be guided by how to apply AES encryption / decryption in a Rails application.

------- update -------

I just noticed that there is an AES gem . If I add this stone to my GemFile, how can I use it in my application for encryption and decryption?

+8
ruby-on-rails ruby-on-rails-3
source share
5 answers

AFAIK, aes stone wraps the Ruby openssl standard library to provide a much more simplified interface. It only supports aes-256-cbc , which is a 256-bit AES with an encryption chain. You would probably add encryption / decryption methods to your models in Rails.

The basic procedure for encryption:

  • compute AES symmetric encryption key, 256 bits
  • it is not necessary to compute the initialization vector for use with aes-256-cbc (the aes stone can actually do this for you, so you can skip this step)
  • encrypt your message, optionally indicating the output :format (Base64 by default, otherwise simple Ruby string strings) and / or initialization vector :iv

This will:

 key = AES.key => "6476b3f5ec6dcaddb637e9c9654aa687" # key ends up as a 32-char long hex string iv = AES.iv(:base_64) => "PPDRCMsZhumCdEO1Zm05uw==" enc64 = AES.encrypt("hello, secret world", key, {:iv => iv}) => "PPDRCMsZhumCdEO1Zm05uw==$b3CCy/1dAMJ2JG5T50igEMGtvo9Ppkla1c9vrKbo+zQ=" # note that the encrypted result is the :iv # and Base64-transformed encrypted message # concatenated with $ 

Then you decrypted enc64 , passing in the whole :iv + $ + encrypted message line, as well as the 256-bit AES key .

 AES.decrypt(enc64, key) => "hello, secret world" 

Having some experience using the standard openssl library in Ruby, I can tell you that the English documentation is sparse, while the Japanese documentation is very good. Anyway, using the openssl API is confusing at best, so if you don't mind restricting yourself to aes-256-cbc , then this aes stone looks very useful.

Remember, the author has a caution regarding speed. If you find that you need a faster solution, you should take a look at FastAES . FastAES is a C extension and will require a compiler for your target platform.

+7
source share

I suggest making a module in my application and including it where you want to use it, and use the module method as:

Module

 require 'openssl' require 'base64' module Preventurl def self.included(base) base.extend self end def cipher OpenSSL::Cipher::Cipher.new('aes-256-cbc') # ('aes-256-cbc') end def cipher_key 'jabcderfghfhfddd!' end def decrypt(value) c = cipher.decrypt c.key = Digest::SHA256.digest(cipher_key) c.update(Base64.decode64(value.to_s)) + c.final end def encrypt(value) c = cipher.encrypt c.key = Digest::SHA256.digest(cipher_key) Base64.encode64(c.update(value.to_s) + c.final) end end 

in the application controller include MyModule

Now from any controller:

 encrypt("This is a text") ==> "h0RGuW5m3Wk9AAspik9ZXVysOcy2IeQrhQDn85mdo5I=%0A" decrypt("h0RGuW5m3Wk9AAspik9ZXVysOcy2IeQrhQDn85mdo5I=%0A") ==> "This is a text" 
+3
source share

You can use the OpenSSL library. Create the following functions, and then you can use encryption and decryption methods.

 def aes(m,k,t) (aes = OpenSSL::Cipher::Cipher.new('aes-256-cbc').send(m)).key = Digest::SHA256.digest(k) aes.update(t) << aes.final end def encrypt(key, text) aes(:encrypt, key, text) end def decrypt(key, text) aes(:decrypt, key, text) end 
+2
source share

https://github.com/shuber/attr_encrypted

http://ezcrypto.rubyforge.org/

attr_encrypted works well for me - although I also used Ezcrypto. It acts as a wrapper around the OpenSSL library.

+2
source share

I came across the same problem and created a simple model for this model (rails 5):

 require 'openssl' require 'base64' module EncryptableModelConcern extend ActiveSupport::Concern included do before_save :encrypt_encryptable_attributes after_save :decrypt_encryptable_attributes after_find :decrypt_encryptable_attributes end module ClassMethods # Sets the model `@encryptable_attributes` class instance variable. # Encryptable attributes are encrypted before saving using `before_save` hook and decrypted using `after_save` and `after_find` hooks. # Example: # ``` # class Board < BaseModel # encryptable_attributes :name, :title, :content # end # ``` def encryptable_attributes(*attrs) @encryptable_attributes = attrs end end # Returns the model `@encryptable_attributes` class instance variable. # def encryptable_attributes self.class.instance_variable_get(:@encryptable_attributes) || [] end # Encryptes the model encryptable attributes before saving using Rails' `before_save` hook. # # **Note: Be careful in calling this method manually as it can corrupt the data.** def encrypt_encryptable_attributes encryptable_attributes.each do |k| self[k] = encrypt(self[k]) end end # Decrypts the model encryptable attributes using Rails' `after_save` and `after_find` hooks. # # **Note: Be careful in calling this method manually as it can corrupt the data.** def decrypt_encryptable_attributes encryptable_attributes.each do |k| self[k] = decrypt(self[k]) end end private def cipher OpenSSL::Cipher::Cipher.new('aes-256-cbc') end def cipher_key Rails.configuration.crypto['key'] # <-- your own key generator here end def encrypt(value) c = cipher.encrypt c.key = Digest::SHA256.digest(cipher_key) c.iv = iv = c.random_iv Base64.encode64(iv) + Base64.encode64(c.update(value.to_s) + c.final) end def decrypt(value) c = cipher.decrypt c.key = Digest::SHA256.digest(cipher_key) c.iv = Base64.decode64 value.slice!(0,25) c.update(Base64.decode64(value.to_s)) + c.final end end 

Include it in your model that you want to have encrypted attributes

 class Post < ApplicationRecord include EncryptableModelConcern encryptable_attributes :title, :content end 

Now your model attributes will be encrypted on before_save and will be decrypted on after_save and after_find .

+2
source share

All Articles