symmetric-encryption 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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