naoki 1.0.21 → 1.0.22

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ data_secure_enabled: false
2
+ properties_file: IngrianNAE.properties
3
+
4
+ credentials:
5
+ document_store:
6
+ username: username
7
+ password: password
8
+ initialization_vector: "1234567890123456"
9
+ key_name: stg-new-test-key
10
+ account_number:
11
+ username: username
12
+ password: password
13
+ initialization_vector: "1234567890123456"
14
+ key_name: stg-new-test-key
@@ -19,6 +19,8 @@ else
19
19
 
20
20
  require 'ffi'
21
21
 
22
+ #
23
+ # This code is deprecated, please use Naoki::DataSecure moving forward.
22
24
  module DataSecureWrapper
23
25
  extend FFI::Library
24
26
  LIB_ICAPI_FILE = `uname -m`.match(/x86_64/) ? 'libICAPI_64.so' : 'libICAPI_32.so'
@@ -3,34 +3,10 @@
3
3
  # NB: this class is not thread-safe. Create an instance for each thread.
4
4
  module Naoki
5
5
  class DataSecure
6
- @enabled = if File.exist?("config/data_secure.yml")
7
- YAML.load(File.read("config/data_secure.yml"))['data_secure_enabled']
8
- end
9
-
10
- if !(`uname -s`.strip =~ /Linux/ && @enabled)
11
-
12
- def self.init(file); end
13
- def close; end
14
-
15
- def encrypt_stream(input, out)
16
- out.write("ENC")
17
- count = 0
18
- while block = input.read(4096)
19
- count += block.size
20
- out.write(block)
21
- end
22
- [count, count + 3]
23
- end
24
-
25
- def decrypt_stream(input, out)
26
- val = input.read(3)
27
- raise ArgumentError, "Invalid encrypted data (#{val})" if val != 'ENC'
28
- count = IO.copy_stream(input, out)
29
- [count + 3, count]
30
- end
31
6
 
32
- else
7
+ @Linux = `uname -s`.strip =~ /linux/i
33
8
 
9
+ if @Linux
34
10
  require 'ffi'
35
11
  extend FFI::Library
36
12
  LIB_ICAPI_FILE = `uname -m`.match(/x86_64/) ? 'libICAPI_64.so' : 'libICAPI_32.so'
@@ -60,115 +36,206 @@ module Naoki
60
36
  attach_function 'I_C_CryptFinal', [:pointer,:pointer,:pointer,:pointer], :int
61
37
  @blocking = true
62
38
  attach_function 'I_C_CryptUpdate', [:pointer, :pointer, :pointer, :uint, :pointer, :pointer], :int
39
+ end
40
+
41
+ DEFAULTS = {
42
+ 'algorithm' => 'AES/CBC/PKCS5Padding',
43
+ }
44
+
45
+ MAX_SAFENET_BLOCK_SIZE = 31000
46
+ MAX_OUTPUT_BLOCK_SIZE = 32000
63
47
 
64
- DEFAULTS = {
65
- :algorithm => 'AES/CBC/PKCS5Padding',
66
- :key_name => 'stg-new-test-key',
67
- :initialization_vector => '1234567890123456',
68
- }
48
+ def initialize(credential_to_use, data_secure_yml)
49
+ options = data_secure_yml
50
+ credential_to_use = credential_to_use.to_s
51
+ @live = self.class.init(options['data_secure_enabled'], options['properties_file'])
69
52
 
70
- MAX_SAFENET_BLOCK_SIZE = 31000
71
- MAX_OUTPUT_BLOCK_SIZE = 32000
53
+ if live?
54
+ @options = DEFAULTS.merge(data_secure_yml['credentials'][credential_to_use])
72
55
 
73
- def initialize(key_to_use = :account_number, options={})
74
- @options = DEFAULTS.merge(options.symbolize_keys)
75
- #check { I_C_Initialize(I_T_Init_File, @options[:properties_file]) }
76
56
  @session_pointer = FFI::MemoryPointer.new :pointer
