rubythemis 0.9.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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/rubythemis.rb +308 -0
  3. metadata +69 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c533507748e3b83574754d815e8876013636b55b
4
+ data.tar.gz: c8b9067cbefeeab4d80a4ca4380affda98d21b79
5
+ SHA512:
6
+ metadata.gz: 78a31344f698b9798b403d9c2cbdbf92601f90c20d62e8e97cf69c9dffc9cffbfe9c97c38ee8d4650829bb2d5056d824e855f64a9848e4d81e3f4bf5e99a4964
7
+ data.tar.gz: 13c1baf7117e3af8ed2496222ca6182e75ee0c709395bfb92042504de8046eb09fba1e45cf86c32636380d74dad9261649074d1833bd18c310ce25516a9ebee7
data/lib/rubythemis.rb ADDED
@@ -0,0 +1,308 @@
1
+ #
2
+ # Copyright (c) 2015 Cossack Labs Limited
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'ffi'
18
+
19
+ module ThemisCommon
20
+ def string_to_pointer_size(string)
21
+ string_buf = FFI::MemoryPointer.new(:char, string.force_encoding("BINARY").size)
22
+ string_buf.put_bytes(0, string.force_encoding("BINARY"), 0, string.force_encoding("BINARY").size)
23
+ return string_buf, string.force_encoding("BINARY").size
24
+ end
25
+ module_function :string_to_pointer_size
26
+ end
27
+
28
+ module ThemisImport
29
+ extend FFI::Library
30
+ ffi_lib 'themis'
31
+
32
+
33
+
34
+ callback :get_pub_key_by_id_type, [:pointer, :int, :pointer, :int, :uint], :int
35
+ callback :send_callback_type, [:pointer, :int, :uint], :int
36
+ callback :receive_callback_type, [:pointer, :int, :uint], :int
37
+
38
+ class Callbacks_struct < FFI::Struct
39
+ layout :send_data, :send_callback_type,
40
+ :receive_data, :receive_callback_type,
41
+ :state_changed, :pointer,
42
+ :get_pub_key_for_id, :get_pub_key_by_id_type,
43
+ :user_data, :uint
44
+ end
45
+
46
+ attach_function :secure_session_create, [ :pointer, :uint, :pointer, :uint, :pointer], :pointer
47
+ attach_function :secure_session_destroy, [ :pointer], :int
48
+ attach_function :secure_session_generate_connect_request, [ :pointer, :pointer, :pointer], :int
49
+ attach_function :secure_session_wrap, [ :pointer, :pointer, :int, :pointer, :pointer], :int
50
+ attach_function :secure_session_unwrap, [ :pointer, :pointer, :int, :pointer, :pointer], :int
51
+ attach_function :secure_session_is_established, [ :pointer], :bool
52
+
53
+ attach_function :themis_secure_message_wrap, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
54
+ attach_function :themis_secure_message_unwrap, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
55
+
56
+ attach_function :themis_gen_rsa_key_pair, [:pointer, :pointer, :pointer, :pointer], :int
57
+ attach_function :themis_gen_ec_key_pair, [:pointer, :pointer, :pointer, :pointer], :int
58
+ attach_function :themis_version, [], :string
59
+
60
+ attach_function :themis_secure_cell_encrypt_full, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
61
+ attach_function :themis_secure_cell_decrypt_full, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
62
+
63
+ attach_function :themis_secure_cell_encrypt_auto_split, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer, :pointer, :pointer], :int
64
+ attach_function :themis_secure_cell_decrypt_auto_split, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
65
+
66
+ attach_function :themis_secure_cell_encrypt_user_split, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
67
+ attach_function :themis_secure_cell_decrypt_user_split, [:pointer, :int, :pointer, :int, :pointer, :int, :pointer, :pointer], :int
68
+ end
69
+
70
+ module Themis
71
+
72
+ BUFFER_TOO_SMALL = -4
73
+ SUCCESS = 0
74
+ FAIL = -1
75
+ SEND_AS_IS = 1
76
+
77
+
78
+ class ThemisError < StandardError
79
+ end
80
+
81
+ class Callbacks
82
+ def get_pub_key_by_id(id)
83
+ raise ThemisError, "Callbacks not implemented: get_pub_key_by_id"
84
+ end
85
+
86
+ def send(message)
87
+ raise ThemisError, "Callbacks not implemented: send"
88
+ end
89
+
90
+ def receive()
91
+ raise ThemisError, "Callbacks not implemented: receive"
92
+ end
93
+ end
94
+
95
+ class SKeyPairGen
96
+ include ThemisCommon
97
+ include ThemisImport
98
+
99
+ def ec()
100
+ private_key_length=FFI::MemoryPointer.new(:uint)
101
+ public_key_length= FFI::MemoryPointer.new(:uint)
102
+ res=themis_gen_ec_key_pair(nil, private_key_length, nil, public_key_length)
103
+ raise ThemisError, "themis_gen_ec_key_pair (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
104
+ private_key = FFI::MemoryPointer.new(:char, private_key_length.read_uint)
105
+ public_key = FFI::MemoryPointer.new(:char, public_key_length.read_uint)
106
+ res=themis_gen_ec_key_pair(private_key, private_key_length, public_key, public_key_length)
107
+ raise ThemisError, "themis_gen_ec_key_pair error: #{res}" unless res == SUCCESS
108
+ return private_key.get_bytes(0, private_key_length.read_uint), public_key.get_bytes(0, public_key_length.read_uint)
109
+ end
110
+
111
+ def rsa()
112
+ private_key_length=FFI::MemoryPointer.new(:uint)
113
+ public_key_length= FFI::MemoryPointer.new(:uint)
114
+ res=themis_gen_rsa_key_pair(nil, private_key_length, nil, public_key_length)
115
+ raise ThemisError, "themis_gen_ec_key_pair (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
116
+ private_key = FFI::MemoryPointer.new(:char, private_key_length.read_uint)
117
+ public_key = FFI::MemoryPointer.new(:char, public_key_length.read_uint)
118
+ res=themis_gen_rsa_key_pair(private_key, private_key_length, public_key, public_key_length)
119
+ raise ThemisError, "themis_gen_ec_key_pair error: #{res}" unless res == SUCCESS
120
+ return private_key.get_bytes(0, private_key_length.read_uint), public_key.get_bytes(0, public_key_length.read_uint)
121
+ end
122
+ end
123
+ class Ssession
124
+ include ThemisCommon
125
+ include ThemisImport
126
+
127
+ MAPPING = {}
128
+
129
+ Get_pub_key_by_id_callback = FFI::Function.new(:int, [:pointer, :int, :pointer, :int, :uint]) do |id_buf, id_length, pubkey_buf, pubkey_length, obj|
130
+ pub_key=MAPPING[obj].get_pub_key_by_id(id_buf.get_bytes(0,id_length))
131
+ if !pub_key
132
+ -1
133
+ end
134
+ pubkey_buf.put_bytes(0, pub_key)
135
+ 0
136
+ end
137
+
138
+ def initialize(id, private_key, transport)
139
+ id_buf, id_length = string_to_pointer_size(id)
140
+ private_key_buf, private_key_length = string_to_pointer_size(private_key)
141
+ @callbacks = Callbacks_struct.new
142
+ @callbacks[:get_pub_key_for_id] = Get_pub_key_by_id_callback
143
+ MAPPING[transport.object_id]=transport
144
+ @callbacks[:user_data] =transport.object_id
145
+ @session=secure_session_create(id_buf, id_length, private_key_buf, private_key_length, @callbacks);
146
+ raise ThemisError, "secure_session_create error" unless @session
147
+ end
148
+
149
+ def is_established()
150
+ return secure_session_is_established(@session)
151
+ end
152
+
153
+ def connect_request()
154
+ connect_request_length = FFI::MemoryPointer.new(:uint)
155
+ res=secure_session_generate_connect_request(@session, nil, connect_request_length)
156
+ raise ThemisError, "secure_session_generate_connect_request (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
157
+ connect_request = FFI::MemoryPointer.new(:char, connect_request_length.read_uint)
158
+ res=secure_session_generate_connect_request(@session, connect_request, connect_request_length)
159
+ raise ThemisError, "secure_session_generate_connect_request error: #{res}" unless res == SUCCESS
160
+ return connect_request.get_bytes(0, connect_request_length.read_uint);
161
+ end
162
+
163
+ def unwrap(message)
164
+ message_, message_length_=string_to_pointer_size(message)
165
+ unwrapped_message_length = FFI::MemoryPointer.new(:uint)
166
+ res=secure_session_unwrap(@session, message_, message_length_, nil, unwrapped_message_length)
167
+ raise ThemisError, "secure_session_unwrap (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL || res == SUCCESS
168
+ if res == SUCCESS
169
+ return SUCCESS, ""
170
+ end
171
+ unwrapped_message = FFI::MemoryPointer.new(:char, unwrapped_message_length.read_uint)
172
+ res=secure_session_unwrap(@session, message_, message_length_, unwrapped_message, unwrapped_message_length)
173
+ raise ThemisError, "secure_session_unwrap error: #{res}" unless res == SUCCESS || res == SEND_AS_IS
174
+ return res, unwrapped_message.get_bytes(0, unwrapped_message_length.read_uint);
175
+ end
176
+
177
+ def wrap(message)
178
+ message_, message_length_=string_to_pointer_size(message)
179
+ wrapped_message_length = FFI::MemoryPointer.new(:uint)
180
+ res=secure_session_wrap(@session, message_, message_length_, nil, wrapped_message_length)
181
+ raise ThemisError, "secure_session_wrap (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
182
+ wrapped_message = FFI::MemoryPointer.new(:char, wrapped_message_length.read_uint)
183
+ res=secure_session_wrap(@session, message_, message_length_, wrapped_message, wrapped_message_length)
184
+ raise ThemisError, "secure_session_wrap error: #{res}" unless res == SUCCESS || res == SEND_AS_IS
185
+ return wrapped_message.get_bytes(0, wrapped_message_length.read_uint);
186
+ end
187
+
188
+ def finalize
189
+ res=secure_session_destroy(@session)
190
+ raise ThemisError, "secure_session_destroy error" unless res == SUCCESS
191
+
192
+ end
193
+ end
194
+
195
+ class Smessage
196
+ include ThemisCommon
197
+ include ThemisImport
198
+ def initialize(private_key, peer_public_key)
199
+ @private_key, @private_key_length = string_to_pointer_size(private_key)
200
+ @peer_public_key, @peer_public_key_length = string_to_pointer_size(peer_public_key)
201
+ end
202
+
203
+ def wrap(message)
204
+ message_, message_length_=string_to_pointer_size(message)
205
+ wrapped_message_length = FFI::MemoryPointer.new(:uint)
206
+ res=themis_secure_message_wrap(@private_key, @private_key_length, @peer_public_key, @peer_public_key_length, message_, message_length_, nil, wrapped_message_length)
207
+ raise ThemisError, "themis_secure_message_wrap (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
208
+ wrapped_message = FFI::MemoryPointer.new(:char, wrapped_message_length.read_uint)
209
+ res=themis_secure_message_wrap(@private_key, @private_key_length, @peer_public_key, @peer_public_key_length, message_, message_length_, wrapped_message, wrapped_message_length)
210
+ raise ThemisError, "themis_secure_message_wrap error: #{res}" unless res == SUCCESS
211
+ return wrapped_message.get_bytes(0, wrapped_message_length.read_uint);
212
+ end
213
+
214
+ def unwrap(message)
215
+ message_, message_length_=string_to_pointer_size(message)
216
+ unwrapped_message_length = FFI::MemoryPointer.new(:uint)
217
+ res=themis_secure_message_unwrap(@private_key, @private_key_length, @peer_public_key, @peer_public_key_length, message_, message_length_, nil, unwrapped_message_length)
218
+ raise ThemisError, "themis_secure_message_unwrap (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
219
+ unwrapped_message = FFI::MemoryPointer.new(:char, unwrapped_message_length.read_uint)
220
+ res=themis_secure_message_unwrap(@private_key, @private_key_length, @peer_public_key, @peer_public_key_length, message_, message_length_, unwrapped_message, unwrapped_message_length)
221
+ raise ThemisError, "themis_secure_message_unwrap error: #{res}" unless res == SUCCESS
222
+ return unwrapped_message.get_bytes(0, unwrapped_message_length.read_uint);
223
+ end
224
+ end
225
+
226
+ class Scell
227
+ include ThemisCommon
228
+ include ThemisImport
229
+
230
+ FULL_MODE = 0
231
+ AUTO_SPLIT_MODE = 1
232
+ USER_SPLIT_MODE = 2
233
+
234
+ def initialize(key, mode)
235
+ @key, @key_length = string_to_pointer_size(key)
236
+ @mode = mode
237
+ end
238
+
239
+ def encrypt(message, context=nil)
240
+ message_, message_length_ = string_to_pointer_size(message)
241
+ context_, context_length_ = context.nil? ? [nil,0] : string_to_pointer_size(context)
242
+ encrypted_message_length=FFI::MemoryPointer.new(:uint)
243
+ enccontext_length=FFI::MemoryPointer.new(:uint)
244
+ case @mode
245
+ when FULL_MODE
246
+ res=themis_secure_cell_encrypt_full(@key, @key_length, context_, context_length_, message_, message_length_, nil, encrypted_message_length)
247
+ raise ThemisError, "themis_secure_cell_encrypt_... (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
248
+ encrypted_message = FFI::MemoryPointer.new(:char, encrypted_message_length.read_uint)
249
+ res=themis_secure_cell_encrypt_full(@key, @key_length, context_, context_length_, message_, message_length_, encrypted_message, encrypted_message_length)
250
+ raise ThemisError, "themis_secure_cell_encrypt_full (length determination) error: #{res}" unless res == SUCCESS
251
+ return encrypted_message.get_bytes(0, encrypted_message_length.read_uint)
252
+ when AUTO_SPLIT_MODE
253
+ res=themis_secure_cell_encrypt_auto_split(@key, @key_length, context_, context_length_, message_, message_length_, nil, enccontext_length, nil, encrypted_message_length)
254
+ raise ThemisError, "themis_secure_cell_encrypt_... (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
255
+ encrypted_message = FFI::MemoryPointer.new(:char, encrypted_message_length.read_uint)
256
+ enccontext = FFI::MemoryPointer.new(:char, enccontext_length.read_uint)
257
+ res=themis_secure_cell_encrypt_auto_split(@key, @key_length, context_, context_length_, message_, message_length_, enccontext, enccontext_length, encrypted_message, encrypted_message_length)
258
+ raise ThemisError, "themis_secure_cell_encrypt_auto_split (length determination) error: #{res}" unless res == SUCCESS
259
+ return enccontext.get_bytes(0, enccontext_length.read_uint), encrypted_message.get_bytes(0, encrypted_message_length.read_uint)
260
+ when USER_SPLIT_MODE
261
+ res=themis_secure_cell_encrypt_user_split(@key, @key_length, message_, message_length_, context_, context_length_, nil, encrypted_message_length)
262
+ raise ThemisError, "themis_secure_cell_encrypt_... (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
263
+ encrypted_message = FFI::MemoryPointer.new(:char, encrypted_message_length.read_uint)
264
+ res=themis_secure_cell_encrypt_user_split(@key, @key_length, message_, message_length_, context_, context_length_, encrypted_message, encrypted_message_length)
265
+ raise ThemisError, "themis_secure_cell_encrypt_user_split (length determination) error: #{res}" unless res == SUCCESS
266
+ return encrypted_message.get_bytes(0, encrypted_message_length.read_uint)
267
+ else
268
+ raise ThemisError, "themis_secure_cell not supported mode"
269
+ end
270
+ end
271
+
272
+ def decrypt(message, context=nil)
273
+ context_, context_length_ = context.nil? ? [nil,0] : string_to_pointer_size(context)
274
+ decrypted_message_length=FFI::MemoryPointer.new(:uint)
275
+ case @mode
276
+ when FULL_MODE
277
+ message_, message_length_ = string_to_pointer_size(message)
278
+ res=themis_secure_cell_decrypt_full(@key, @key_length, context_, context_length_, message_, message_length_, nil, decrypted_message_length)
279
+ raise ThemisError, "themis_secure_cell_decrypt_full (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
280
+ decrypted_message = FFI::MemoryPointer.new(:char, decrypted_message_length.read_uint)
281
+ res=themis_secure_cell_decrypt_full(@key, @key_length, context_, context_length_, message_, message_length_, decrypted_message, decrypted_message_length)
282
+ raise ThemisError, "themis_secure_cell_decrypt_full (length determination) error: #{res}" unless res == SUCCESS
283
+ return decrypted_message.get_bytes(0, decrypted_message_length.read_uint)
284
+ when AUTO_SPLIT_MODE
285
+ enccontext, message_ = message
286
+ message__, message_length__ = string_to_pointer_size(message_)
287
+ enccontext_, enccontext_length = string_to_pointer_size(enccontext)
288
+ res=themis_secure_cell_decrypt_auto_split(@key, @key_length, context_, context_length_, message__, message_length__, enccontext_, enccontext_length, nil, decrypted_message_length)
289
+ raise ThemisError, "themis_secure_cell_encrypt_auto_split (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
290
+ decrypted_message = FFI::MemoryPointer.new(:char, decrypted_message_length.read_uint)
291
+ res=themis_secure_cell_decrypt_auto_split(@key, @key_length, context_, context_length_, message__, message_length__, enccontext_, enccontext_length, decrypted_message, decrypted_message_length)
292
+ raise ThemisError, "themis_secure_cell_encrypt_auto_split (length determination) error: #{res}" unless res == SUCCESS
293
+ return decrypted_message.get_bytes(0, decrypted_message_length.read_uint)
294
+ when USER_SPLIT_MODE
295
+ message_, message_length_ = string_to_pointer_size(message)
296
+ res=themis_secure_cell_decrypt_user_split(@key, @key_length, message_, message_length_, context_, context_length_, nil, decrypted_message_length)
297
+ raise ThemisError, "themis_secure_cell_decrypt_user_split (length determination) error: #{res}" unless res == BUFFER_TOO_SMALL
298
+ decrypted_message = FFI::MemoryPointer.new(:char, decrypted_message_length.read_uint)
299
+ res=themis_secure_cell_decrypt_user_split(@key, @key_length, message_, message_length_, context_, context_length_, decrypted_message, decrypted_message_length)
300
+ raise ThemisError, "themis_secure_cell_decrypt_user_split (length determination) error: #{res}" unless res == SUCCESS
301
+ return decrypted_message.get_bytes(0, decrypted_message_length.read_uint)
302
+ else
303
+ raise ThemisError, "themis_secure_cell not supported mode"
304
+ end
305
+ end
306
+
307
+ end
308
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubythemis
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ platform: ruby
6
+ authors:
7
+ - CossackLabs
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.9.8
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.9'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.9.8
33
+ description: Themis is a data security library, providing users with high-quality
34
+ security services for secure messaging of any kinds and flexible data storage. Themis
35
+ is aimed at modern developers, with high level OOP wrappers for Ruby, Python, PHP,
36
+ Java / Android and iOS / OSX. It is designed with ease of use in mind, high security
37
+ and cross-platform availability.
38
+ email: dev@cossacklabs.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - lib/rubythemis.rb
44
+ homepage: http://cossacklabs.com/
45
+ licenses:
46
+ - Apache 2.0
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements:
63
+ - libthemis, v0.9
64
+ rubyforge_project:
65
+ rubygems_version: 2.4.5
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Data security library for network communication and data storage for Ruby
69
+ test_files: []