5

Does ActiveSupport::MessageEncryptor support deterministic encryption so that we get the same encrypted value every time we encrypt a particular string? If not, are there any other Ruby libs that support deterministic encryption?

My goal is to get same encrypted value every time I encrypt a string and I should be able to decrypt it to original value as well.

Thanks.

Saim
  • 2,471
  • 5
  • 30
  • 43

3 Answers3

8

You get different crypts because ActiveSupport::MessageEncryptor uses OpenSSL for encryption which requires an iv by default to prevent attackers from inferring relationships between segments of the encrypted message. I would highly recommend you to not mess around with that because you open ways for attackers to infer the encryption key.

However if you still want to do that take a look into the OpenSSL documentation of ruby. There should be a way to encrypt without vector.

Because it's a high security risk I don't add code to the answer to protect others from unnecessary loop holes.

Tobias
  • 4,523
  • 2
  • 20
  • 40
  • 3
    Tobias, thanks for your note and I understand the security risk. The information we are trying to encrypt is stored in a secure database. We need to use the encrypted column in WHERE clause to filter encrypted data. We have discussed the security concerned and we are okay with this approach. I would be obliged if you could share a code snippet and maybe delete it later once I take a lot? Thanks again. – Saim Feb 26 '18 at 21:16
  • @Saim may I ask which database engine you use? What if you hash the content instead? – Tobias Feb 27 '18 at 07:32
  • its MySQL - InnoDB. We are also planning to migrate to Postgres in near future. – Saim Feb 28 '18 at 18:09
4

I did not get why ActiveSupport:MessageEncryptor didn't work. Here is another way to do it.

require 'bcrypt'

encrypted_password = BCrypt::Engine.hash_secret('password@!2#4', 'ADD SALT HERE')

you can also use it like this:

class User
  SALT = 'GENERATE A STATIC SALT HERE AND KEEP IT SECURE'.freeze
  include BCrypt

  def password=(given_password)
    @encrypted_password = Engine.hash_secret(given_password, SALT)
  end
end

For the full documentation please check their repo

PS: using a static salt for all users for authentication is a bad idea.

khaled_gomaa
  • 3,382
  • 21
  • 24
  • BCrypt produces the different encrypted value every time we call Password.create("something_to_encrypt"). – Saim Feb 26 '18 at 21:36
  • 1
    I updated the answer to use a static salt which assures the same encryption (this is used by devise in authentication) – khaled_gomaa Feb 26 '18 at 22:22
  • Thank you, Khaled. What I am actually trying to do is to store the encrypted auth_tokens in the database. The encryption part is working now. Now there is another issue, the problem is it's not logging me in even after even if we authenticate it properly in `authenticate_user_from_token!` method. It creates the session entry in the database but gets me to the login page. Do you have any idea where I need to look at? – Saim Feb 26 '18 at 23:20
  • Can you maybe share some code about this? Maybe even another question (A) – khaled_gomaa Feb 26 '18 at 23:23
  • Khaled, I have posted another question: https://stackoverflow.com/questions/48998922/device-token-authenticatable-is-not-working-with-encrypted-auth-tokens – Saim Feb 26 '18 at 23:49
-1

Of course: one just need to use the same key to get the same encryption

x = ActiveSupport::MessageEncryptor.new('12345678901234567890123456789012').encrypt_and_sign('foo')
=> "bXJmRUczdjVXRFdLTitUcmkvRnk1UT09LS0vb2ZYdDRybGdWbmNXMUI1VDNnQzVBPT0=--13232bbe31d966f7d1df3aaa6fcc1cdc9eea60a1"
ActiveSupport::MessageEncryptor.new('12345678901234567890123456789012').decrypt_and_verify(x)
=> "foo"

It's hard to tell why you get different results since you didn't post any code...

Greg
  • 5,862
  • 1
  • 25
  • 52
  • 1
    try to invoke `x = ActiveSupport::MessageEncryptor.new('12345678901234567890123456789012').encrypt_and_sign('foo')` multiple times and you would see it different encrypted value every time. I need same encrypted value every time I encrypt the same string with the same key. – Saim Feb 26 '18 at 19:13
  • But if you store the encrytped value, and try to decrypt it - it should give you the decrypted value. Did you try it? – Greg Feb 26 '18 at 19:16
  • 2
    Yes, it decrypts fine. What's I want is consistent/same encrypted value every time I encrypt a string. – Saim Feb 26 '18 at 21:34
  • Ok, got it. Maybe this will be useful for you https://stackoverflow.com/questions/4128939/simple-encryption-in-ruby-without-external-gems But I wonder - why would you insist on this, since it makes it less secure? – Greg Feb 26 '18 at 22:22