symmetric-encryption 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,6 +19,8 @@ ActiveRecord::Schema.define :version => 0 do
19
19
  create_table :users, :force => true do |t|
20
20
  t.string :encrypted_bank_account_number
21
21
  t.string :encrypted_social_security_number
22
+ t.string :encrypted_string
23
+ t.text :encrypted_long_string
22
24
  t.string :name
23
25
  end
24
26
  end
@@ -26,6 +28,8 @@ end
26
28
  class User < ActiveRecord::Base
27
29
  attr_encrypted :bank_account_number
28
30
  attr_encrypted :social_security_number
31
+ attr_encrypted :string, :random_iv => true
32
+ attr_encrypted :long_string, :random_iv => true, :compress => true
29
33
 
30
34
  validates :encrypted_bank_account_number, :symmetric_encryption => true
31
35
  validates :encrypted_social_security_number, :symmetric_encryption => true
@@ -56,6 +60,9 @@ class AttrEncryptedTest < Test::Unit::TestCase
56
60
  @social_security_number = "987654321"
57
61
  @social_security_number_encrypted = "S+8X1NRrqdfEIQyFHVPuVA=="
58
62
 
63
+ @string = "A string containing some data to be encrypted with a random initialization vector"
64
+ @long_string = "A string containing some data to be encrypted with a random initialization vector and compressed since it takes up so much space in plain text form"
65
+
59
66
  @user = User.new(
60
67
  # Encrypted Attribute
61
68
  :bank_account_number => @bank_account_number,
@@ -82,6 +89,29 @@ class AttrEncryptedTest < Test::Unit::TestCase
82
89
  assert_equal @social_security_number_encrypted, @user.encrypted_social_security_number
83
90
  end
84
91
 
92
+ should "support same iv" do
93
+ @user.social_security_number = @social_security_number
94
+ assert first_value = @user.social_security_number
95
+ # Assign the same value
96
+ @user.social_security_number = @social_security_number
97
+ assert_equal first_value, @user.social_security_number
98
+ end
99
+
100
+ should "support a random iv" do
101
+ @user.string = @string
102
+ assert first_value = @user.encrypted_string
103
+ # Assign the same value
104
+ @user.string = @string.dup
105
+ assert_equal true, first_value != @user.encrypted_string
106
+ end
107
+
108
+ should "support a random iv and compress" do
109
+ @user.string = @long_string
110
+ @user.long_string = @long_string
111
+
112
+ assert_equal true, (@user.encrypted_long_string.length.to_f / @user.encrypted_string.length) < 0.8
113
+ end
114
+
85
115
  should "encrypt" do
86
116
  user = User.new
87
117
  user.bank_account_number = @bank_account_number
data/test/cipher_test.rb CHANGED
@@ -14,14 +14,14 @@ SymmetricEncryption.load!(File.join(File.dirname(__FILE__), 'config', 'symmetric
14
14
  class CipherTest < Test::Unit::TestCase
15
15
  context 'standalone' do
16
16
 
17
- should "allow setting the cipher" do
17
+ should "allow setting the cipher_name" do
18
18
  cipher = SymmetricEncryption::Cipher.new(
19
- :cipher => 'aes-128-cbc',
19
+ :cipher_name => 'aes-128-cbc',
20
20
  :key => '1234567890ABCDEF1234567890ABCDEF',
21
21
  :iv => '1234567890ABCDEF',
22
22
  :encoding => :none
23
23
  )
24
- assert_equal 'aes-128-cbc', cipher.cipher
24
+ assert_equal 'aes-128-cbc', cipher.cipher_name
25
25
  end
26
26
 
27
27
  should "not require an iv" do
@@ -40,7 +40,7 @@ class CipherTest < Test::Unit::TestCase
40
40
 
41
41
  should "throw an exception on bad data" do
42
42
  cipher = SymmetricEncryption::Cipher.new(
43
- :cipher => 'aes-128-cbc',
43
+ :cipher_name => 'aes-128-cbc',
44
44
  :key => '1234567890ABCDEF1234567890ABCDEF',
45
45
  :iv => '1234567890ABCDEF',
46
46
  :encoding => :none
@@ -70,7 +70,7 @@ class CipherTest < Test::Unit::TestCase
70
70
  end
71
71
 
72
72
  should "default to 'aes-256-cbc'" do
73
- assert_equal 'aes-256-cbc', @cipher.cipher
73
+ assert_equal 'aes-256-cbc', @cipher.cipher_name
74
74
  end
75
75
 
76
76
  should "encrypt simple string" do
@@ -96,17 +96,18 @@ class CipherTest < Test::Unit::TestCase
96
96
  context "magic header" do
97
97
 
98
98
  should "create and parse magic header" do
99
- random_cipher = SymmetricEncryption::Cipher.random_cipher
100
- header = random_cipher.magic_header(compressed=true, include_iv=true, include_key=true, include_cipher=true)
101
- cipher, compressed = SymmetricEncryption::Cipher.parse_magic_header!(header)
99
+ random_cipher = SymmetricEncryption::Cipher.new(SymmetricEncryption::Cipher.random_key_pair)
100
+ header = SymmetricEncryption::Cipher.magic_header(1, compressed=true, random_cipher.send(:iv), random_cipher.send(:key), random_cipher.cipher_name)
101
+ compressed, iv, key, cipher_name, decryption_cipher = SymmetricEncryption::Cipher.parse_magic_header!(header)
102
102
  assert_equal true, compressed
103
- assert_equal random_cipher.cipher, cipher.cipher, "Ciphers differ"
104
- assert_equal random_cipher.send(:key), cipher.send(:key), "Keys differ"
105
- assert_equal random_cipher.send(:iv), cipher.send(:iv), "IVs differ"
103
+ assert_equal random_cipher.cipher_name, cipher_name, "Ciphers differ"
104
+ assert_equal random_cipher.send(:key), key, "Keys differ"
105
+ assert_equal random_cipher.send(:iv), iv, "IVs differ"
106
106
 
107
- string = "Hellow World"
107
+ string = "Hello World"
108
+ cipher = SymmetricEncryption::Cipher.new(:key => key, :iv => iv, :cipher_name => cipher_name)
108
109
  # Test Encryption
109
- assert_equal random_cipher.encrypt(string, false), cipher.encrypt(string, false), "Encrypted values differ"
110
+ assert_equal random_cipher.encrypt(string, false, false), cipher.encrypt(string, false, false), "Encrypted values differ"
110
111
  end
111
112
  end
112
113
 
@@ -38,7 +38,7 @@ test:
38
38
  # Current / Newest Symmetric Encryption Key
39
39
  - key_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_new.key
40
40
  iv_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_new.iv
41
- cipher: aes-128-cbc
41
+ cipher_name: aes-128-cbc
42
42
  # Base64 encode encrypted data without newlines
43
43
  encoding: base64strict
44
44
  version: 1
@@ -46,7 +46,7 @@ test:
46
46
  # Previous Symmetric Encryption Key
47
47
  - key_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_secondary_1.key
48
48
  iv_filename: /Users/rmorrison/Sandbox/symmetric-encryption/test/config/test_secondary_1.iv
49
- cipher: aes-128-cbc
49
+ cipher_name: aes-128-cbc
50
50
  # Base64 encode encrypted data without newlines
51
51
  encoding: base64
52
52
  version: 0
@@ -22,6 +22,8 @@ class MongoidUser
22
22
  field :name, :type => String
23
23
  field :encrypted_bank_account_number, :type => String, :encrypted => true
24
24
  field :encrypted_social_security_number, :type => String, :encrypted => true
25
+ field :encrypted_string, :type => String, :encrypted => true, :random_iv => true
26
+ field :encrypted_long_string, :type => String, :encrypted => true, :random_iv => true, :compress => true
25
27
  # field :encrypted_integer, :type => Integer, :encrypted => true
26
28
  # field :encrypted_float, :type => Float, :encrypted => true
27
29
  # field :encrypted_date, :type => Date, :encrypted => true
@@ -55,6 +57,9 @@ class FieldEncryptedTest < Test::Unit::TestCase
55
57
  @date = Date.parse('20120320')
56
58
  @date_encrypted = "WTkSPHo5ApSSHBJMxxWt2A=="
57
59
 
60
+ @string = "A string containing some data to be encrypted with a random initialization vector"
61
+ @long_string = "A string containing some data to be encrypted with a random initialization vector and compressed since it takes up so much space in plain text form"
62
+
58
63
  # #TODO Intercept passing in attributes to create etc.
59
64
  @user = MongoidUser.new(
60
65
  :encrypted_bank_account_number => @bank_account_number_encrypted,
@@ -84,6 +89,29 @@ class FieldEncryptedTest < Test::Unit::TestCase
84
89
  assert_equal @social_security_number_encrypted, @user.encrypted_social_security_number
85
90
  end
86
91
 
92
+ should "support same iv" do
93
+ @user.social_security_number = @social_security_number
94
+ assert first_value = @user.social_security_number
95
+ # Assign the same value
96
+ @user.social_security_number = @social_security_number
97
+ assert_equal first_value, @user.social_security_number
98
+ end
99
+
100
+ should "support a random iv" do
101
+ @user.string = @string
102
+ assert first_value = @user.encrypted_string
103
+ # Assign the same value
104
+ @user.string = @string.dup
105
+ assert_equal true, first_value != @user.encrypted_string
106
+ end
107
+
108
+ should "support a random iv and compress" do
109
+ @user.string = @long_string
110
+ @user.long_string = @long_string
111
+
112
+ assert_equal true, (@user.encrypted_long_string.length.to_f / @user.encrypted_string.length) < 0.8
113
+ end
114
+
87
115
  should "encrypt" do
88
116
  user = MongoidUser.new
89
117
  user.bank_account_number = @bank_account_number
data/test/reader_test.rb CHANGED
@@ -22,56 +22,90 @@ class ReaderTest < Test::Unit::TestCase
22
22
  ]
23
23
  @data_str = @data.inject('') {|sum,str| sum << str}
24
24
  @data_len = @data_str.length
25
- @data_encrypted = SymmetricEncryption.cipher.encrypt(@data_str, false)
25
+ @data_encrypted_without_header = SymmetricEncryption.cipher.binary_encrypt(@data_str)
26
+
27
+ @data_encrypted_with_header = SymmetricEncryption::Cipher.magic_header(
28
+ SymmetricEncryption.cipher.version,
29
+ compress = false,
30
+ SymmetricEncryption.cipher.send(:iv),
31
+ SymmetricEncryption.cipher.send(:key),
32
+ SymmetricEncryption.cipher.cipher_name)
33
+ @data_encrypted_with_header << SymmetricEncryption.cipher.binary_encrypt(@data_str)
34
+
35
+ # Verify regular decrypt can decrypt this string
36
+ SymmetricEncryption.cipher.binary_decrypt(@data_encrypted_without_header)
37
+ SymmetricEncryption.cipher.binary_decrypt(@data_encrypted_with_header)
26
38
  end
27
39
 
28
- should "decrypt from string stream as a single read" do
29
- stream = StringIO.new(@data_encrypted)
30
- decrypted = SymmetricEncryption::Reader.open(stream) {|file| file.read}
31
- assert_equal @data_str, decrypted
32
- end
40
+ [true, false].each do |header|
41
+ context header do
42
+ setup do
43
+ @data_encrypted = header ? @data_encrypted_with_header : @data_encrypted_without_header
44
+ end
33
45
 
34
- should "decrypt from string stream as a single read, after a partial read" do
35
- stream = StringIO.new(@data_encrypted)
36
- decrypted = SymmetricEncryption::Reader.open(stream) do |file|
37
- file.read(10)
38
- file.read
39
- end
40
- assert_equal @data_str[10..-1], decrypted
41
- end
46
+ should "decrypt from string stream as a single read" do
47
+ stream = StringIO.new(@data_encrypted)
48
+ decrypted = SymmetricEncryption::Reader.open(stream) {|file| file.read}
49
+ assert_equal @data_str, decrypted
50
+ end
42
51
 
43
- should "decrypt lines from string stream" do
44
- stream = StringIO.new(@data_encrypted)
45
- i = 0
46
- decrypted = SymmetricEncryption::Reader.open(stream) do |file|
47
- file.each_line do |line|
48
- assert_equal @data[i], line
49
- i += 1
52
+ should "decrypt from string stream as a single read, after a partial read" do
53
+ stream = StringIO.new(@data_encrypted)
54
+ decrypted = SymmetricEncryption::Reader.open(stream) do |file|
55
+ file.read(10)
56
+ file.read
57
+ end
58
+ assert_equal @data_str[10..-1], decrypted
50
59
  end
51
- end
52
- end
53
60
 
54
- should "decrypt fixed lengths from string stream" do
55
- stream = StringIO.new(@data_encrypted)
56
- i = 0
57
- SymmetricEncryption::Reader.open(stream) do |file|
58
- index = 0
59
- [0,10,5,5000].each do |size|
60
- buf = file.read(size)
61
- if size == 0
62
- assert_equal '', buf
63
- else
64
- assert_equal @data_str[index..index+size-1], buf
61
+ should "decrypt lines from string stream" do
62
+ stream = StringIO.new(@data_encrypted)
63
+ i = 0
64
+ decrypted = SymmetricEncryption::Reader.open(stream) do |file|
65
+ file.each_line do |line|
66
+ assert_equal @data[i], line
67
+ i += 1
68
+ end
69
+ end
70
+ end
71
+
72
+ should "decrypt fixed lengths from string stream" do
73
+ stream = StringIO.new(@data_encrypted)
74
+ i = 0
75
+ SymmetricEncryption::Reader.open(stream) do |file|
76
+ index = 0
77
+ [0,10,5,5000].each do |size|
78
+ buf = file.read(size)
79
+ if size == 0
80
+ assert_equal '', buf
81
+ else
82
+ assert_equal @data_str[index..index+size-1], buf
83
+ end
84
+ index += size
85
+ end
65
86
  end
66
- index += size
67
87
  end
68
88
  end
69
89
  end
70
90
 
71
91
  context "reading from file" do
72
- # With and without header
73
- [{:header => false, :version => 1}, {:header => false, :random_key => false, :version => 1}, {:compress => false}, {:compress => true}, {:random_key => false}].each_with_index do |options, i|
74
- context "with#{'out' unless options[:header]} header #{i}" do
92
+ [
93
+ # No Header
94
+ {:header => false, :random_key => false, :random_iv => false},
95
+ # Default Header with random key and iv
96
+ {},
97
+ # Header with no compression ( default anyway )
98
+ {:compress => false},
99
+ # Compress and use Random key, iv
100
+ {:compress => true},
101
+ # Header but not random key or iv
102
+ {:random_key => false},
103
+ # Random iv only
104
+ {:random_key => false, :random_iv => true},
105
+ # Random iv only with compression
106
+ {:random_iv => true, :compress => true},
107
+ ].each do |options|
108
+ context "with options: #{options.inspect}" do
75
109
  setup do
76
110
  @filename = '._test'
77
111
  # Create encrypted file
@@ -23,25 +23,25 @@ class SymmetricEncryptionTest < Test::Unit::TestCase
23
23
 
24
24
  should "match config file for first cipher" do
25
25
  cipher = SymmetricEncryption.cipher
26
- assert_equal @cipher_v1[:cipher], cipher.cipher
26
+ assert_equal @cipher_v1[:cipher_name], cipher.cipher_name
27
27
  assert_equal @cipher_v1[:version], cipher.version
28
28
  assert_equal false, SymmetricEncryption.secondary_ciphers.include?(cipher)
29
29
  end
30
30
 
31
31
  should "match config file for v1 cipher" do
32
32
  cipher = SymmetricEncryption.cipher(1)
33
- assert @cipher_v1[:cipher]
33
+ assert @cipher_v1[:cipher_name]
34
34
  assert @cipher_v1[:version]
35
- assert_equal @cipher_v1[:cipher], cipher.cipher
35
+ assert_equal @cipher_v1[:cipher_name], cipher.cipher_name
36
36
  assert_equal @cipher_v1[:version], cipher.version
37
37
  assert_equal false, SymmetricEncryption.secondary_ciphers.include?(cipher)
38
38
  end
39
39
 
40
40
  should "match config file for v0 cipher" do
41
41
  cipher = SymmetricEncryption.cipher(0)
42
- assert @cipher_v0[:cipher]
42
+ assert @cipher_v0[:cipher_name]
43
43
  assert @cipher_v0[:version]
44
- assert_equal @cipher_v0[:cipher], cipher.cipher
44
+ assert_equal @cipher_v0[:cipher_name], cipher.cipher_name
45
45
  assert_equal @cipher_v0[:version], cipher.version
46
46
  assert_equal true, SymmetricEncryption.secondary_ciphers.include?(cipher)
47
47
  end
@@ -95,6 +95,26 @@ class SymmetricEncryptionTest < Test::Unit::TestCase
95
95
  end
96
96
  end
97
97
 
98
+ context "random iv" do
99
+ setup do
100
+ @social_security_number = "987654321"
101
+ end
102
+
103
+ should "encrypt and then decrypt using random iv" do
104
+ # Encrypt with random iv
105
+ assert encrypted = SymmetricEncryption.encrypt(@social_security_number, true)
106
+ assert_equal true, SymmetricEncryption.encrypted?(encrypted)
107
+ assert_equal @social_security_number, SymmetricEncryption.decrypt(encrypted)
108
+ end
109
+
110
+ should "encrypt and then decrypt using random iv" do
111
+ # Encrypt with random iv and compress
112
+ assert encrypted = SymmetricEncryption.encrypt(@social_security_number, true, true)
113
+ assert_equal true, SymmetricEncryption.encrypted?(encrypted)
114
+ assert_equal @social_security_number, SymmetricEncryption.decrypt(encrypted)
115
+ end
116
+ end
117
+
98
118
  end
99
119
 
100
120
  end
data/test/test_db.sqlite3 CHANGED
Binary file
data/test/writer_test.rb CHANGED
@@ -22,7 +22,7 @@ class WriterTest < Test::Unit::TestCase
22
22
  ]
23
23
  @data_str = @data.inject('') {|sum,str| sum << str}
24
24
  @data_len = @data_str.length
25
- @data_encrypted = SymmetricEncryption.cipher.encrypt(@data_str, false)
25
+ @data_encrypted = SymmetricEncryption.cipher.binary_encrypt(@data_str, false, false)
26
26
  @filename = '._test'
27
27
  end
28
28
 
@@ -32,7 +32,7 @@ class WriterTest < Test::Unit::TestCase
32
32
 
33
33
  should "encrypt to string stream" do
34
34
  stream = StringIO.new
35
- file = SymmetricEncryption::Writer.new(stream, :header => false, :random_key => false)
35
+ file = SymmetricEncryption::Writer.new(stream, :header => false, :random_key => false, :random_iv => false)
36
36
  written_len = @data.inject(0) {|sum,str| sum + file.write(str)}
37
37
  file.close
38
38
 
@@ -53,7 +53,7 @@ class WriterTest < Test::Unit::TestCase
53
53
 
54
54
  should "encrypt to file using .open" do
55
55
  written_len = nil
56
- SymmetricEncryption::Writer.open(@filename, :header => false, :random_key => false) do |file|
56
+ SymmetricEncryption::Writer.open(@filename, :header => false, :random_key => false, :random_iv => false) do |file|
57
57
  written_len = @data.inject(0) {|sum,str| sum + file.write(str)}
58
58
  end
59
59
  assert_equal @data_len, written_len
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: symmetric-encryption
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-11 00:00:00.000000000 Z
11
+ date: 2013-04-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: SymmetricEncryption supports encrypting ActiveRecord data, Mongoid data,
14
14
  passwords in configuration files, encrypting and decrypting of large files through