naoki 1.0.19 → 1.0.20

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.
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ Logfile*
5
5
  IngrianNAE.properties
6
6
  *.gem
7
7
  Gemfile.lock
8
+ ManillaLocalCA.crt
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create ruby-1.9.2-p180@naoki
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new(:test) do |test|
4
+ test.libs << 'test'
5
+ test.pattern = 'test/**/test_*.rb'
6
+ end
7
+
8
+ task :default => :test
@@ -0,0 +1,170 @@
1
+ # Create a DataSecure connection for encrypting/decrypting documents.
2
+ # All operations performed on an instance share the same session/connection.
3
+ # NB: this class is not thread-safe. Create an instance for each thread.
4
+ module Naoki
5
+ class DataSecure
6
+ if `uname -s`.strip !~ /Linux/
7
+
8
+ def self.init(file); end
9
+ def close; end
10
+
11
+ def encrypt_stream(input, out)
12
+ out.write("ENC")
13
+ count = 0
14
+ while block = input.read(4096)
15
+ count += block.size
16
+ out.write(block)
17
+ end
18
+ [count, count + 3]
19
+ end
20
+
21
+ def decrypt_stream(input, out)
22
+ val = input.read(3)
23
+ raise ArgumentError, "Invalid encrypted data (#{val})" if val != 'ENC'
24
+ count = IO.copy_stream(input, out)
25
+ [count + 3, count]
26
+ end
27
+
28
+ else
29
+
30
+ require 'ffi'
31
+ extend FFI::Library
32
+ LIB_ICAPI_FILE = `uname -m`.match(/x86_64/) ? 'libICAPI_64.so' : 'libICAPI_32.so'
33
+ ffi_lib File.expand_path(File.join(File.dirname(__FILE__), '..', LIB_ICAPI_FILE))
34
+
35
+ I_T_Init_File = 0
36
+ I_E_OK = 0
37
+ I_T_Auth_Password = 0
38
+ I_T_Operation_Encrypt = 0
39
+ I_T_Operation_Decrypt = 1
40
+
41
+ attach_function 'I_C_GetErrorString', [:int], :string
42
+ attach_function 'I_C_Initialize', [:uint8, :string], :int
43
+ attach_function 'I_C_OpenSession', [:pointer, :uint8, :string, :string], :int
44
+ attach_function 'I_C_CreateCipherSpec', [:string, :string, :pointer], :int
45
+ attach_function 'I_C_CalculateEncipheredSizeForKey', [:pointer, :pointer, :uint8, :uint, :pointer], :int
46
+ attach_function 'I_C_DeleteCipherSpec', [:pointer], :int
47
+ attach_function 'I_C_Crypt', [:pointer, :pointer, :uint8, :string, :uint, :pointer, :uint, :pointer, :pointer], :int
48
+ attach_function 'I_C_CalculateOutputSizeForKey', [:pointer, :pointer, :uint8, :int, :pointer], :int
49
+ attach_function 'I_C_CloseSession', [:pointer], :void
50
+
51
+ # Setting @blocking = true before calling attach_function is the blessed FFI way to tell FFI to release
52
+ # Ruby's GIL when calling the wrapped C function. What a wretched hack.
53
+ @blocking = true
54
+ attach_function 'I_C_CryptInit', [:pointer, :pointer, :uint8, :pointer, :uint, :pointer], :int
55
+ @blocking = true
56
+ attach_function 'I_C_CryptFinal', [:pointer,:pointer,:pointer,:pointer], :int
57
+ @blocking = true
58
+ attach_function 'I_C_CryptUpdate', [:pointer, :pointer, :pointer, :uint, :pointer, :pointer], :int
59
+
60
+ DEFAULTS = {
61
+ :algorithm => 'AES/CBC/PKCS5Padding',
62
+ :key_name => 'stg-new-test-key',
63
+ :initialization_vector => '1234567890123456',
64
+ }
65
+
66
+ MAX_SAFENET_BLOCK_SIZE = 31000
67
+ MAX_OUTPUT_BLOCK_SIZE = 32000
68
+
69
+ def initialize(key_to_use = :account_number, options={})
70
+ @options = DEFAULTS.merge(options.symbolize_keys)
71
+ #check { I_C_Initialize(I_T_Init_File, @options[:properties_file]) }
72
+ @session_pointer = FFI::MemoryPointer.new :pointer
73
+ check { I_C_OpenSession(@session_pointer, I_T_Auth_Password, @options[:username], @options[:password]) }
74
+ @cipherspec_pointer = FFI::MemoryPointer.new :pointer
75
+ check { I_C_CreateCipherSpec(@options[:algorithm], @options[:keys][key_to_use.to_s], @cipherspec_pointer) }
76
+ end
77
+
78
+ def self.init(file)
79
+ check { I_C_Initialize(I_T_Init_File, file) }
80
+ end
81
+
82
+ def close
83
+ I_C_CloseSession(@session_pointer.get_pointer(0)) if @session_pointer
84
+ end
85
+
86
+ def encrypt_stream(input_io, output_io)
87
+ transform_stream(I_T_Operation_Encrypt, input_io, output_io)
88
+ end
89
+
90
+ def decrypt_stream(input_io, output_io)
91
+ transform_stream(I_T_Operation_Decrypt, input_io, output_io)
92
+ end
93
+
94
+ private
95
+
96
+ def transform_stream(op, input_io, output_io)
97
+ current_state = FFI::MemoryPointer.new :pointer
98
+ check do
99
+ I_C_CryptInit(
100
+ @session_pointer.get_pointer(0),
101
+ @cipherspec_pointer.get_pointer(0),
102
+ op,
103
+ @options[:initialization_vector],
104
+ @options[:initialization_vector].length,
105
+ current_state)
106
+ end
107
+
108
+ done = false
109
+ read_size = 0
110
+ wrote_size = 0
111
+ output_data = FFI::MemoryPointer.new :pointer, MAX_OUTPUT_BLOCK_SIZE
112
+ output_data_length_pointer = FFI::MemoryPointer.new :pointer
113
+
114
+ loop do
115
+ output_data_length_pointer.write_uint(MAX_OUTPUT_BLOCK_SIZE)
116
+
117
+ data = input_io.read(MAX_SAFENET_BLOCK_SIZE)
118
+ if !data || data.size == 0
119
+
120
+ check do
121
+ I_C_CryptFinal(
122
+ @session_pointer.get_pointer(0),
123
+ current_state.get_pointer(0),
124
+ output_data,
125
+ output_data_length_pointer)
126
+ end
127
+ done = true
128
+
129
+ elsif data.size <= MAX_SAFENET_BLOCK_SIZE
130
+ read_size += data.size
131
+ check do
132
+ I_C_CryptUpdate(
133
+ @session_pointer.get_pointer(0),
134
+ current_state.get_pointer(0),
135
+ data,
136
+ data.size,
137
+ output_data,
138
+ output_data_length_pointer)
139
+ end
140
+
141
+ else
142
+ raise "DataSecure, how did we get here? #{data}"
143
+ end
144
+
145
+ outsize = output_data_length_pointer.read_uint
146
+ enc_data = output_data.get_bytes(0, outsize)
147
+ wrote_size += output_io.write(enc_data)
148
+ break if done
149
+ end
150
+
151
+ [read_size, wrote_size]
152
+ end
153
+
154
+ def check
155
+ return_code = yield
156
+ if return_code != I_E_OK
157
+ I_C_DeleteCipherSpec(@cipherspec_pointer.get_pointer(0)) if @cipherspec_pointer
158
+ @cipherspec_pointer = nil
159
+ raise I_C_GetErrorString(return_code)
160
+ end
161
+ end
162
+
163
+ def self.check(&block)
164
+ return_code = yield
165
+ raise I_C_GetErrorString(return_code) if return_code != I_E_OK
166
+ end
167
+
168
+ end
169
+ end
170
+ end
data/lib/naoki.rb CHANGED
@@ -1 +1,2 @@
1
1
  require 'data_secure_wrapper'
