开发者

What is the best way to obfuscate numerical IDs in an application

Given I've got a site where most of the resources have numerical IDs (i.e. user.id question.id etc.) b开发者_运维技巧ut that like the Germans looking back on WWII I'd rather not reveal these to the observers, what's the best way to obfuscate them?

I presume the method is going to involve the .to_param and then some symmetric encryption algorithm but I'm not sure what's the most efficient encryption to do and how it'll impact lookup times in the DB etc.

Any advice from the road trodden would be much appreciated.


I published a Rails plugin that does this called obfuscate_id. I didn't need it to be secure, but just to make the id in the url non-obvious to the casual user. I also wanted it to look cleaner than a long hash.

It also has the advantage of needing no migrations or database changes. It's pretty simple.

Just add the gem to your Gemfile:

gem 'obfuscate_id'

And add call the obfuscate id in your model:

class Post < ActiveRecord::Base
  obfuscate_id
end

This will create urls like this:

# post 7000
http://example.com/posts/5270192353
# post 7001
http://example.com/posts/7107163820
# post 7002
http://example.com/posts/3296163828

You also don't need to look up the records in any special way, ActiveRecord find just works.

Post.find(params[:id])

More information here:

https://github.com/namick/obfuscate_id


I usually use a salted Hash and store it in the DB in an indexed field. It depends on the level of security you expect, but I use one salt for all.

This method makes the creation a bit more expensive, because you are going to have an INSERT and an UPDATE, but your lookups will be quite fast.

Pseudo code:

class MyModel << ActiveRecord::Base

  MY_SALT = 'some secret string'

  after_create :generate_hashed_id

  def to_param
    self.hashed_id
  end

  def generate_hashed_id
    self.update_attributes(:hashed_id => Digest::SHA1.hexdigest("--#{MY_SALT}--#{self.id}--"))
  end

end

Now you can look up the record with MyModel.find_by_hashed_id(params[:id]) without any performance repercussions.


Here's a solution. It's the same concept as Wukerplank's answer, but there's a couple of important differences.

1) There's no need to insert the record then update it. Just set the uuid before inserting by using the before_create callback. Also note the set_uuid callback is private.

2) There's a handy library called SecureRandom. Use it! I like to use uuid's, but SecureRandom can generate other types of random numbers as well.

3) To find the record use User.find_by_uuid!(params[:id]). Notice the "!". That will raise an error if the record is not found just like User.find(params[:id]) would.

class User
  before_create :set_uuid

  def to_param
    uuid
  end

private

  def set_uuid
    self.uuid = SecureRandom.uuid
  end

end


Hashids is a great cross-platform option.


You can try using this gem,

https://github.com/wbasmayor/masked_id

it obfuscates your id and at the same time giving each model it's own obfuscated code so all no. 1 id won't have the same hash. Also, it does not override anything on the rails side, it just provides new method so it doesn't mess up your rails if your also extending them.


Faced with a similar problem, I created a gem to handle the obfuscation of Model ids using Blowfish. This allows the creation of nice 11 character obfuscated ids on the fly. The caveat is, the id must be within 99,999,999, e.g. a max length of 8.

https://github.com/mguymon/obfuscate

To use with Rails, create an initializer in config/initializers with:

require 'obfuscate/obfuscatable'
Obfuscate.setup do |config|
  config.salt = "A weak salt ..."
end

Now add to models that you want to be Obfuscatable:

class Message < ActiveRecord::Base
  obfuscatable # a hash of config overrides can be passed.
end

To get the 11 character obfuscated_id, which uses the Blowfish single block encryption:

message = Message.find(1)
obfuscated = message.obfuscated_id           # "NuwhZTtHnko"
clarified = message.clarify_id( obfuscated ) # "1"

Message.find_by_obfuscated_id( obfuscated )

Or obfuscate a block of text using Blowfish string encryption, allowing longer blocks of text to be obfuscated:

obfuscated = message.obfuscate( "if you use your imagination, this is a long block of text" ) # "GoxjVCCuBQgaLvttm7mXNEN9U6A_xxBjM3CYWBrsWs640PVXmkuypo7S8rBHEv_z1jP3hhFqQzlI9L1s2DTQ6FYZwfop-xlA"
clarified = message.clarify( obfuscated ) # "if you use your imagination, this is a long block of text"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