Michael de Silva's Blog

Software Engineer. Rubyist and Roboticist.

Michael de Silva's Blog

Software Engineer. Rubyist and Roboticist.

Nygma - Signing and encrypting data with tools built-in to Rails 4

Having stumbled on Signing and encrypting data with tools built-in to Rails I was quite pleased to see this approach use the same tools that Rails uses for encrypting the user session (cookie).

This lead me to building Nygma to allow encrypting tokens received from Stripe. Since this was built rather quickly, I haven't been able to document its API as I normally do, but I will be cleaning this up in due course.

For those curious engineers amongst us, Rails' encrypted cookie implementation looks like

    class EncryptedCookieJar #:nodoc:
      include ChainedCookieJars

      def initialize(parent_jar, key_generator, options = {})
        if ActiveSupport::LegacyKeyGenerator === key_generator
          raise "You didn't set config.secret_key_base, which is required for this cookie jar. " +
            "Read the upgrade documentation to learn more about this new config option."
        end

        @parent_jar = parent_jar
        @options = options
        secret = key_generator.generate_key(@options[:encrypted_cookie_salt])
        sign_secret = key_generator.generate_key(@options[:encrypted_signed_cookie_salt])
        @encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)
      end

      def [](name)
        if encrypted_message = @parent_jar[name]
          decrypt_and_verify(encrypted_message)
        end
      end

      def []=(name, options)
        if options.is_a?(Hash)
          options.symbolize_keys!
        else
          options = { :value => options }
        end
        options[:value] = @encryptor.encrypt_and_sign(options[:value])

        raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE
        @parent_jar[name] = options
      end

      private
        def decrypt_and_verify(encrypted_message)
          @encryptor.decrypt_and_verify(encrypted_message)
        rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage
          nil
        end
    end
comments powered by Disqus