2
+ require 'naoki/data_secure'
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.19"
3
+ s.version = "1.0.20"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.homepage = ""
6
6
  s.summary = "C bindings for SafeNet DataSecure ICAPI"
data/sample.rb CHANGED
@@ -1,21 +1,55 @@
1
1
  require File.join(File.dirname(__FILE__), 'lib/data_secure_wrapper')
2
+ require '~/naoki_config'
2
3
 
3
4
  properties_file = 'IngrianNAE.properties'
4
- user_name = ''
5
- password = ''
6
- algorithm = ''
7
- key_name = ''
8
- initialization_vector = ''
5
+ user_name = SAFENET_CONFIG[:user_name]
6
+ password = SAFENET_CONFIG[:password]
7
+ algorithm = SAFENET_CONFIG[:algorithm]
8
+ key_name = SAFENET_CONFIG[:key_name] # versioned key
9
+ initialization_vector = SAFENET_CONFIG[:initialization_vector]
9
10
 
10
- input_data = 'qwertyuiopasdfghjkl;zxcvbnm,./'
11
+ #input_data = 'qwertyuiopasdfghjkl;zxcvbnm,./'
12
+ input_data = 'hello'
11
13
 
12
14
  ###
13
15
 
14
16
  DataSecureWrapper.configure(properties_file)
