symmetric-encryption 2.0.0 → 2.0.1
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +24 -24
- data/README.md +10 -0
- data/lib/symmetric_encryption/cipher.rb +3 -3
- data/lib/symmetric_encryption/extensions/mongoid/fields.rb +2 -2
- data/lib/symmetric_encryption/reader.rb +41 -13
- data/lib/symmetric_encryption/version.rb +1 -1
- data/lib/symmetric_encryption/writer.rb +19 -16
- data/nbproject/private/private.xml +1 -14
- data/test/cipher_test.rb +1 -1
- data/{nbproject/private/config.properties → test/config/empty.csv} +0 -0
- data/test/reader_test.rb +128 -33
- data/test/symmetric_encryption_test.rb +1 -1
- data/test/test_db.sqlite3 +0 -0
- data/test/writer_test.rb +3 -0
- metadata +4 -6
- data/nbproject/private/private.properties +0 -3
- data/test.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 231447a49387dc528e881059bf00023b1103cd42
|
4
|
+
data.tar.gz: 6d3e9212d2925e2e93aa62d1e7ec998ca79992c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b824fdb557f6df9b9354e3706a6da0e3c04a9754f0b231c0ef1233e1423057bf0fb94ba1ceb4643bea3dec95b0cf595e85fc19f023b94585d8764a7c81b617a
|
7
|
+
data.tar.gz: e602a1f3d44bec6575d43f69d975a6764d73faba374cb2b744c5e1aaa2744fda7bec2d028a9a525128f5e2fb0b3390b4256b2916d3b98faa6aad63a5565bd962
|
data/Gemfile.lock
CHANGED
@@ -1,42 +1,42 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
activemodel (3.2.
|
5
|
-
activesupport (= 3.2.
|
4
|
+
activemodel (3.2.13)
|
5
|
+
activesupport (= 3.2.13)
|
6
6
|
builder (~> 3.0.0)
|
7
|
-
activerecord (3.2.
|
8
|
-
activemodel (= 3.2.
|
9
|
-
activesupport (= 3.2.
|
7
|
+
activerecord (3.2.13)
|
8
|
+
activemodel (= 3.2.13)
|
9
|
+
activesupport (= 3.2.13)
|
10
10
|
arel (~> 3.0.2)
|
11
11
|
tzinfo (~> 0.3.29)
|
12
|
-
activesupport (3.2.
|
13
|
-
i18n (
|
12
|
+
activesupport (3.2.13)
|
13
|
+
i18n (= 0.6.1)
|
14
14
|
multi_json (~> 1.0)
|
15
15
|
arel (3.0.2)
|
16
|
-
bourne (1.
|
17
|
-
mocha (
|
16
|
+
bourne (1.4.0)
|
17
|
+
mocha (~> 0.13.2)
|
18
18
|
builder (3.0.4)
|
19
19
|
i18n (0.6.1)
|
20
20
|
metaclass (0.0.1)
|
21
|
-
mocha (0.
|
21
|
+
mocha (0.13.3)
|
22
22
|
metaclass (~> 0.0.1)
|
23
|
-
mongoid (3.
|
24
|
-
activemodel (~> 3.
|
25
|
-
moped (~> 1.
|
23
|
+
mongoid (3.1.3)
|
24
|
+
activemodel (~> 3.2)
|
25
|
+
moped (~> 1.4.2)
|
26
26
|
origin (~> 1.0)
|
27
27
|
tzinfo (~> 0.3.22)
|
28
|
-
moped (1.
|
29
|
-
multi_json (1.
|
30
|
-
origin (1.0.
|
31
|
-
shoulda (3.
|
32
|
-
shoulda-context (~> 1.0.1)
|
33
|
-
shoulda-matchers (~> 1.4.1)
|
34
|
-
shoulda-context (1.
|
35
|
-
shoulda-matchers (1.
|
28
|
+
moped (1.4.5)
|
29
|
+
multi_json (1.7.2)
|
30
|
+
origin (1.0.11)
|
31
|
+
shoulda (3.4.0)
|
32
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
33
|
+
shoulda-matchers (~> 1.0, >= 1.4.1)
|
34
|
+
shoulda-context (1.1.1)
|
35
|
+
shoulda-matchers (1.5.6)
|
36
36
|
activesupport (>= 3.0.0)
|
37
|
-
bourne (~> 1.
|
38
|
-
sqlite3 (1.3.
|
39
|
-
tzinfo (0.3.
|
37
|
+
bourne (~> 1.3)
|
38
|
+
sqlite3 (1.3.7)
|
39
|
+
tzinfo (0.3.37)
|
40
40
|
|
41
41
|
PLATFORMS
|
42
42
|
ruby
|
data/README.md
CHANGED
@@ -122,6 +122,15 @@ class User < ActiveRecord::Base
|
|
122
122
|
# Requires table users to have a column called encrypted_social_security_number
|
123
123
|
attr_encrypted :social_security_number
|
124
124
|
|
125
|
+
# Since string and long_string are not used in the where clause of any SQL
|
126
|
+
# queries it is better to ensure that the encrypted value is always different
|
127
|
+
# by encrypting every value with a random Initialization Vector.
|
128
|
+
attr_encrypted :string, :random_iv => true
|
129
|
+
|
130
|
+
# Long encrypted strings can also be compressed prior to encryption to save
|
131
|
+
# disk space
|
132
|
+
attr_encrypted :long_string, :random_iv => true, :compress => true
|
133
|
+
|
125
134
|
validates :encrypted_bank_account_number, :symmetric_encryption => true
|
126
135
|
validates :encrypted_social_security_number, :symmetric_encryption => true
|
127
136
|
end
|
@@ -151,6 +160,7 @@ class User
|
|
151
160
|
field :name, :type => String
|
152
161
|
field :encrypted_bank_account_number, :type => String, :encrypted => true
|
153
162
|
field :encrypted_social_security_number, :type => String, :encrypted => true
|
163
|
+
field :encrypted_life_history, :type => String, :encrypted => true, :compress => true, :random_iv => true
|
154
164
|
end
|
155
165
|
|
156
166
|
# Create a new user document
|
@@ -215,8 +215,8 @@ module SymmetricEncryption
|
|
215
215
|
# default_compressed
|
216
216
|
# If no header is present, this is the default value for the compression
|
217
217
|
def self.parse_magic_header!(buffer, default_version=nil, default_compressed=false)
|
218
|
-
buffer.force_encoding(SymmetricEncryption::BINARY_ENCODING)
|
219
|
-
return [default_compressed, nil, nil, nil, SymmetricEncryption.cipher(default_version)] unless buffer.start_with?(MAGIC_HEADER)
|
218
|
+
buffer.force_encoding(SymmetricEncryption::BINARY_ENCODING) if buffer
|
219
|
+
return [default_compressed, nil, nil, nil, nil, SymmetricEncryption.cipher(default_version)] unless buffer && buffer.start_with?(MAGIC_HEADER)
|
220
220
|
|
221
221
|
# Header includes magic header and version byte
|
222
222
|
# Remove header and extract flags
|
@@ -245,7 +245,7 @@ module SymmetricEncryption
|
|
245
245
|
cipher_name = buffer.slice!(0..len-1)
|
246
246
|
end
|
247
247
|
|
248
|
-
[compressed, iv, key, cipher_name, decryption_cipher]
|
248
|
+
[compressed, iv, key, cipher_name, version, decryption_cipher]
|
249
249
|
end
|
250
250
|
|
251
251
|
# Returns a magic header for this cipher instance that can be placed at
|
@@ -25,8 +25,7 @@ module Mongoid
|
|
25
25
|
# field :name, :type => String
|
26
26
|
# field :encrypted_social_security_number, :type => String, :encrypted => true
|
27
27
|
# field :age, :type => Integer
|
28
|
-
# field :
|
29
|
-
#
|
28
|
+
# field :encrypted_life_history, :type => String, :encrypted => true, :compress => true, :random_iv => true
|
30
29
|
# end
|
31
30
|
#
|
32
31
|
# The above document results in the following document in the Mongo collection 'persons':
|
@@ -34,6 +33,7 @@ module Mongoid
|
|
34
33
|
# "name" : "Joe",
|
35
34
|
# "encrypted_social_security_number" : "...",
|
36
35
|
# "age" : 21
|
36
|
+
# "encrypted_life_history" : "...",
|
37
37
|
# }
|
38
38
|
#
|
39
39
|
# Symmetric Encryption creates the getters and setters to be able to work with the field
|
@@ -22,8 +22,7 @@ module SymmetricEncryption
|
|
22
22
|
#
|
23
23
|
# :buffer_size
|
24
24
|
# Amount of data to read at a time
|
25
|
-
#
|
26
|
-
# magic header if one is present
|
25
|
+
# Minimum Value 128
|
27
26
|
# Default: 4096
|
28
27
|
#
|
29
28
|
# The following options are only used if the stream/file has no header
|
@@ -85,18 +84,39 @@ module SymmetricEncryption
|
|
85
84
|
|
86
85
|
begin
|
87
86
|
file = self.new(ios, options)
|
88
|
-
file = Zlib::GzipReader.new(file) if file.compressed? || compress
|
87
|
+
file = Zlib::GzipReader.new(file) if !file.eof? && (file.compressed? || compress)
|
89
88
|
block ? block.call(file) : file
|
90
89
|
ensure
|
91
90
|
file.close if block && file
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
94
|
+
# Returns [true|false] whether the file or stream contains any data
|
95
|
+
# excluding the header should it have one
|
96
|
+
def self.empty?(filename_or_stream)
|
97
|
+
open(filename_or_stream) {|file| file.eof? }
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns [true|false] whether the file contains the encryption header
|
101
|
+
def self.header_present?(filename)
|
102
|
+
::File.open(filename, 'rb') {|file| new(file).header_present?}
|
103
|
+
end
|
104
|
+
|
105
|
+
# After opening a file Returns [true|false] whether the file being
|
106
|
+
# read has an encryption header
|
107
|
+
def header_present?
|
108
|
+
@header_present
|
109
|
+
end
|
110
|
+
|
95
111
|
# Decrypt data before reading from the supplied stream
|
96
112
|
def initialize(ios,options={})
|
97
|
-
@ios
|
98
|
-
@buffer_size
|
99
|
-
@version
|
113
|
+
@ios = ios
|
114
|
+
@buffer_size = options.fetch(:buffer_size, 4096).to_i
|
115
|
+
@version = options[:version]
|
116
|
+
@header_present = false
|
117
|
+
|
118
|
+
raise "Buffer size cannot be smaller than 128" unless @buffer_size >= 128
|
119
|
+
|
100
120
|
read_header
|
101
121
|
end
|
102
122
|
|
@@ -154,11 +174,13 @@ module SymmetricEncryption
|
|
154
174
|
# Reads at most length bytes from the I/O stream, or to the end of file if
|
155
175
|
# length is omitted or is nil. length must be a non-negative integer or nil.
|
156
176
|
#
|
157
|
-
# At end of file, it returns nil
|
177
|
+
# At end of file, it returns nil if no more data is available, or the last
|
178
|
+
# remaining bytes
|
158
179
|
def read(length=nil)
|
159
180
|
data = nil
|
160
181
|
if length
|
161
182
|
return '' if length == 0
|
183
|
+
return nil if @ios.eof? && (@read_buffer.length == 0)
|
162
184
|
# Read length bytes
|
163
185
|
while (@read_buffer.length < length) && !@ios.eof?
|
164
186
|
read_block
|
@@ -196,11 +218,12 @@ module SymmetricEncryption
|
|
196
218
|
# A sep_string of nil reads the entire contents of the file
|
197
219
|
# Returns nil on eof
|
198
220
|
# The stream must be opened for reading or an IOError will be raised.
|
199
|
-
def gets(sep_string)
|
200
|
-
return read if sep_string.nil?
|
221
|
+
def gets(sep_string,length=nil)
|
222
|
+
return read(length) if sep_string.nil?
|
201
223
|
|
202
224
|
# Read more data until we get the sep_string
|
203
225
|
while (index = @read_buffer.index(sep_string)).nil? && !@ios.eof?
|
226
|
+
break if length && @read_buffer.length >= length
|
204
227
|
read_block
|
205
228
|
end
|
206
229
|
index ||= -1
|
@@ -288,14 +311,15 @@ module SymmetricEncryption
|
|
288
311
|
|
289
312
|
# Read the header from the file if present
|
290
313
|
def read_header
|
291
|
-
@compressed
|
314
|
+
@compressed = nil
|
292
315
|
@pos = 0
|
293
316
|
|
294
317
|
# Read first block and check for the header
|
295
318
|
buf = @ios.read(@buffer_size)
|
296
319
|
|
297
320
|
# Use cipher specified in header, or global cipher if it has no header
|
298
|
-
@compressed, iv, key, cipher_name, decryption_cipher = SymmetricEncryption::Cipher.parse_magic_header!(buf, @version)
|
321
|
+
@compressed, iv, key, cipher_name, version, decryption_cipher = SymmetricEncryption::Cipher.parse_magic_header!(buf, @version)
|
322
|
+
@header_present = true if iv || key || version
|
299
323
|
|
300
324
|
@stream_cipher = ::OpenSSL::Cipher.new(cipher_name || decryption_cipher.cipher_name)
|
301
325
|
@stream_cipher.decrypt
|
@@ -303,8 +327,12 @@ module SymmetricEncryption
|
|
303
327
|
@stream_cipher.iv = iv || decryption_cipher.send(:iv)
|
304
328
|
|
305
329
|
# First call to #update should return an empty string anyway
|
306
|
-
|
307
|
-
|
330
|
+
if buf && buf.length > 0
|
331
|
+
@read_buffer = @stream_cipher.update(buf)
|
332
|
+
@read_buffer << @stream_cipher.final if @ios.eof?
|
333
|
+
else
|
334
|
+
@read_buffer = ''
|
335
|
+
end
|
308
336
|
end
|
309
337
|
|
310
338
|
# Read a block of data and append the decrypted data in the read buffer
|
@@ -129,19 +129,11 @@ module SymmetricEncryption
|
|
129
129
|
# Force header if compressed or using random iv, key
|
130
130
|
header = true if compress || random_key || random_iv
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
version = SymmetricEncryption.cipher.version
|
136
|
-
else
|
137
|
-
# Use global key if a new random one is not being generated
|
138
|
-
cipher = SymmetricEncryption.cipher(version)
|
139
|
-
raise "Cipher with version:#{version} not found in any of the configured SymmetricEncryption ciphers" unless cipher
|
140
|
-
# Version of key used to encrypt the data
|
141
|
-
version = cipher.version
|
142
|
-
end
|
132
|
+
# Cipher to encrypt the random_key, or the entire file
|
133
|
+
cipher = SymmetricEncryption.cipher(version)
|
134
|
+
raise "Cipher with version:#{version} not found in any of the configured SymmetricEncryption ciphers" unless cipher
|
143
135
|
|
144
|
-
@stream_cipher = ::OpenSSL::Cipher.new(cipher_name ||
|
136
|
+
@stream_cipher = ::OpenSSL::Cipher.new(cipher_name || cipher.cipher_name)
|
145
137
|
@stream_cipher.encrypt
|
146
138
|
|
147
139
|
key = random_key ? @stream_cipher.random_key : cipher.send(:key)
|
@@ -153,12 +145,13 @@ module SymmetricEncryption
|
|
153
145
|
# Write the Encryption header including the random iv, key, and cipher
|
154
146
|
if header
|
155
147
|
@ios.write(Cipher.magic_header(
|
156
|
-
version,
|
148
|
+
cipher.version,
|
157
149
|
compress,
|
158
150
|
random_iv ? iv : nil,
|
159
151
|
random_key ? key : nil,
|
160
152
|
cipher_name))
|
161
153
|
end
|
154
|
+
@size = 0
|
162
155
|
end
|
163
156
|
|
164
157
|
# Close the IO Stream
|
@@ -174,15 +167,21 @@ module SymmetricEncryption
|
|
174
167
|
# rather than creating an instance of Symmetric::EncryptedStream directly to
|
175
168
|
# ensure that the encrypted stream is closed before the stream itself is closed
|
176
169
|
def close(close_child_stream = true)
|
177
|
-
|
178
|
-
|
170
|
+
if size > 0
|
171
|
+
final = @stream_cipher.final
|
172
|
+
@ios.write(final) if final.length > 0
|
173
|
+
end
|
179
174
|
@ios.close if close_child_stream
|
180
175
|
end
|
181
176
|
|
182
177
|
# Write to the IO Stream as encrypted data
|
183
178
|
# Returns the number of bytes written
|
184
179
|
def write(data)
|
185
|
-
|
180
|
+
return unless data
|
181
|
+
|
182
|
+
bytes = data.to_s
|
183
|
+
@size += bytes.size
|
184
|
+
partial = @stream_cipher.update(bytes)
|
186
185
|
@ios.write(partial) if partial.length > 0
|
187
186
|
data.length
|
188
187
|
end
|
@@ -205,5 +204,9 @@ module SymmetricEncryption
|
|
205
204
|
@ios.flush
|
206
205
|
end
|
207
206
|
|
207
|
+
# Returns [Integer] the number of unencrypted and uncompressed bytes
|
208
|
+
# written to the file so far
|
209
|
+
attr_reader :size
|
210
|
+
|
208
211
|
end
|
209
212
|
end
|
@@ -1,17 +1,4 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
3
|
-
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/
|
4
|
-
<file>
|
5
|
-
<url>lib/symmetric/encryption.rb</url>
|
6
|
-
<line>62</line>
|
7
|
-
</file>
|
8
|
-
<file>
|
9
|
-
<url>lib/symmetric_encryption/encryption.rb</url>
|
10
|
-
<line>60</line>
|
11
|
-
</file>
|
12
|
-
<file>
|
13
|
-
<url>lib/symmetric_encryption/symmetric_encryption.rb</url>
|
14
|
-
<line>76</line>
|
15
|
-
</file>
|
16
|
-
</editor-bookmarks>
|
3
|
+
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
17
4
|
</project-private>
|
data/test/cipher_test.rb
CHANGED
@@ -98,7 +98,7 @@ class CipherTest < Test::Unit::TestCase
|
|
98
98
|
should "create and parse magic header" do
|
99
99
|
random_cipher = SymmetricEncryption::Cipher.new(SymmetricEncryption::Cipher.random_key_pair)
|
100
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)
|
101
|
+
compressed, iv, key, cipher_name, version, decryption_cipher = SymmetricEncryption::Cipher.parse_magic_header!(header)
|
102
102
|
assert_equal true, compressed
|
103
103
|
assert_equal random_cipher.cipher_name, cipher_name, "Ciphers differ"
|
104
104
|
assert_equal random_cipher.send(:key), key, "Keys differ"
|
File without changes
|
data/test/reader_test.rb
CHANGED
@@ -43,13 +43,13 @@ class ReaderTest < Test::Unit::TestCase
|
|
43
43
|
@data_encrypted = header ? @data_encrypted_with_header : @data_encrypted_without_header
|
44
44
|
end
|
45
45
|
|
46
|
-
should "
|
46
|
+
should "#read()" do
|
47
47
|
stream = StringIO.new(@data_encrypted)
|
48
48
|
decrypted = SymmetricEncryption::Reader.open(stream) {|file| file.read}
|
49
49
|
assert_equal @data_str, decrypted
|
50
50
|
end
|
51
51
|
|
52
|
-
should "
|
52
|
+
should "#read(size) followed by #read()" do
|
53
53
|
stream = StringIO.new(@data_encrypted)
|
54
54
|
decrypted = SymmetricEncryption::Reader.open(stream) do |file|
|
55
55
|
file.read(10)
|
@@ -58,7 +58,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
58
58
|
assert_equal @data_str[10..-1], decrypted
|
59
59
|
end
|
60
60
|
|
61
|
-
should "
|
61
|
+
should "#each_line" do
|
62
62
|
stream = StringIO.new(@data_encrypted)
|
63
63
|
i = 0
|
64
64
|
decrypted = SymmetricEncryption::Reader.open(stream) do |file|
|
@@ -69,7 +69,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
should "
|
72
|
+
should "#read(size)" do
|
73
73
|
stream = StringIO.new(@data_encrypted)
|
74
74
|
i = 0
|
75
75
|
SymmetricEncryption::Reader.open(stream) do |file|
|
@@ -88,42 +88,105 @@ class ReaderTest < Test::Unit::TestCase
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
91
|
+
[
|
92
|
+
# No Header
|
93
|
+
{:header => false, :random_key => false, :random_iv => false},
|
94
|
+
# Default Header with random key and iv
|
95
|
+
{},
|
96
|
+
# Header with no compression ( default anyway )
|
97
|
+
{:compress => false},
|
98
|
+
# Compress and use Random key, iv
|
99
|
+
{:compress => true},
|
100
|
+
# Header but not random key or iv
|
101
|
+
{:random_key => false},
|
102
|
+
# Random iv only
|
103
|
+
{:random_key => false, :random_iv => true},
|
104
|
+
# Random iv only with compression
|
105
|
+
{:random_iv => true, :compress => true},
|
106
|
+
].each do |options|
|
107
|
+
|
108
|
+
[:data, :empty, :blank].each do |usecase|
|
109
|
+
|
110
|
+
context "read from #{usecase} file with options: #{options.inspect}" do
|
109
111
|
setup do
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
@
|
112
|
+
case usecase
|
113
|
+
when :data
|
114
|
+
# Create encrypted file
|
115
|
+
@eof = false
|
116
|
+
@filename = '._test'
|
117
|
+
@header = (options[:header] != false)
|
118
|
+
SymmetricEncryption::Writer.open(@filename, options) do |file|
|
119
|
+
@data.inject(0) {|sum,str| sum + file.write(str)}
|
120
|
+
end
|
121
|
+
when :empty
|
122
|
+
@data_str = ''
|
123
|
+
@eof = true
|
124
|
+
@filename = '._test_empty'
|
125
|
+
@header = (options[:header] != false)
|
126
|
+
SymmetricEncryption::Writer.open(@filename, options) do |file|
|
127
|
+
# Leave data portion empty
|
128
|
+
end
|
129
|
+
when :blank
|
130
|
+
@data_str = ''
|
131
|
+
@eof = true
|
132
|
+
@filename = File.join(File.dirname(__FILE__), 'config/empty.csv')
|
133
|
+
@header = false
|
134
|
+
assert_equal 0, File.size(@filename)
|
135
|
+
else
|
136
|
+
raise "Unhandled usecase: #{usecase}"
|
114
137
|
end
|
138
|
+
@data_size = @data_str.length
|
115
139
|
end
|
116
140
|
|
117
141
|
teardown do
|
118
|
-
File.delete(@filename) if File.exist?(@filename)
|
142
|
+
File.delete(@filename) if File.exist?(@filename) && !@filename.end_with?('empty.csv')
|
119
143
|
end
|
120
144
|
|
121
|
-
should "
|
122
|
-
|
123
|
-
|
145
|
+
should ".empty?" do
|
146
|
+
assert_equal (@data_size==0), SymmetricEncryption::Reader.empty?(@filename)
|
147
|
+
assert_raise Errno::ENOENT do
|
148
|
+
SymmetricEncryption::Reader.empty?('missing_file')
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
should ".header_present?" do
|
153
|
+
assert_equal @header, SymmetricEncryption::Reader.header_present?(@filename)
|
154
|
+
assert_raise Errno::ENOENT do
|
155
|
+
SymmetricEncryption::Reader.header_present?('missing_file')
|
156
|
+
end
|
124
157
|
end
|
125
158
|
|
126
|
-
should "
|
159
|
+
should ".open return Zlib::GzipReader when compressed" do
|
160
|
+
file = SymmetricEncryption::Reader.open(@filename)
|
161
|
+
#assert_equal (@header && (options[:compress]||false)), file.is_a?(Zlib::GzipReader)
|
162
|
+
file.close
|
163
|
+
end
|
164
|
+
|
165
|
+
should "#read()" do
|
166
|
+
data = nil
|
167
|
+
eof = nil
|
168
|
+
result = SymmetricEncryption::Reader.open(@filename) do |file|
|
169
|
+
eof = file.eof?
|
170
|
+
data = file.read
|
171
|
+
end
|
172
|
+
assert_equal @eof, eof
|
173
|
+
assert_equal @data_str, data
|
174
|
+
assert_equal @data_str, result
|
175
|
+
end
|
176
|
+
|
177
|
+
should "#read(size)" do
|
178
|
+
data = nil
|
179
|
+
eof = nil
|
180
|
+
file = SymmetricEncryption::Reader.open(@filename)
|
181
|
+
eof = file.eof?
|
182
|
+
data = file.read(4096)
|
183
|
+
file.close
|
184
|
+
|
185
|
+
assert_equal @eof, eof
|
186
|
+
assert_equal (@data_size > 0 ? @data_str : nil), data
|
187
|
+
end
|
188
|
+
|
189
|
+
should "#each_line" do
|
127
190
|
decrypted = SymmetricEncryption::Reader.open(@filename) do |file|
|
128
191
|
i = 0
|
129
192
|
file.each_line do |line|
|
@@ -133,7 +196,7 @@ class ReaderTest < Test::Unit::TestCase
|
|
133
196
|
end
|
134
197
|
end
|
135
198
|
|
136
|
-
should "
|
199
|
+
should "#rewind" do
|
137
200
|
decrypted = SymmetricEncryption::Reader.open(@filename) do |file|
|
138
201
|
file.read
|
139
202
|
file.rewind
|
@@ -142,9 +205,41 @@ class ReaderTest < Test::Unit::TestCase
|
|
142
205
|
assert_equal @data_str, decrypted
|
143
206
|
end
|
144
207
|
|
208
|
+
should "#gets(nil,size)" do
|
209
|
+
data = nil
|
210
|
+
eof = nil
|
211
|
+
file = SymmetricEncryption::Reader.open(@filename)
|
212
|
+
eof = file.eof?
|
213
|
+
data = file.gets(nil,4096)
|
214
|
+
file.close
|
215
|
+
|
216
|
+
assert_equal @eof, eof
|
217
|
+
assert_equal (@data_size > 0 ? @data_str : nil), data
|
218
|
+
end
|
219
|
+
|
220
|
+
should "#gets(delim)" do
|
221
|
+
decrypted = SymmetricEncryption::Reader.open(@filename) do |file|
|
222
|
+
i = 0
|
223
|
+
while line = file.gets("\n")
|
224
|
+
assert_equal @data[i], line
|
225
|
+
i += 1
|
226
|
+
end
|
227
|
+
assert_equal (@data_size > 0 ? 3 : 0), i
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
should "#gets(delim,size)" do
|
232
|
+
decrypted = SymmetricEncryption::Reader.open(@filename) do |file|
|
233
|
+
i = 0
|
234
|
+
while line = file.gets("\n",128)
|
235
|
+
i += 1
|
236
|
+
end
|
237
|
+
assert_equal (@data_size > 0 ? 3 : 0), i
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
145
241
|
end
|
146
242
|
end
|
147
|
-
|
148
243
|
end
|
149
244
|
|
150
245
|
context "reading from files with previous keys" do
|
@@ -107,7 +107,7 @@ class SymmetricEncryptionTest < Test::Unit::TestCase
|
|
107
107
|
assert_equal @social_security_number, SymmetricEncryption.decrypt(encrypted)
|
108
108
|
end
|
109
109
|
|
110
|
-
should "encrypt and then decrypt using random iv" do
|
110
|
+
should "encrypt and then decrypt using random iv with compression" do
|
111
111
|
# Encrypt with random iv and compress
|
112
112
|
assert encrypted = SymmetricEncryption.encrypt(@social_security_number, true, true)
|
113
113
|
assert_equal true, SymmetricEncryption.encrypted?(encrypted)
|
data/test/test_db.sqlite3
CHANGED
Binary file
|
data/test/writer_test.rb
CHANGED
@@ -34,6 +34,7 @@ class WriterTest < Test::Unit::TestCase
|
|
34
34
|
stream = StringIO.new
|
35
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
|
+
assert_equal @data_len, file.size
|
37
38
|
file.close
|
38
39
|
|
39
40
|
assert_equal @data_len, written_len
|
@@ -47,6 +48,7 @@ class WriterTest < Test::Unit::TestCase
|
|
47
48
|
stream = StringIO.new
|
48
49
|
SymmetricEncryption::Writer.open(stream) do |file|
|
49
50
|
written_len = @data.inject(0) {|sum,str| sum + file.write(str)}
|
51
|
+
assert_equal @data_len, file.size
|
50
52
|
end
|
51
53
|
assert_equal @data_len, written_len
|
52
54
|
end
|
@@ -55,6 +57,7 @@ class WriterTest < Test::Unit::TestCase
|
|
55
57
|
written_len = nil
|
56
58
|
SymmetricEncryption::Writer.open(@filename, :header => false, :random_key => false, :random_iv => false) do |file|
|
57
59
|
written_len = @data.inject(0) {|sum,str| sum + file.write(str)}
|
60
|
+
assert_equal @data_len, file.size
|
58
61
|
end
|
59
62
|
assert_equal @data_len, written_len
|
60
63
|
assert_equal @data_encrypted, File.open(@filename, 'rb') {|f| f.read }
|
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: 2.0.
|
4
|
+
version: 2.0.1
|
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
|
+
date: 2013-04-22 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
|
@@ -40,16 +40,14 @@ files:
|
|
40
40
|
- lib/symmetric_encryption/symmetric_encryption.rb
|
41
41
|
- lib/symmetric_encryption/version.rb
|
42
42
|
- lib/symmetric_encryption/writer.rb
|
43
|
-
- nbproject/private/config.properties
|
44
|
-
- nbproject/private/private.properties
|
45
43
|
- nbproject/private/private.xml
|
46
44
|
- nbproject/private/rake-d.txt
|
47
45
|
- nbproject/project.properties
|
48
46
|
- nbproject/project.xml
|
49
|
-
- test.rb
|
50
47
|
- test/attr_encrypted_test.rb
|
51
48
|
- test/cipher_test.rb
|
52
49
|
- test/config/database.yml
|
50
|
+
- test/config/empty.csv
|
53
51
|
- test/config/mongoid_v2.yml
|
54
52
|
- test/config/mongoid_v3.yml
|
55
53
|
- test/config/symmetric-encryption.yml
|
@@ -82,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
80
|
version: '0'
|
83
81
|
requirements: []
|
84
82
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.0.
|
83
|
+
rubygems_version: 2.0.3
|
86
84
|
signing_key:
|
87
85
|
specification_version: 4
|
88
86
|
summary: Symmetric Encryption for Ruby, and Ruby on Rails
|
data/test.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'openssl'
|
3
|
-
openssl_cipher = ::OpenSSL::Cipher.new('aes-128-cbc')
|
4
|
-
openssl_cipher.encrypt
|
5
|
-
openssl_cipher.key = '1234567890ABCDEF1234567890ABCDEF'
|
6
|
-
result = openssl_cipher.update('Hello World')
|
7
|
-
result << openssl_cipher.final
|
8
|
-
puts result.unpack('H*')
|
9
|
-
|
10
|
-
# jruby 1.7.0.RC1 (1.9.3p203) 2012-09-25 8e849de on Java HotSpot(TM) 64-Bit Server VM 1.6.0_35-b10-428-11M3811 [darwin-x86_64]
|
11
|
-
# => 9dc9ebb434bc421326664c038bb4271d
|
12
|
-
#
|
13
|
-
# ruby 1.8.7 (2012-02-08 patchlevel 358) [universal-darwin12.0]
|
14
|
-
# => b597b74f1de1f19a83d901a6fdb40643
|
15
|
-
#
|
16
|
-
# ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin12.2.0]
|
17
|
-
# => b597b74f1de1f19a83d901a6fdb40643
|
18
|
-
#
|
19
|
-
# jruby 1.6.8 (ruby-1.8.7-p357) (2012-09-18 1772b40) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_35) [darwin-x86_64-java]
|
20
|
-
# => 9dc9ebb434bc421326664c038bb4271d
|
21
|
-
#
|
22
|
-
# jruby 1.6.5 (ruby-1.8.7-p330) (2011-10-25 9dcd388) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_35) [darwin-x86_64-java]
|
23
|
-
# => 9dc9ebb434bc421326664c038bb4271d
|