naoki 1.0.19 → 1.0.20

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