15
17
  DataSecureWrapper.open(user_name, password)
16
18
 
17
- puts "encrypting: '#{input_data}'"
18
- encrypted_data = DataSecureWrapper.encrypt(algorithm, key_name, initialization_vector, input_data)
19
- decrypted_data = DataSecureWrapper.decrypt(algorithm, key_name, initialization_vector, encrypted_data)
20
- puts "decrypted: '#{decrypted_data}'"
19
+ #puts "encrypting: '#{input_data}'"
20
+ #encrypted_data = DataSecureWrapper.encrypt(algorithm, key_name, initialization_vector, input_data)
21
+ #decrypted_data = DataSecureWrapper.decrypt(algorithm, key_name, initialization_vector, encrypted_data)
22
+ #puts "decrypted: '#{decrypted_data}'"
23
+
24
+
25
+ help = <<EOM
26
+
27
+ This console is for testing our interaction with Safenet.
28
+
29
+ Usage:
30
+
31
+ e = test encrypting and decrypting a string
32
+
33
+ q = quit
34
+ EOM
35
+
36
+ puts help
37
+
38
+ while (input = gets.strip) != "q"
39
+ case input
40
+ when "e"
41
+ puts "string to encrypt:"
42
+ input_data = gets.chomp
43
+ puts "encrypting: '#{input_data}'"
44
+
45
+ encrypted_data = DataSecureWrapper.encrypt(algorithm, key_name, initialization_vector, input_data)
46
+ decrypted_data = DataSecureWrapper.decrypt(algorithm, key_name, initialization_vector, encrypted_data)
47
+ puts "decrypted: '#{decrypted_data}'"
48
+ when "q"
49
+ exit
50
+ else
51
+ puts "command not recognized"
52
+ end
53
+ puts help
54
+ end
21
55
 
data/test/helper.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'minitest/unit'
2
+ 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
+ require 'minitest/autorun'
@@ -0,0 +1,53 @@
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
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: naoki
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.19
5
+ version: 1.0.20
6
6
  platform: ruby
7
7
  authors:
8
8
  - Chris Apolzon
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-05-04 00:00:00 -07:00
14
+ date: 2011-06-20 00:00:00 -07:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
@@ -36,13 +36,18 @@ extra_rdoc_files: []
36
36
 
37
37
  files:
38
38
  - .gitignore
39
+ - .rvmrc
39
40
  - Gemfile
41
+ - Rakefile
40
42
  - lib/data_secure_wrapper.rb
41
43
  - lib/libICAPI_32.so
42
44
  - lib/libICAPI_64.so
43
45
  - lib/naoki.rb
46
+ - lib/naoki/data_secure.rb
44
47
  - naoki.gemspec
45
48
  - sample.rb
49
+ - test/helper.rb
50
+ - test/test_data_secure_wrapper.rb
46
51
  has_rdoc: true
47
52
  homepage: ""
48
53
  licenses: []