77
- check { I_C_OpenSession(@session_pointer, I_T_Auth_Password, @options[:username], @options[:password]) }
57
+ check { I_C_OpenSession(@session_pointer, I_T_Auth_Password, @options['username'], @options['password']) }
78
58
  @cipherspec_pointer = FFI::MemoryPointer.new :pointer
79
- check { I_C_CreateCipherSpec(@options[:algorithm], @options[:keys][key_to_use.to_s], @cipherspec_pointer) }
59
+ check { I_C_CreateCipherSpec(@options['algorithm'], @options['key_name'], @cipherspec_pointer) }
80
60
  end
61
+ end
81
62
 
82
- def self.init(file)
83
- check { I_C_Initialize(I_T_Init_File, file) }
84
- end
63
+ def self.init(enabled, file)
64
+ return false unless file && enabled && @Linux
65
+ return true if @initialized
66
+ check { I_C_Initialize(I_T_Init_File, file) }
67
+ @initialized = true
68
+ true
69
+ end
85
70
 
86
- def close
87
- I_C_CloseSession(@session_pointer.get_pointer(0)) if @session_pointer
88
- end
71
+ def close
72
+ return unless live?
73
+ check { I_C_DeleteCipherSpec(@cipherspec_pointer.get_pointer(0)) } if @cipherspec_pointer
74
+ @cipherspec_pointer = nil
75
+ I_C_CloseSession(@session_pointer.get_pointer(0)) if @session_pointer
76
+ @session_pointer = nil
77
+ end
89
78
 
90
- def encrypt_stream(input_io, output_io)
91
- transform_stream(I_T_Operation_Encrypt, input_io, output_io)
92
- end
79
+ def encrypt_stream(input_io, output_io)
80
+ return dummy_encrypt_stream(input_io, output_io) unless live?
81
+ transform_stream(I_T_Operation_Encrypt, input_io, output_io)
82
+ end
93
83
 
94
- def decrypt_stream(input_io, output_io)
95
- transform_stream(I_T_Operation_Decrypt, input_io, output_io)
96
- end
84
+ def decrypt_stream(input_io, output_io)
85
+ return dummy_decrypt_stream(input_io, output_io) unless live?
86
+ transform_stream(I_T_Operation_Decrypt, input_io, output_io)
87
+ end
97
88
 
98
- private
89
+ def encrypt(plain_text)
90
+ return dummy_encrypt(plain_text) unless live?
91
+ transform(I_T_Operation_Encrypt, plain_text) do |transform_data_length_pointer|
92
+ check do
93
+ I_C_CalculateEncipheredSizeForKey(
94
+ @session_pointer.get_pointer(0),
95
+ @cipherspec_pointer.get_pointer(0),
96
+ I_T_Operation_Encrypt,
97
+ plain_text.length,
98
+ transform_data_length_pointer)
99
+ end
100
+ end
101
+ end
99
102
 
100
- def transform_stream(op, input_io, output_io)
101
- current_state = FFI::MemoryPointer.new :pointer
103
+ def decrypt(text)
104
+ return dummy_decrypt(text) unless live?
105
+ transform(I_T_Operation_Decrypt, text) do |transform_data_length_pointer|
102
106
  check do
103
- I_C_CryptInit(
107
+ I_C_CalculateOutputSizeForKey(
104
108
  @session_pointer.get_pointer(0),
105
109
  @cipherspec_pointer.get_pointer(0),
106
- op,
107
- @options[:initialization_vector],
108
- @options[:initialization_vector].length,
109
- current_state)
110
+ I_T_Operation_Decrypt,
111
+ text.length,
112
+ transform_data_length_pointer)
110
113
  end
114
+ end
115
+ end
111
116
 
