AR7 deterministic encryption & custom key Provider

I would like to use deterministic and non-deterministic encryption of attributes with ActiveRecord 7.1.3.2.

This works when using the default key provider and generated :primary_key, :deterministic_key and :derivation_salt in config/credentials.yml, but it does not work, if I need to use a custom key provider. I want to implement a multi-tenancy approach and use a very rough custom key provider like that:

  class KeyProviders::TenantKeyProvider
    def initialize
      @keys = load_keys
    end
  
    def encryption_key
      tenant_id = Current.tenant
      @tenant_keys[tenant_id]
    end

    def decryption_keys(message)
      tenant_id = Current.tenant
      [@tenant_keys[tenant_id]]
    end

    private
  
    def load_keys
      key_secret1 = Rails.application.key_generator.generate_key('tenant1 key', 32)
      key_secret2 = Rails.application.key_generator.generate_key('tenant2 key', 32)
      key_secret3 = Rails.application.key_generator.generate_key('tenant3 key', 32)

      encryption_key1 = ActiveRecord::Encryption::Key.new(key_secret1)
      encryption_key2 = ActiveRecord::Encryption::Key.new(key_secret2)
      encryption_key3 = ActiveRecord::Encryption::Key.new(key_secret3)
      {
        'tenant1' => encryption_key1,
        'tenant2' => encryption_key2,
        'tenant3' => encryption_key3
      }
    end
  end

Result is, that non-deterministic encryption works properly and uses the proper per-tenant key, but deterministic encryption on a per-tenant basis does not work.

I can make deterministic encryption work, if I re-introduce the default key providers credentials, but I would like to get deterministic encryption to work with tenant-specific keys instead.

I don’t see a reason, why the ActiveRecord::Encryption::Key objects should be any different for deterministic and non-deterministic encryption, but I guess there is rather something that I do not know or understand yet.

Is this just a missing feature, or am I requesting something, that does not make sense at all?

1 Like

Did you figure out the problem? I am trying to create a custom key provider for deterministic encryption so I can set up custom key rotation, but I am getting an error that decryption_keys(message) method is undefined. I haven’t been able to get past that.

Heya, did you ever figure out a solution for this? I’m starting down this road at the moment and it’s proving difficult finding any real info