zilverline/sequent

Feature request: Two way encryption with Active Record Encryption

Closed this issue · 9 comments

We are migrating our application to use Sequent and currently encrypt quite a lot of data using Active Record Encryption. I noticed in the documentation that Sequent supports encryption but that's only one way encryption.

We would love to use Active Record Encryption in our app. Does anyone else have this use case?

lvonk commented

Interesting. We don't have this use case (yet), but would be nice to have and use. I don't have experience with Active Record encryption but having read through the docs this should be a way to test if this is possible (if you haven't already done so):

  1. MyCommand.new(sensitive_content: EncryptUsingWhatEverActiveRecordIsUsing.call('foobar')) where sensitive_content is 'just' a String. Also the Event containing this sensitive content should be of type String.

  2. Then I think we need to use the ActiveRecord::Encryption.without_encryption context in a Projector (since the data here is already encrypted):

class MyProjector
  on MyEventWithEncryption do
    ActiveRecord::Encryption.without_encryption do
       ...
    end
  end

If this works than we can start proper support by letting the Command do the encrypting using a special type or so and make the Sequent projector smarter so whenever it sees that type it will execute in the correct context.

Thanks for the quick response. @bforma had the same idea.

I'm not sure yet if you can use the encryption easily without ActiveRecord, but I'll will ook into this! I'll report back when I have some more info.

lvonk commented

It looks like you can use the config.active_record.encryption.encryptor for encrypting the payload in the Command. If that works then I expect querying the data should decrypt out of the box.... Curious to see if this will work.

I browsed the Rails source code and came up with this working code:

salt =  SecureRandom.random_bytes(32)

encryptor = ActiveRecord::Encryption::Cipher::Aes256Gcm.new(salt, deterministic: true)
encrypted_text = encryptor.encrypt("Hello Sequent")
stored_in_database = ActiveRecord::Encryption::MessageSerializer.new.dump(encrypted_text)
puts stored_in_database # => {"p":"KJNhOuD7uzSvCWA=","h":{"iv":"kB2LUXoHLcjiLRua","at":"PtW+F6WekN4I0MwP442f6g=="}}

message = ActiveRecord::Encryption::MessageSerializer.new.load(stored_in_database)
puts encryptor.decrypt(message) # => "Hello Sequent"

It looks like you can use the config.active_record.encryption.encryptor for encrypting the payload in the Command. If that works then I expect querying the data should decrypt out of the box.... Curious to see if this will work.

This returns nil, in our app.

>> Stekker::Application.config.active_record.encryption.encryptor
=> nil
lvonk commented

Hmm I'd expected some of the attributes of config.active_record.encryption to be set... They all seem nil.

lvonk commented

Any update on this @jankeesvw ?

No, sorry, we haven't touched this idea in the last couple of weeks.

lvonk commented

Closing due to inactivity. When needed we can re-open.