spikex / strongbox

Secures ActiveRecord attributes with public key encryption
http://stuff-things.net/2009/04/17/introducing-strongbox/
MIT License
397 stars 43 forks source link

RSAError: data greater than mod len #14

Closed whurl closed 12 years ago

whurl commented 13 years ago

OpenSSL::PKey::RSAError: data greater than mod len from /usr/local/lib/ruby/gems/1.8/gems/strongbox-0.4.6/lib/strongbox/lock.rb:87:in private_decrypt' from /usr/local/lib/ruby/gems/1.8/gems/strongbox-0.4.6/lib/strongbox/lock.rb:87:indecrypt'

Have you ever come across this error? I can't figure out the problem. I followed your readme word for word from creating the private/public key files and keypair.pem to setting up the model.

I'm using a Mac 10.6.7 and OpenSSL 0.9.8l 5 Nov 2009

whurl commented 13 years ago

P.S. I get that error when I call model.secret.decrypt 'pass'

spikex commented 13 years ago

OpenSSL::PKey::RSAError: data greater than mod len from /usr/local/lib/ruby/gems/1.8/gems/strongbox-0.4.6/lib/strongbox/lock.rb:87:in private_decrypt' from /usr/local/lib/ruby/gems/1.8/gems/strongbox-0.4.6/lib/strongbox/lock.rb:87:indecrypt'

Have you ever come across this error? I can't figure out the problem. I followed your readme word for word from creating the private/public key files and keypair.pem to setting up the model.

I'm using a Mac 10.6.7 and OpenSSL 0.9.8l 5 Nov 2009

How long is the data you are trying to encrypt? What size key did you generate?

cafedelamar commented 12 years ago

whurl, Did you ever get this issue resolved? I'm having the same issue only in my production heroku (with dedicated db) instance, not in any other shared db instance or my local postgres instance.

spikex commented 12 years ago

Can you get the length of the encrypted field? This error almost always means that the encrypted data is truncated (because the database column is too small) or it's padded with whitespace of some sort.

cafedelamar commented 12 years ago

The length of the three fields are: field_name(32), field_name_key(256), field_name_iv(256), the unencrypted field is 16 bytes like VDF8-QJWSVX-P9WU and all of the columns are bytea (postgres).

spikex commented 12 years ago

If you look at the encrypted value of field_name in the database, how big is that?

cafedelamar commented 12 years ago

Using the length function showed that it is 32 in the prod db. That is a little bit suspicious given that my local sqllite values are anywhere from 24 - 34. I only have one example in prod, so I guess I'll go create a few more to see if there's a pattern.

cafedelamar commented 12 years ago

After a brainstorm with my colleagues, here's my theory: when the database and the ruby code are all on the same platform or type of platform, everything's fine. After migrating the heroku database to a dedicated database, maybe a db server from IBM or Sun box that is big-endian while the ruby code runs on linux little-endian, then the decrypt fails.

I think I need an encryption solution that doesn't store in binary columns, but rather encodes to characters.

What do you think?

spikex commented 12 years ago

That's certainly possible. If you add:

:base64 => true

to your options and use a text column instead of a binary one, Strongbox will store the data as Base64 encoded text which might work across endians.

cafedelamar commented 12 years ago

Thanks Spike, I think that would work. The issue has been resolved with a Postgres config setting: bytea_output. Heroku shared databases default to bytea_output='escape' while the dedicated databases default to bytea_output=hex.

Here's the answer from Heroku's docs: http://devcenter.heroku.com/articles/heroku-postgresql#troubleshooting

PostgreSQL 9 bytea encoding

When migrating from PostgeSQL 8.x to PostgreSQL 9.x you can run into issues with binary string compatibility. The default representation is hex in version 9 but version 8 it is set to escaped. You can make PostgreSQL 9 use escaped by manually setting bytea_output.

You’ll need to first get the database username from your DATABASE_URL

For instance, if the DATABASE_URL is postgres://username:password@host/database_name

ALTER ROLE username SET bytea_output TO 'escape';

You can reset it back to hex:

ALTER ROLE username RESET bytea_output;

Once you have made this change, all subsequent connections will have the new encoding format. The easiest way to establish new connections is to restart your app.

$ heroku restart

spikex commented 12 years ago

Good to know, thanks! I'll document this somewhere.