112
- done = false
113
- read_size = 0
114
- wrote_size = 0
115
- output_data = FFI::MemoryPointer.new :pointer, MAX_OUTPUT_BLOCK_SIZE
116
- output_data_length_pointer = FFI::MemoryPointer.new :pointer
117
-
118
- loop do
119
- output_data_length_pointer.write_uint(MAX_OUTPUT_BLOCK_SIZE)
120
-
121
- data = input_io.read(MAX_SAFENET_BLOCK_SIZE)
122
- if !data || data.size == 0
123
-
124
- check do
125
- I_C_CryptFinal(
126
- @session_pointer.get_pointer(0),
127
- current_state.get_pointer(0),
128
- output_data,
129
- output_data_length_pointer)
130
- end
131
- done = true
132
-
133
- elsif data.size <= MAX_SAFENET_BLOCK_SIZE
134
- read_size += data.size
135
- check do
136
- I_C_CryptUpdate(
137
- @session_pointer.get_pointer(0),
138
- current_state.get_pointer(0),
139
- data,
140
- data.size,
141
- output_data,
142
- output_data_length_pointer)
143
- end
144
-
145
- else
146
- raise "DataSecure, how did we get here? #{data}"
147
- end
117
+ private
148
118
 
149
- outsize = output_data_length_pointer.read_uint
150
- enc_data = output_data.get_bytes(0, outsize)
151
- wrote_size += output_io.write(enc_data)
152
- break if done
153
- end
119
+ def live?
120
+ @live
121
+ end
122
+
123
+ def dummy_encrypt(input)
124
+ "encrypted string"
125
+ end
126
+
127
+ def dummy_decrypt(input)
128
+ "decrypted string"
129
+ end
130
+
131
+ def dummy_encrypt_stream(input, out)
132
+ out.write("ENC")
133
+ count = 0
134
+ while block = input.read(4096)
135
+ count += block.size
136
+ out.write(block)
137
+ end
138
+ [count, count + 3]
139
+ end
140
+
141
+ def dummy_decrypt_stream(input, out)
142
+ val = input.read(3)
143
+ raise ArgumentError, "Invalid encrypted data (#{val})" if val != 'ENC'
144
+ count = IO.copy_stream(input, out)
145
+ [count + 3, count]
146
+ end
147
+
148
+ def transform(op, text)
149
+ yield(transform_data_length_pointer = FFI::MemoryPointer.new(:uint))
150
+
151
+ transform_data = FFI::MemoryPointer.new :char, transform_data_length_pointer.read_uint
154
152
 
155
- [read_size, wrote_size]
153
+ check { I_C_Crypt(
154
+ @session_pointer.get_pointer(0),
155
+ @cipherspec_pointer.get_pointer(0),
156
+ op,
157
+ @options['initialization_vector'],
158
+ @options['initialization_vector'].length,
159
+ text,
160
+ text.length,
161
+ transform_data,
162
+ transform_data_length_pointer
163
+ ) }
164
+
165
+ transform_data.read_string(transform_data_length_pointer.read_uint)
166
+ end
167
+
168
+ def transform_stream(op, input_io, output_io)
169
+ current_state = FFI::MemoryPointer.new :pointer
170
+ check do
171
+ I_C_CryptInit(
172
+ @session_pointer.get_pointer(0),
173
+ @cipherspec_pointer.get_pointer(0),
174
+ op,
175
+ @options['initialization_vector'],
176
+ @options['initialization_vector'].length,
177
+ current_state)
156
178
  end
157
179
 
158
- def check
159
- return_code = yield
160
- if return_code != I_E_OK
161
- I_C_DeleteCipherSpec(@cipherspec_pointer.get_pointer(0)) if @cipherspec_pointer
162
- @cipherspec_pointer = nil
163
- raise I_C_GetErrorString(return_code)
180
+ done = false
181
+ read_size = 0
182
+ wrote_size = 0
183
+ output_data = FFI::MemoryPointer.new :pointer, MAX_OUTPUT_BLOCK_SIZE
184
+ output_data_length_pointer = FFI::MemoryPointer.new :pointer
185
+
186
+ loop do
187
+ output_data_length_pointer.write_uint(MAX_OUTPUT_BLOCK_SIZE)
188
+
189
+ data = input_io.read(MAX_SAFENET_BLOCK_SIZE)
190
+ if !data || data.size == 0
191
+
192
+ check do
193
+ I_C_CryptFinal(
194
+ @session_pointer.get_pointer(0),
195
+ current_state.get_pointer(0),
196
+ output_data,
197
+ output_data_length_pointer)
198
+ end
199
+ done = true
200
+
201
+ elsif data.size <= MAX_SAFENET_BLOCK_SIZE
202
+ read_size += data.size
203
+ check do
204
+ I_C_CryptUpdate(
205
+ @session_pointer.get_pointer(0),
206
+ current_state.get_pointer(0),
207
+ data,
208
+ data.size,
209
+ output_data,
210
+ output_data_length_pointer)
211
+ end
212
+
213
+ else
214
+ raise "DataSecure, how did we get here? #{data}"
164
215
  end
