naoki 1.0.21 → 1.0.22

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.
@@ -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