views:

229

answers:

6

Let's say an application has really specific data which belongs to a user, and nobody is supposed to see it except the owner. I use MySQL database with DataMapper ORM mapper. The application is written in Ruby on Sinatra.

Application behavior:

  1. User signs up for an account. Creates username and password.
  2. Logs into his dashboard.
  3. Some fields in specific tables must be protected.

Basically, I'm looking for auto-encryption for a model properties. Something like this:

class Transaction
  include DataMapper::Resource

  property :id, Serial
  property :value, String, :length => 1024, :encrypted => true
  ... etc ...
  belongs_to :user
end

I assume that encryption/decryption on the fly will cause performance problems, but that's ok. At least if that works - I'm fine.

Any ideas how to do this?

A: 

You use a one-way hashing algorithm. Hash the password and store the hash. Then whenever the user enters his password, you hash the password entered and compare it to the stored hashed password. If they're the same, you let them through. If not, they're denied.

Pistol
Don't forget to use a salt too. http://en.wikipedia.org/wiki/Salt_%28cryptography%29
Mark Byers
that's good for "not storing user's password in plaintext", but I think that the questioner needs to decrypt the user's data at some point (e.g. medical records)
Piskvor
i know about passwords, but the question is about how to keep user`s data enctypted.
Dan Sosedoff
+1  A: 

It's generally not a good idea to ever store a user's password that can be taken to plaintext.

Typically it is stored as a salted hash of either MD5 or SHA1.

So, you have a random salt, store it in the user's table, and then you hash their pass and the salt, like this:

$hash = md5(md5(salt) + pass)

I would recommend against storing a pass that can be returned, the only way I'd recommend you store it is in a one way hash.

That said, there are some encryption schemes that you can use, such as RSA encrytion. This way, your application will encrypt the user's password that it receives from the end user using your public key, and when you need to decrypt it, do so using your private key. There's really very limited application for storing a key this way (such as providing a log in to another site automatically) and is typically frowned upon.

Crowe T. Robot
+2  A: 

So you want to store the data encrypted in the database? Firstly, I would ask you to consider why you need to do this? You should be able to write your application such that only the authenticated user can get to their own data.

If you do genuninely need to store encrypted data, that you also need to be able to decrypt (as opposed to a one-way hash) then there is lots about encryption in ruby here: http://www.example-code.com/ruby/encryption.asp

DanSingerman
"only the authenticated user can get to their own data." Indeed, that's the premise of the question. But the data don't exist in a vacuum, if there is a need to store them, they have to be stored somewhere. As long as you encrypt them properly, you may as well store them in the DB, other factors permitting (storing 100 MB file in DB makes no sense, storing a 1K string may)
Piskvor
yeah, data will be primarily numbers and short strings, it is money-related data so need to keep it private for each user.another thing is - how to make any aggregate operations on such encrypted data?
Dan Sosedoff
+3  A: 

I wouldn't store any data that relies on the user remembering their password and then using that password to decrypt the data. What are you going to do when the user changes their password? Decrypt/Encrypt everything? I doubt it. What if the admin reset the password? All data lost? Again, I doubt it.

See the other links about storing secrets but please don't use any value from the user as part of your encryption.

No Refunds No Returns
Yes, the password entered by the user should be used to verify *access* to the rest of his data, not used to actually encrypt it. The password could also be used to verify access to a random encryption string (which never changes) for encrypting the user data.
Loadmaster
+1  A: 

You certainly should encrypt/decrypt data on user side - otherwise there is no point in encrypted storage, as tracks of private data still there somewhere - in network cache, in swapfiles of different kind etc. Moreover, data can be sniffed with Man-In-The-Middle attack.

So what you probably want is javascript-based client-side encryption. Topic is greatly covered in http://javascript.about.com/library/blencrypt.htm (Rijndael encryption algorithm), and there is great AES implementation library on http://www.movable-type.co.uk/scripts/aes.html

You should encrypt data before submission of form (with onClick callback of "Submit" button f. e.), and then pass to server and process as usual.

Drawback is that you can't use any Rails with such data - only client-side javascript.

kirushik
+1  A: 

I had to do this for encrypting sensitive data. I wrapped the strongbox gem and it's on github: http://github.com/bitzesty/safe

The safe gem provides Public Key Encryption of AR attributes.

MatthewFord