spikex / strongbox Goto Github PK
View Code? Open in Web Editor NEWSecures ActiveRecord attributes with public key encryption
Home Page: http://stuff-things.net/2009/04/17/introducing-strongbox/
License: MIT License
Secures ActiveRecord attributes with public key encryption
Home Page: http://stuff-things.net/2009/04/17/introducing-strongbox/
License: MIT License
Adding the gem causes a "stack level too deep" of the db:schema:dump rake task on Rails 3.2.2 / Ruby 1.9.3.
Here is the output from the task using --trace:
** Invoke db:schema:dump (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config (first_time)
** Invoke rails_env (first_time)
** Execute rails_env
** Execute db:load_config
** Execute db:schema:dump
rake aborted!
stack level too deep
/Users/carsonreinke/.rvm/gems/ruby-1.9.3-p125/gems/rake-0.9.2.2/lib/rake/task.rb:162
Tasks: TOP => db:schema:dump
You call class_attribute in strongbox.rb which doesn't exist in older rails versions.
Maybe more of a feature request than anything else but using the (default) symmetric => :always option without the relevant database columns currently fails silently. E.g. the secret_iv and secret_key attributes are assigned and saving the AR model appears to work. But when reloading the model from the database obviously the required secret_iv and secret_key values are lost making the encrypted secret irretrievable.
Hi there.
I'm using the master branch to get access to the deferred_encryption
option.
This is the error I'm getting:
Agent.create(password: 'hello', encrypted_password: 'a').encrypted_password.decrypt 'hello'
# => OpenSSL::PKey::RSAError: padding check failed
Based on this code:
require 'openssl'
class Agent < ActiveRecord::Base
attr_accessor :password
# Encrypts the emphemeral #password value into the #encrypted_password field.
encrypt_with_public_key :encrypted_password, key_pair: :key_pair,
deferred_encryption: true,
padding: RSA_PKCS1_OAEP_PADDING,
symmetric: :always,
symmetric_cipher: 'des3'
private
def key_pair
rsa_key = OpenSSL::PKey::RSA.new(2048)
cipher = OpenSSL::Cipher::Cipher.new('des3')
rsa_key.to_pem(cipher,self.password) + rsa_key.public_key.to_pem
end
end
Here is the stacktrace from the exception:
from /Users/emil/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/bundler/gems/strongbox-975d4dcf6c8b/lib/strongbox/lock.rb:105:in `private_decrypt'
from /Users/emil/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/bundler/gems/strongbox-975d4dcf6c8b/lib/strongbox/lock.rb:105:in `decrypt'
from (irb):1
from /Users/emil/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.3/lib/rails/commands/console.rb:110:in `start'
from /Users/emil/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.3/lib/rails/commands/console.rb:9:in `start'
from /Users/emil/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:68:in `console'
from /Users/emil/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.3/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /Users/emil/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.3/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
I tried outputting boy the symmetric_cipher and the padding from lock.rb
s encrypt
and decrypt
method, and they where the same going in, and comming out. So I'm a little at a loss, on what's going on.
The reason I'm bringing it up as an issue here, is that I suspect that the deferred_encryption might be at fault?
Best regards,
Emil
This code:
class User < ActiveRecord::Base
encrypt_with_public_key :first_name, :symmetric => :never, :base64 => true, :public_key => File.join(RAILS_ROOT,'config','public.pem')
encrypt_with_public_key :last_name, :symmetric => :never, :base64 => true, :public_key => File.join(RAILS_ROOT,'config','public.pem')
end
results in
User.create(:first_name => 'jason', :last_name => 'ward)
=> #<User id: 2, first_name: nil, last_name: "pMLj/Sa87FgR6mV1et8Hbo6F/eTI/efSgb6qenVVegNVUMEyjz9...", created_at: "2009-10-09 05:05:55", updated_at: "2009-10-09 05:05:55">
According to this article http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation
the IV doesn't to be secret; instead, it should only be ensured that the IV isn't re-used with the same key. Since you do generate a random key already, then it should be fine to record the IV without need for encrypting it.
Of course, backward compatibility is an issue with that. There would need to be an option to indicate unencrypted IV's - that, or a marker on the IV to indicate that it's cleartext.
Thoughts?
Randy
It looks like you're asking if the passphrase is blank? instead of nil - if the secret key is not encrypted (being secured through other means), then the data can't be recovered with the current version of your code :)
Fortunately, it's an easy fix.
I using strongbox in my application. Some userdata which should be encrypted are not mandatory. When a user add a phone number for an example and will remove this data later, this is not possible. How can I implement this. I find the issue how to set a field to nil, but I only will do this if the string is empty. Can this be done in the model? Thank you.
I tried this before the validation, because I need a validation on encrypted fields later.
def before_validation
if self.sec_data.blank?
self.sec_data = nil
end
end
Please add Changelog or History to the repository. It's much easier to perform the upgrade when you're confident nothing will break.
Thanks.
After gem 'strongbox', :git => 'https://github.com/spikex/strongbox.git'
and bundle install, i have:
Using strongbox (0.4.2) from https://github.com/spikex/strongbox.git (at master)
strongbox at /Users/vshvedov/.rvm/gems/ruby-1.9.2-p0/bundler/gems/strongbox-60fadf03d926 did not have a valid gemspec.
This prevents bundler from installing bins or native extensions, but that may not affect its functionality.
The validation message from Rubygems was:
["README.html"] are not files
message.
When trying to set the field to nil, nil gets encrypted.
u = User.first
u.secret = nil
u.save
u = User.first
u.secret.nil?
=> false
Hi again,
We want to symmetrically encrypt certain data to a key that's provided by the model object. Particularly, we're encrypting it to a secret answer known only to the user. We'd like to encrypt it without the asymmetric encryption - looks pretty easy to adjust in Strongbox::Lock. Would you entertain a patch for that?
For background, we're going to encrypt the secret answer using the normal method, and in the security perimeter we'll be able to then conduct operations that require the decrypted answer - like encrypting new bits of data using it as a symmetric key. Then, at times when the user chooses to enter their secret answer, we can provide some limited decryption for that user's need, while preventing mass exposure of decryptable content to an attacker.
Thoughts?
Randy
PKCS#1 v1.5 is vulnerable to adaptive chosen ciphertext attacks. The default padding should likely be changed to OAEP. "No padding" should not be an option.
The encrypt_with_public_key
declaration in the models using strongbox is producing the following deprecation warnings under Rails 3.1.0.rc4:
DEPRECATION WARNING: class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first.
What can be done about this?
I have a simple registration form for user with nested models (like contact model below), which captures telephone, mobile, email and website. telephone and email are protected using strongbox.
the code in model:
belongs_to :contactable, :polymorphic => true
validates :telephone, :length => {:minimum => 6, :maximum => 16}
validates :mobile, :length => {:minimum => 6,:maximum => 16}
validates :email, :length => {:minimum => 6,:maximum => 64}
encrypt_with_public_key :telephone,
:key_pair => File.join(File.dirname(FILE),'../../config/keypair.pem'),
:symmetric => :never,
:base64 => :true
encrypt_with_public_key :email,
:key_pair => File.join(File.dirname(FILE),'../../config/keypair.pem'),
:symmetric => :never,
:base64 => :true
the problem is in validation. If I leave the form empty and click on create button, it will show undefined method `>=' for nil:NilClass. if I correctly enter the data the registration is saved just fine.
If I enter email and telephone and leave other fields empty, validation works, but those two fields are presented on the form in encrypted version.
What is the problem? Encryption should be set if all validation pass and then object is stored to DB.
Miha
What is the current state of this gem? According to the Readme:
Strongbox is tested against Rails 2.3 and 3.x using Ruby 1.8.7, 1.9.2, and 1.9.3.
I see there is an unmerged pull request from 2014 to update support for Rails 4.1 and Ruby 2.1. Now, Rails 5 is out. Is this gem maintained anymore?
WIth binary columns both some_encrypted_model_instance.to_xml and some_encrypted_model_instance.to_json do not work. I expected them to return ** encrypted ** values.
Hi I'm not sure this is an issue it might be more a question or perhaps a feature request.
I would like to avoid storing the private key in the server for extra security, therefore I would like to regenerate the private key everytime the user needs to access the encrypted data. Also I dont understand the point of generating the public-private key pair and encrypt with the public key if both are going to be stored at the server?
Thanks
It is possible to have dynamic ":public_key", ":private_key" configuration. For example each user have many addressees. Each user can upload own keys to the server and can encrypt/decrypt data with this keys.
I am using NSS to store the keys I want to provide to strongbox for encryption/decryption. Accessing nss requires the use of the PKCS11 gem. The keys, when retrieved from NSS are PKCS11::Object's. Strongbox requires OpenSSL::PKey::RSA objects. I am unfamiliar with the internals of both of those objects, and so it is unclear to me how to convert PKCS11::Object to OpenSSL::PKey::RSA. Has anyone done this before or know how to do it? Thanks
Brendan
Docs are a bit unclear on this one. The data that can be encrypted with asymmetric-only is limited to the size of the key minus 11 bytes. Particularly:
I understand that "a string field is unlikely to be able to store the result"... but more detail would be clearer.
Thanks!
Hi,
This is not actually an issue, but rather a set of questions. We're faced with a tough problem and it looks like your gem might actually help us. Here's our case:
Our system has multiple companies
Each company has multiple users
Each company can create multiple auctions
Other companies can then submit their bids for the available auctions.
The prices for the bids will be saved as integers (cents) and as such will always be smaller than 245 bytes per price.
The problem that we're facing is that our customers do not want us to ever have access to the bid prices, for security reasons.
Here's what we thus thought of doing:
When a company signs up, we create a public/private keypair for it. Each company in the system thus have it's own fixed pair that cannot be changed once created. The password of the keypair is not saved into the database and must be entered every time its required by a user of the company.
When a company submits a bid, we encrypt the data using the auction's owner company to encrypt the data. When the prices then have to be made public, we ask the issuing company for their password and use their own private key to decrypt the prices using their own private key.
SO here are the questions (and we're unfortunately not security experts, so sorry if those are stupid questions)
Thanks!
I have a problem with german umlauts in secured datafields. When I saved "grün" (english: green) in a mysql database field, and show it again, i get the following Error:
Encoding::CompatibilityError in Addressees#show
incompatible character encodings: UTF8 and ASCII-8BIT
I had to use force_encode('utf8') for each field.
It this an error in strongbox? Why are the encrypted fields decrypted in ascii-8bit?
Hello,
My format validation doesn't appear to work with Strongbox encryption. For an object called Request, I have an attribute called :tin
. Request is a child class of User.
The validations are now failing after attempting to encrypt with Strongbox. I believe it's because Strongbox is validating the encrypted value, rather than the value itself: When the validation fails and the form is rendered again, the encrypted value shows up in the :tin
field.
A snippet of models/request.rb
is below.
class Request < ActiveRecord::Base
attr_accessible :tin
belongs_to :user
accepts_nested_attributes_for :user
TINRegex = /^\d{2}\-\d{7}$/
validates_format_of :tin, :with=>TINRegex
encrypt_with_public_key :tin,
:symmetric => :never,
:base64 => true,
:key_pair => Rails.root.join('config','keypair.pem')
end
When I was working on strongbox earlier, I realized that I wasn't testing the Rails 2.x stuff. If we had our build set up to run with Travis-CI automatically (and specify the versions that we support -- Rails and ruby versions), then this would make development a lot easier.
So I propose that we set up Travis-CI (it's free for open source projects like this).
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:in
decrypt'
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
This gem does not use a MAC to verify data integrity. This can be problematic if ciphertexts are malleable by an attacker, i.e. an attacker gains access to the database and can perform chosen ciphertext attacks.
I'd suggest you add something like ActiveSupport::MessageVerifier (which uses HMAC and performs a timing-attack resistant MAC comparison) to ensure the ciphertexts are authentic:
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/message_verifier.rb
Hey there,
I'm getting this error when trying to save my model: string contains null byte
Here's the stack trace from the console:
ArgumentError: string contains null byte
from /usr/local/bundle/gems/activerecord-4.1.6/lib/active_record/connection_adapters/postgresql/oid.rb:30:in `unescape_bytea'
from /usr/local/bundle/gems/activerecord-4.1.6/lib/active_record/connection_adapters/postgresql/oid.rb:30:in `type_cast'
from /usr/local/bundle/gems/activerecord-4.1.6/lib/active_record/connection_adapters/postgresql_adapter.rb:156:in `type_cast'
from /usr/local/bundle/gems/activerecord-4.1.6/lib/active_record/attribute_methods/dirty.rb:102:in `_field_changed?'
from /usr/local/bundle/gems/activerecord-4.1.6/lib/active_record/attribute_methods/dirty.rb:78:in `save_changed_attribute'
from /usr/local/bundle/gems/activerecord-4.1.6/lib/active_record/attribute_methods/dirty.rb:66:in `write_attribute'
from /usr/local/bundle/gems/activerecord-4.1.6/lib/active_record/attribute_methods.rb:395:in `[]='
from /usr/local/bundle/gems/strongbox-0.7.0/lib/strongbox/lock.rb:50:in `encrypt'
from /usr/local/bundle/gems/strongbox-0.7.0/lib/strongbox.rb:80:in `block in encrypt_with_public_key'
from (irb):2
from /usr/local/bundle/gems/railties-4.1.6/lib/rails/commands/console.rb:90:in `start'
from /usr/local/bundle/gems/railties-4.1.6/lib/rails/commands/console.rb:9:in `start'
from /usr/local/bundle/gems/railties-4.1.6/lib/rails/commands/commands_tasks.rb:69:in `console'
from /usr/local/bundle/gems/railties-4.1.6/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from /usr/local/bundle/gems/railties-4.1.6/lib/rails/commands.rb:17:in `<top (required)>'
from /usr/local/bundle/gems/activesupport-4.1.6/lib/active_support/dependencies.rb:247:in `require'
... 4 levels...
from /usr/local/bundle/gems/activesupport-4.1.6/lib/active_support/dependencies.rb:241:in `load'
from /usr/local/bundle/gems/activesupport-4.1.6/lib/active_support/dependencies.rb:241:in `block in load'
from /usr/local/bundle/gems/activesupport-4.1.6/lib/active_support/dependencies.rb:232:in `load_dependency'
from /usr/local/bundle/gems/activesupport-4.1.6/lib/active_support/dependencies.rb:241:in `load'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/commands/rails.rb:6:in `call'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/command_wrapper.rb:38:in `call'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/application.rb:183:in `block in serve'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/application.rb:156:in `fork'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/application.rb:156:in `serve'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/application.rb:131:in `block in run'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/application.rb:125:in `loop'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/application.rb:125:in `run'
from /usr/local/bundle/gems/spring-1.2.0/lib/spring/application/boot.rb:18:in `<top (required)>'
from /usr/local/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /usr/local/lib/ruby/2.1.0/rubygems/core_ext/kernel_require.rb:55:in `require'
Any ideas?
Hi there. I'm not sure if this is an issue or if I'm just not understanding the usage correctly.
I have:
class MyUser < ActiveRecord::Base
validate :validate_contact_number_format
encrypt_with_public_key :contact_number, :key_pair => Rails.root.join("config", "keypair.pem")
def validate_contact_number_format
if entry.start_with?('555')
errors.add :contact_number, "Invalid Contact Number"
end
end
end
However, when I try and save it, it will die with:
NoMethodError: undefined method `start_with?' for #<Strongbox::Lock:0x00000007b38998>
Understandably, it can't get the encrypted value without the password, but is there a way to validate the attribute before encrypting it?
I'm getting this error message when trying to use Strongbox for more then one field.
Cannot visit Strongbox::Lock
Here is the model related code.
encrypt_with_public_key :password, key_pair: File.join(Rails.root, "config", "keypairs.pem")
encrypt_with_public_key :username, key_pair: File.join(Rails.root, "config", "keypairs.pem")
Here is the schema.rb
file.
create_table "users", :force => true do |t|
# ...
t.binary "password"
t.binary "password_key"
t.binary "password_iv"
t.binary "username"
t.binary "username_key"
t.binary "username_iv"
end
I'm using Strongbox 0.4.8
, with Rails 3.1.1
.
The error occur when trying save an active record object.
Here is an example.
User.create!(username: "A", password: "B") # Fails
user = User.new
user.username = "A"
user.password = "B"
save! # Fails
Any ideas why this is happening?
There is a way to validate uniqueness?
I thought in encrypt the new input of my field and try to search for it in the database, but seems that it wasn't working very well oO
Someone have an idea for validate uniqueness of a field?
Is it possible to make the decryption offline?
Tagging future releases means it's easy to discern the code as-at a version number. Knowing this makes it easier to track down bugs, or determine features available at a certain version.
The readme says to config.gem spikex-strongbox, but that produces version 0.1.5 instead of 0.2.1 :(
Hi! I like your gem. But I am not really sure why I need :secret field for asymmetric-encryption? I've tried without it and it works fine (let's say on email field).
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.