Permalink
Browse files

Allow Lock to decrypt arbitrary strings encrypted with the same keypair.

  • Loading branch information...
1 parent 850bd70 commit 8236c73d94ac3909dccf0b48d10df13a8519d6eb Jason Whittle committed Jan 12, 2011
Showing with 37 additions and 33 deletions.
  1. +2 −2 lib/strongbox/lock.rb
  2. BIN test/fixtures/encrypted
  3. +35 −31 test/strongbox_test.rb
View
4 lib/strongbox/lock.rb
@@ -60,10 +60,10 @@ def encrypt plaintext
# Given the private key password decrypts the attribute. Will raise
# OpenSSL::PKey::RSAError if the password is wrong.
- def decrypt password = nil
+ def decrypt password = nil, ciphertext = nil
# Given a private key and a nil password OpenSSL::PKey::RSA.new() will
# *prompt* for a password, we default to an empty string to avoid that.
- ciphertext = @instance[@name]
+ ciphertext ||= @instance[@name]
return nil if ciphertext.nil?
return "" if ciphertext.empty?
View
BIN test/fixtures/encrypted
Binary file not shown.
View
66 test/strongbox_test.rb
@@ -15,31 +15,31 @@ class StrongboxTest < Test::Unit::TestCase
end
end
end
-
+
context 'that is valid' do
setup do
@dummy = Dummy.new
@dummy.secret = 'Shhhh'
@dummy.in_the_clear = 'Hey you guys!'
end
-
+
should 'not change unencrypted fields' do
assert_equal 'Hey you guys!', @dummy.in_the_clear
end
-
+
should 'return "*encrypted*" when locked' do
assert_equal '*encrypted*', @dummy.secret.decrypt
end
-
+
should 'return secret when unlocked' do
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
end
-
+
should 'generate and store symmetric encryption key and IV' do
assert_not_nil @dummy.attributes['secret_key']
assert_not_nil @dummy.attributes['secret_iv']
end
-
+
should 'raise on bad password' do
assert_raises(OpenSSL::PKey::RSAError) do
@dummy.secret.decrypt('letmein')
@@ -51,12 +51,12 @@ class StrongboxTest < Test::Unit::TestCase
@dummy.in_the_clear = 'I see you...'
@dummy.save
end
-
+
should 'not effect the secret' do
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
end
end
-
+
context 'updating the secret' do
setup do
@dummy.secret = @new_secret = 'Don\'t tell'
@@ -67,62 +67,67 @@ class StrongboxTest < Test::Unit::TestCase
assert_equal @new_secret, @dummy.secret.decrypt(@password)
end
end
-
+
context 'with symmetric encryption disabled' do
setup do
rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
:symmetric => :never)
@dummy = Dummy.new
@dummy.secret = 'Shhhh'
end
-
+
should 'return "*encrypted*" when locked' do
assert_equal '*encrypted*', @dummy.secret.decrypt
end
-
+
should 'return secret when unlocked' do
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
end
-
+
+ should 'allow decryption of other strings encrypted with the same key' do
+ encrypted_text = File.read(File.join(FIXTURES_DIR,'encrypted'))
+ assert_equal 'Setec Astronomy', @dummy.secret.decrypt(@password, encrypted_text)
+ end
+
should 'not generate and store symmetric encryption key and IV' do
assert_nil @dummy.attributes['secret_key']
assert_nil @dummy.attributes['secret_iv']
end
end
-
+
context 'with Base64 encoding enabled' do
setup do
rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
:base64 => true)
@dummy = Dummy.new
@dummy.secret = 'Shhhh'
end
-
+
should 'Base64 encode the ciphertext' do
# Base64 encoded text is limited to the charaters A–Z, a–z, and 0–9,
# and is padded with 0 to 2 equal-signs
assert_match /^[0-9A-Za-z+\/]+={0,2}$/, @dummy.attributes['secret']
assert_match /^[0-9A-Za-z+\/]+={0,2}$/, @dummy.attributes['secret_key']
assert_match /^[0-9A-Za-z+\/]+={0,2}$/, @dummy.attributes['secret_iv']
end
-
+
should 'encrypt the data' do
assert_not_equal @dummy.attributes['secret'], 'Shhhh'
assert_equal '*encrypted*', @dummy.secret.decrypt
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
end
end
end
-
+
context 'using blowfish cipher instead of AES' do
setup do
rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'),
:symmetric_cipher => 'bf-cbc')
@dummy = Dummy.new
@dummy.secret = 'Shhhh'
end
-
+
should 'encrypt the data' do
assert_not_equal @dummy.attributes['secret'], 'Shhhh'
assert_equal '*encrypted*', @dummy.secret.decrypt
@@ -143,20 +148,20 @@ class StrongboxTest < Test::Unit::TestCase
end
end
end
-
+
context 'when a private key is not provided' do
setup do
@password = 'boost facile'
rebuild_class(:public_key => File.join(FIXTURES_DIR,'keypair.pem'))
@dummy = Dummy.new(:secret => 'Shhhh')
end
-
+
should 'raise on decrypt with a password' do
assert_raises(Strongbox::StrongboxError) do
@dummy.secret.decrypt(@password)
end
end
-
+
should 'return "*encrypted*" when still locked' do
assert_equal '*encrypted*', @dummy.secret.decrypt
end
@@ -185,7 +190,7 @@ class StrongboxTest < Test::Unit::TestCase
assert_equal "Shhhh", @dummy.secret.decrypt('')
end
end
-
+
context 'with validations' do
context 'using validates_presence_of' do
setup do
@@ -194,18 +199,18 @@ class StrongboxTest < Test::Unit::TestCase
@valid = Dummy.new(:secret => 'Shhhh')
@invalid = Dummy.new(:secret => nil)
end
-
+
should 'not have an error on the secret when valid' do
assert @valid.valid?
assert_does_not_have_errors_on(@valid,:secret)
end
-
+
should 'have an error on the secret when invalid' do
assert !@invalid.valid?
assert_has_errors_on(@invalid,:secret)
end
end
-
+
context 'using validates_length_of' do
setup do
rebuild_class(:key_pair => File.join(FIXTURES_DIR,'keypair.pem'))
@@ -220,22 +225,22 @@ class StrongboxTest < Test::Unit::TestCase
@valid_blank = Dummy.new(:secret => '')
@invalid = Dummy.new(:secret => '1')
end
-
+
should 'not have an error on the secret when in range' do
assert @valid.valid?
assert_does_not_have_errors_on(@valid,:secret)
end
-
+
should 'not have an error on the secret when nil' do
assert @valid_nil.valid?
assert_does_not_have_errors_on(@valid_nil,:secret)
end
-
+
should 'not have an error on the secret when blank' do
assert @valid_blank.valid?
assert_does_not_have_errors_on(@valid_blank,:secret)
end
-
+
should 'have an error on the secret when invalid' do
assert !@invalid.valid?
assert_has_errors_on(@invalid,:secret)
@@ -260,7 +265,7 @@ class StrongboxTest < Test::Unit::TestCase
@dummy.secret = 'I have a secret...'
@dummy.segreto = 'Ho un segreto...'
end
-
+
should 'return "*encrypted*" when the record is locked' do
assert_equal '*encrypted*', @dummy.secret.decrypt
assert_equal '*encrypted*', @dummy.segreto.decrypt
@@ -290,10 +295,9 @@ class StrongboxTest < Test::Unit::TestCase
should 'return "*encrypted*" when locked' do
assert_equal '*encrypted*', @dummy.secret.decrypt
end
-
+
should 'return secret when unlocked' do
assert_equal 'Shhhh', @dummy.secret.decrypt(@password)
end
end
end
-

0 comments on commit 8236c73

Please sign in to comment.