rubythemis 0.9.1

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