216
+
217
+ outsize = output_data_length_pointer.read_uint
218
+ enc_data = output_data.get_bytes(0, outsize)
219
+ wrote_size += output_io.write(enc_data)
220
+ break if done
165
221
  end
166
222
 
167
- def self.check(&block)
168
- return_code = yield
169
- raise I_C_GetErrorString(return_code) if return_code != I_E_OK
223
+ [read_size, wrote_size]
224
+ end
225
+
226
+ def check
227
+ return_code = yield
228
+ if return_code != I_E_OK
229
+ I_C_DeleteCipherSpec(@cipherspec_pointer.get_pointer(0)) if @cipherspec_pointer
230
+ @cipherspec_pointer = nil
231
+ raise I_C_GetErrorString(return_code)
170
232
  end
233
+ end
171
234
 
235
+ def self.check(&block)
236
+ return_code = yield
237
+ raise I_C_GetErrorString(return_code) if return_code != I_E_OK
172
238
  end
239
+
173
240
  end
174
241
  end
data/naoki.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "naoki"
3
- s.version = "1.0.21"
3
+ s.version = "1.0.22"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.homepage = ""
6
6
  s.summary = "C bindings for SafeNet DataSecure ICAPI"
data/test/helper.rb CHANGED
@@ -1,23 +1,4 @@
1
+ require 'yaml'
1
2
  require 'minitest/unit'
2
3
  require 'naoki'
3
- require '~/naoki_config'
4
-
5
- def one_time_setup
6
- user_name = SAFENET_CONFIG[:username]
7
- password = SAFENET_CONFIG[:password]
8
- algorithm = SAFENET_CONFIG[:algorithm]
9
- key_name = SAFENET_CONFIG[:key_name] # versioned key
10
- initialization_vector = SAFENET_CONFIG[:initialization_vector]
11
-
12
- properties_file = 'IngrianNAE.properties'
13
-
14
- DataSecureWrapper.configure(properties_file)
15
- DataSecureWrapper.open(user_name, password)
16
-
17
- at_exit do
18
- DataSecureWrapper.close
19
- end
20
- end
21
- one_time_setup
22
-
23
4
  require 'minitest/autorun'
@@ -0,0 +1,53 @@
1
+ require 'helper'
2
+ require 'stringio'
3
+
4
+ class TestDataSecure < MiniTest::Unit::TestCase
5
+ def setup
6
+ @data_secure = Naoki::DataSecure.new(:account_number, config_file)
7
+ end
8
+
9
+ def teardown
10
+ @data_secure.close
11
+ @data_secure = nil
12
+ end
13
+
14
+ def test_hello_world
15
+ expected = 'hello world!'
16
+ encrypted_data = @data_secure.encrypt(expected)
17
+ decrypted_data = @data_secure.decrypt(encrypted_data)
18
+ assert(expected == decrypted_data || "decrypted string" == decrypted_data)
19
+ end
20
+
21
+ def test_documents
22
+ 13.times do |idx|
23
+ str = '01234567'*(1 << idx)
24
+ encrypt_and_decrypt(str.size, StringIO.new(str))
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def encrypt_and_decrypt(size, unencrypted)
31
+ encrypted = StringIO.new
32
+ unencrypted_size = unencrypted.size
33
+
34
+ (read_bytes, written_bytes) = @data_secure.encrypt_stream(unencrypted, encrypted)
35
+
36
+ assert_equal unencrypted_size, read_bytes
37
+ assert(read_bytes < written_bytes)
38
+
39
+ encrypted.rewind
40
+
41
+ decrypted = StringIO.new
42
+ (read_bytes, written_bytes) = @data_secure.decrypt_stream(encrypted, decrypted)
43
+
44
+ unencrypted.rewind
45
+ decrypted.rewind
46
+ assert(read_bytes > written_bytes)
47
+ assert_equal(unencrypted.read, decrypted.read)
48
+ end
49
+
50
+ def config_file
51
+ YAML.load(File.read('config/data_secure.yml'))
52
+ end
53
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: naoki
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.21
5
+ version: 1.0.22
6
6
  platform: ruby
