File: active_support/message_encryptor.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: ActiveSupport#3
  class: MessageEncryptor#11
inherits from
  Object ( Builtin-Module )
has properties
constant: OpenSSLCipherError #13
method: initialize / 2 #15
method: encrypt / 1 #20
method: decrypt / 1 #35
method: encrypt_and_sign / 1 #51
method: decrypt_and_verify / 1 #55
method: new_cipher #62
method: verifier #66
  class: InvalidMessage#12
inherits from
  StandardError ( Builtin-Module )

Code

   1  require 'openssl'
   2 
   3  module ActiveSupport
   4    # MessageEncryptor is a simple way to encrypt values which get stored somewhere 
   5    # you don't trust.
   6    # 
   7    # The cipher text and initialization vector are base64 encoded and returned to you.
   8    #
   9    # This can be used in situations similar to the MessageVerifier, but where you don't
  10    # want users to be able to determine the value of the payload.
  11    class MessageEncryptor
  12      class InvalidMessage < StandardError; end
  13      OpenSSLCipherError = OpenSSL::Cipher.const_defined?(:CipherError) ? OpenSSL::Cipher::CipherError : OpenSSL::CipherError
  14 
  15      def initialize(secret, cipher = 'aes-256-cbc')
  16        @secret = secret
  17        @cipher = cipher
  18      end
  19      
  20      def encrypt(value)
  21        cipher = new_cipher
  22        # Rely on OpenSSL for the initialization vector
  23        iv = cipher.random_iv
  24        
  25        cipher.encrypt 
  26        cipher.key = @secret
  27        cipher.iv  = iv
  28        
  29        encrypted_data = cipher.update(Marshal.dump(value)) 
  30        encrypted_data << cipher.final
  31 
  32        [encrypted_data, iv].map {|v| ActiveSupport::Base64.encode64s(v)}.join("--")
  33      end
  34      
  35      def decrypt(encrypted_message)
  36        cipher = new_cipher
  37        encrypted_data, iv = encrypted_message.split("--").map {|v| ActiveSupport::Base64.decode64(v)}
  38        
  39        cipher.decrypt
  40        cipher.key = @secret
  41        cipher.iv  = iv
  42 
  43        decrypted_data = cipher.update(encrypted_data)
  44        decrypted_data << cipher.final
  45        
  46        Marshal.load(decrypted_data)
  47      rescue OpenSSLCipherError, TypeError
  48        raise InvalidMessage
  49      end
  50      
  51      def encrypt_and_sign(value)
  52        verifier.generate(encrypt(value))
  53      end
  54      
  55      def decrypt_and_verify(value)
  56        decrypt(verifier.verify(value))
  57      end
  58      
  59      
  60      
  61      private 
  62        def new_cipher
  63          OpenSSL::Cipher::Cipher.new(@cipher)
  64        end
  65        
  66        def verifier
  67          MessageVerifier.new(@secret)
  68        end
  69    end
  70  end