7
7
  authors:
8
8
  - Chris Apolzon
@@ -11,7 +11,8 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-06-21 00:00:00 Z
14
+ date: 2011-06-21 00:00:00 -07:00
15
+ default_executable:
15
16
  dependencies:
16
17
  - !ruby/object:Gem::Dependency
17
18
  name: ffi
@@ -38,6 +39,7 @@ files:
38
39
  - .rvmrc
39
40
  - Gemfile
40
41
  - Rakefile
42
+ - config/data_secure.yml
41
43
  - lib/data_secure_wrapper.rb
42
44
  - lib/libICAPI_32.so
43
45
  - lib/libICAPI_64.so
@@ -46,7 +48,8 @@ files:
46
48
  - naoki.gemspec
47
49
  - sample.rb
48
50
  - test/helper.rb
49
- - test/test_data_secure_wrapper.rb
51
+ - test/test_data_secure.rb
52
+ has_rdoc: true
50
53
  homepage: ""
51
54
  licenses: []
52
55
 
@@ -70,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
73
  requirements: []
71
74
 
72
75
  rubyforge_project:
73
- rubygems_version: 1.7.2
76
+ rubygems_version: 1.5.2
74
77
  signing_key:
75
78
  specification_version: 3
76
79
  summary: C bindings for SafeNet DataSecure ICAPI
@@ -1,53 +0,0 @@
1
- require 'helper'
2
- require 'stringio'
3
-
4
- class TestDataSecureWrapper < MiniTest::Unit::TestCase
5
-
6
- def test_hello_world
7
- expected = 'hello world!'
8
- encrypted_data = encrypt(expected)
9
- decrypted_data = decrypt(encrypted_data)
10
- assert(expected == decrypted_data || "decrypted_string" == decrypted_data)
11
- end
12
-
13
- def test_documents
14
- ds = Naoki::DataSecure.new(:document_store, SAFENET_CONFIG)
15
-
16
- 15.times do |idx|
17
- str = '01234567'*(1 << idx)
18
- encrypt_and_decrypt(ds, str.size, StringIO.new(str))
19
- end
20
- ensure
21
- ds.close
22
- end
23
-
24
- private
25
-
26
- def encrypt_and_decrypt(ds, size, unencrypted)
27
- encrypted = StringIO.new
28
- unencrypted_size = unencrypted.size
29
-
30
- (read_bytes, written_bytes) = ds.encrypt_stream(unencrypted, encrypted)
31
-
32
- assert_equal unencrypted_size, read_bytes
33
- assert(read_bytes < written_bytes)
34
-
35
- encrypted.rewind
36
-
37
- decrypted = StringIO.new
38
- (read_bytes, written_bytes) = ds.decrypt_stream(encrypted, decrypted)
39
-
40
- unencrypted.rewind
41
- decrypted.rewind
42
- assert(read_bytes > written_bytes)
43
- assert_equal(unencrypted.read, decrypted.read)
44
- end
45
-
46
- def decrypt(data)
47
- DataSecureWrapper.decrypt(SAFENET_CONFIG[:algorithm], SAFENET_CONFIG[:key_name], SAFENET_CONFIG[:initialization_vector], data)
48
- end
49
-
50
- def encrypt(data)
51
- DataSecureWrapper.encrypt(SAFENET_CONFIG[:algorithm], SAFENET_CONFIG[:key_name], SAFENET_CONFIG[:initialization_vector], data)
52
- end
53
- end