rbthemis 0.10.0 → 0.14.0
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.
- checksums.yaml +5 -5
- data/lib/rbthemis.rb +992 -0
- metadata +12 -15
- data/lib/rubythemis.rb +0 -645
data/lib/rbthemis.rb
ADDED
@@ -0,0 +1,992 @@
|
|
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.from_string(string)
|
22
|
+
[string_buf, string.bytesize]
|
23
|
+
end
|
24
|
+
|
25
|
+
def empty?(value)
|
26
|
+
return value.nil? || value.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
module_function :string_to_pointer_size
|
30
|
+
module_function :empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
module ThemisImport
|
34
|
+
extend FFI::Library
|
35
|
+
ffi_lib 'themis'
|
36
|
+
|
37
|
+
callback :get_pub_key_by_id_type,
|
38
|
+
[:pointer, :int, :pointer, :int, :pointer], :int
|
39
|
+
callback :send_callback_type, [:pointer, :int, :uint], :int
|
40
|
+
callback :receive_callback_type, [:pointer, :int, :uint], :int
|
41
|
+
|
42
|
+
class CallbacksStruct < FFI::Struct
|
43
|
+
layout :send_data, :send_callback_type,
|
44
|
+
:receive_data, :receive_callback_type,
|
45
|
+
:state_changed, :pointer,
|
46
|
+
:get_pub_key_for_id, :get_pub_key_by_id_type,
|
47
|
+
:user_data, :pointer
|
48
|
+
end
|
49
|
+
|
50
|
+
attach_function :secure_session_create,
|
51
|
+
[:pointer, :uint, :pointer, :uint, :pointer], :pointer
|
52
|
+
attach_function :secure_session_destroy, [:pointer], :int
|
53
|
+
attach_function :secure_session_generate_connect_request,
|
54
|
+
[:pointer, :pointer, :pointer], :int
|
55
|
+
|
56
|
+
attach_function :secure_session_wrap,
|
57
|
+
[:pointer, :pointer, :int, :pointer, :pointer], :int
|
58
|
+
attach_function :secure_session_unwrap,
|
59
|
+
[:pointer, :pointer, :int, :pointer, :pointer], :int
|
60
|
+
attach_function :secure_session_is_established, [:pointer], :bool
|
61
|
+
|
62
|
+
attach_function :themis_secure_message_encrypt,
|
63
|
+
[:pointer, :int, :pointer, :int, :pointer,
|
64
|
+
:int, :pointer, :pointer], :int
|
65
|
+
attach_function :themis_secure_message_decrypt,
|
66
|
+
[:pointer, :int, :pointer, :int, :pointer,
|
67
|
+
:int, :pointer, :pointer], :int
|
68
|
+
attach_function :themis_secure_message_sign,
|
69
|
+
[:pointer, :int, :pointer, :int, :pointer,
|
70
|
+
:pointer], :int
|
71
|
+
attach_function :themis_secure_message_verify,
|
72
|
+
[:pointer, :int, :pointer, :int, :pointer,
|
73
|
+
:pointer], :int
|
74
|
+
|
75
|
+
attach_function :themis_gen_rsa_key_pair,
|
76
|
+
[:pointer, :pointer, :pointer, :pointer], :int
|
77
|
+
attach_function :themis_gen_ec_key_pair,
|
78
|
+
[:pointer, :pointer, :pointer, :pointer], :int
|
79
|
+
attach_function :themis_gen_sym_key,
|
80
|
+
[:pointer, :pointer], :int
|
81
|
+
|
82
|
+
THEMIS_KEY_INVALID = 0
|
83
|
+
THEMIS_KEY_RSA_PRIVATE = 1
|
84
|
+
THEMIS_KEY_RSA_PUBLIC = 2
|
85
|
+
THEMIS_KEY_EC_PRIVATE = 3
|
86
|
+
THEMIS_KEY_EC_PUBLIC = 4
|
87
|
+
|
88
|
+
attach_function :themis_is_valid_asym_key, [:pointer, :int], :int
|
89
|
+
attach_function :themis_get_asym_key_kind, [:pointer, :int], :int
|
90
|
+
|
91
|
+
attach_function :themis_secure_cell_encrypt_seal,
|
92
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
93
|
+
:pointer, :pointer], :int
|
94
|
+
attach_function :themis_secure_cell_decrypt_seal,
|
95
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
96
|
+
:pointer, :pointer], :int
|
97
|
+
|
98
|
+
attach_function :themis_secure_cell_encrypt_seal_with_passphrase,
|
99
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
100
|
+
:pointer, :pointer], :int
|
101
|
+
attach_function :themis_secure_cell_decrypt_seal_with_passphrase,
|
102
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
103
|
+
:pointer, :pointer], :int
|
104
|
+
|
105
|
+
attach_function :themis_secure_cell_encrypt_token_protect,
|
106
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
107
|
+
:pointer, :pointer, :pointer, :pointer], :int
|
108
|
+
attach_function :themis_secure_cell_decrypt_token_protect,
|
109
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
110
|
+
:pointer, :int, :pointer, :pointer], :int
|
111
|
+
|
112
|
+
attach_function :themis_secure_cell_encrypt_context_imprint,
|
113
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
114
|
+
:pointer, :pointer], :int
|
115
|
+
attach_function :themis_secure_cell_decrypt_context_imprint,
|
116
|
+
[:pointer, :int, :pointer, :int, :pointer, :int,
|
117
|
+
:pointer, :pointer], :int
|
118
|
+
|
119
|
+
begin
|
120
|
+
attach_function :secure_comparator_create, [], :pointer
|
121
|
+
attach_function :secure_comparator_destroy, [:pointer], :int
|
122
|
+
attach_function :secure_comparator_append_secret,
|
123
|
+
[:pointer, :pointer, :int], :int
|
124
|
+
attach_function :secure_comparator_begin_compare,
|
125
|
+
[:pointer, :pointer, :pointer], :int
|
126
|
+
attach_function :secure_comparator_proceed_compare,
|
127
|
+
[:pointer, :pointer, :int, :pointer, :pointer], :int
|
128
|
+
attach_function :secure_comparator_get_result, [:pointer], :int
|
129
|
+
rescue FFI::NotFoundError
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
module Themis
|
134
|
+
extend ThemisCommon
|
135
|
+
extend ThemisImport
|
136
|
+
|
137
|
+
extend Gem::Deprecate
|
138
|
+
|
139
|
+
BUFFER_TOO_SMALL = 14
|
140
|
+
SUCCESS = 0
|
141
|
+
FAIL = 11
|
142
|
+
INVALID_ARGUMENT = 12
|
143
|
+
SEND_AS_IS = 1
|
144
|
+
|
145
|
+
# Common class of errors caused by Themis functions.
|
146
|
+
# You can access the numerical value via "error_code" attribute.
|
147
|
+
# Human-readable message is accessible via "message" attribute.
|
148
|
+
class ThemisError < StandardError
|
149
|
+
attr_reader :error_code
|
150
|
+
|
151
|
+
def initialize(error_code = INVALID_ARGUMENT)
|
152
|
+
super
|
153
|
+
@error_code = error_code
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class Callbacks
|
158
|
+
def get_pub_key_by_id(id)
|
159
|
+
raise ThemisError, 'Callback is not implemented: get_pub_key_by_id'
|
160
|
+
end
|
161
|
+
|
162
|
+
def send(message)
|
163
|
+
raise ThemisError, 'Callback is not implemented: send'
|
164
|
+
end
|
165
|
+
|
166
|
+
def receive
|
167
|
+
raise ThemisError, 'Callback is not implemented: receive'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class SKeyPairGen
|
172
|
+
include ThemisCommon
|
173
|
+
include ThemisImport
|
174
|
+
|
175
|
+
def ec
|
176
|
+
private_key_length = FFI::MemoryPointer.new(:uint)
|
177
|
+
public_key_length = FFI::MemoryPointer.new(:uint)
|
178
|
+
|
179
|
+
res = themis_gen_ec_key_pair(
|
180
|
+
nil, private_key_length, nil, public_key_length)
|
181
|
+
if res != BUFFER_TOO_SMALL
|
182
|
+
raise ThemisError, "Themis failed generating EC KeyPair: #{res}"
|
183
|
+
end
|
184
|
+
|
185
|
+
private_key = FFI::MemoryPointer.new(:char, private_key_length.read_uint)
|
186
|
+
public_key = FFI::MemoryPointer.new(:char, public_key_length.read_uint)
|
187
|
+
|
188
|
+
res = themis_gen_ec_key_pair(
|
189
|
+
private_key, private_key_length, public_key, public_key_length)
|
190
|
+
if res != SUCCESS
|
191
|
+
raise ThemisError, "Themis failed generating EC KeyPair: #{res}"
|
192
|
+
end
|
193
|
+
|
194
|
+
[private_key.get_bytes(0, private_key_length.read_uint),
|
195
|
+
public_key.get_bytes(0, public_key_length.read_uint)]
|
196
|
+
end
|
197
|
+
|
198
|
+
def rsa
|
199
|
+
private_key_length = FFI::MemoryPointer.new(:uint)
|
200
|
+
public_key_length = FFI::MemoryPointer.new(:uint)
|
201
|
+
|
202
|
+
res = themis_gen_rsa_key_pair(
|
203
|
+
nil, private_key_length, nil, public_key_length)
|
204
|
+
if res != BUFFER_TOO_SMALL
|
205
|
+
raise ThemisError, "Themis failed generating RSA KeyPair: #{res}"
|
206
|
+
end
|
207
|
+
|
208
|
+
private_key = FFI::MemoryPointer.new(:char, private_key_length.read_uint)
|
209
|
+
public_key = FFI::MemoryPointer.new(:char, public_key_length.read_uint)
|
210
|
+
|
211
|
+
res = themis_gen_rsa_key_pair(
|
212
|
+
private_key, private_key_length, public_key, public_key_length)
|
213
|
+
if res != SUCCESS
|
214
|
+
raise ThemisError, "Themis failed generating RSA KeyPair: #{res}"
|
215
|
+
end
|
216
|
+
|
217
|
+
[private_key.get_bytes(0, private_key_length.read_uint),
|
218
|
+
public_key.get_bytes(0, public_key_length.read_uint)]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def Themis.valid_key(key)
|
223
|
+
if key.nil? || key.empty?
|
224
|
+
return false
|
225
|
+
end
|
226
|
+
key_, len_ = string_to_pointer_size(key)
|
227
|
+
return themis_is_valid_asym_key(key_, len_) == SUCCESS
|
228
|
+
end
|
229
|
+
|
230
|
+
def Themis.private_key(key)
|
231
|
+
key_, len_ = string_to_pointer_size(key)
|
232
|
+
kind = themis_get_asym_key_kind(key_, len_)
|
233
|
+
return kind == ThemisImport::THEMIS_KEY_RSA_PRIVATE \
|
234
|
+
|| kind == ThemisImport::THEMIS_KEY_EC_PRIVATE
|
235
|
+
end
|
236
|
+
|
237
|
+
def Themis.public_key(key)
|
238
|
+
key_, len_ = string_to_pointer_size(key)
|
239
|
+
kind = themis_get_asym_key_kind(key_, len_)
|
240
|
+
return kind == ThemisImport::THEMIS_KEY_RSA_PUBLIC \
|
241
|
+
|| kind == ThemisImport::THEMIS_KEY_EC_PUBLIC
|
242
|
+
end
|
243
|
+
|
244
|
+
class Ssession
|
245
|
+
include ThemisCommon
|
246
|
+
include ThemisImport
|
247
|
+
|
248
|
+
extend Gem::Deprecate
|
249
|
+
|
250
|
+
MAPPING = {}
|
251
|
+
|
252
|
+
GetPubKeyByIDCallback =
|
253
|
+
FFI::Function.new(:int, [:pointer, :int, :pointer, :int, :pointer]) do |id_buf, id_length, pubkey_buf, pubkey_length, obj|
|
254
|
+
pub_key = MAPPING[obj.read_uint64].get_pub_key_by_id(
|
255
|
+
id_buf.get_bytes(0, id_length))
|
256
|
+
return -1 unless pub_key
|
257
|
+
pubkey_buf.put_bytes(0, pub_key)
|
258
|
+
0
|
259
|
+
end
|
260
|
+
|
261
|
+
def initialize(id, private_key, transport)
|
262
|
+
id_buf, id_length = string_to_pointer_size(id)
|
263
|
+
private_key_buf, private_key_length = string_to_pointer_size(private_key)
|
264
|
+
|
265
|
+
@callbacks = CallbacksStruct.new
|
266
|
+
@callbacks[:get_pub_key_for_id] = GetPubKeyByIDCallback
|
267
|
+
|
268
|
+
MAPPING[transport.object_id] = transport
|
269
|
+
@transport_obj_id = transport.object_id
|
270
|
+
|
271
|
+
@callbacks[:user_data] = FFI::MemoryPointer.new(:uint64)
|
272
|
+
@callbacks[:user_data].write_uint64(@transport_obj_id)
|
273
|
+
|
274
|
+
@session = secure_session_create(
|
275
|
+
id_buf, id_length, private_key_buf, private_key_length, @callbacks)
|
276
|
+
|
277
|
+
raise ThemisError, 'Secure Session failed creating' if @session.null?
|
278
|
+
end
|
279
|
+
|
280
|
+
def is_established
|
281
|
+
established?
|
282
|
+
end
|
283
|
+
deprecate(:is_established, :established?, 2018, 6)
|
284
|
+
|
285
|
+
def established?
|
286
|
+
secure_session_is_established @session
|
287
|
+
end
|
288
|
+
|
289
|
+
def connect_request
|
290
|
+
connect_request_length = FFI::MemoryPointer.new(:uint)
|
291
|
+
res = secure_session_generate_connect_request(
|
292
|
+
@session, nil, connect_request_length)
|
293
|
+
if res != BUFFER_TOO_SMALL
|
294
|
+
raise(ThemisError,
|
295
|
+
"Secure Session failed making connection request: #{res}")
|
296
|
+
end
|
297
|
+
connect_request = FFI::MemoryPointer.new(
|
298
|
+
:char, connect_request_length.read_uint)
|
299
|
+
res = secure_session_generate_connect_request(
|
300
|
+
@session, connect_request, connect_request_length)
|
301
|
+
if res != SUCCESS
|
302
|
+
raise(ThemisError,
|
303
|
+
"Secure Session failed making connection request: #{res}")
|
304
|
+
end
|
305
|
+
connect_request.get_bytes(0, connect_request_length.read_uint)
|
306
|
+
end
|
307
|
+
|
308
|
+
def unwrap(message)
|
309
|
+
message_, message_length_ = string_to_pointer_size message
|
310
|
+
unwrapped_message_length = FFI::MemoryPointer.new(:uint)
|
311
|
+
|
312
|
+
res = secure_session_unwrap(
|
313
|
+
@session, message_, message_length_, nil, unwrapped_message_length)
|
314
|
+
return SUCCESS, '' if res == SUCCESS
|
315
|
+
if res != BUFFER_TOO_SMALL
|
316
|
+
raise ThemisError, "Secure Session failed decrypting: #{res}"
|
317
|
+
end
|
318
|
+
|
319
|
+
unwrapped_message = FFI::MemoryPointer.new(
|
320
|
+
:char, unwrapped_message_length.read_uint)
|
321
|
+
res = secure_session_unwrap(@session, message_, message_length_,
|
322
|
+
unwrapped_message, unwrapped_message_length)
|
323
|
+
if res != SUCCESS && res != SEND_AS_IS
|
324
|
+
raise ThemisError, "Secure Session failed decrypting: #{res}"
|
325
|
+
end
|
326
|
+
|
327
|
+
[res, unwrapped_message.get_bytes(0, unwrapped_message_length.read_uint)]
|
328
|
+
end
|
329
|
+
|
330
|
+
def wrap(message)
|
331
|
+
message_, message_length_ = string_to_pointer_size(message)
|
332
|
+
|
333
|
+
wrapped_message_length = FFI::MemoryPointer.new(:uint)
|
334
|
+
res = secure_session_wrap(
|
335
|
+
@session, message_, message_length_, nil, wrapped_message_length)
|
336
|
+
if res != BUFFER_TOO_SMALL
|
337
|
+
raise ThemisError, "Secure Session failed encrypting: #{res}"
|
338
|
+
end
|
339
|
+
|
340
|
+
wrapped_message = FFI::MemoryPointer.new(
|
341
|
+
:char, wrapped_message_length.read_uint)
|
342
|
+
res = secure_session_wrap(@session, message_, message_length_,
|
343
|
+
wrapped_message, wrapped_message_length)
|
344
|
+
if res != SUCCESS && res != SEND_AS_IS
|
345
|
+
raise ThemisError, "Secure Session failed encrypting: #{res}"
|
346
|
+
end
|
347
|
+
|
348
|
+
wrapped_message.get_bytes(0, wrapped_message_length.read_uint)
|
349
|
+
end
|
350
|
+
|
351
|
+
def finalize
|
352
|
+
res = secure_session_destroy(@session)
|
353
|
+
raise ThemisError, 'Secure Session failed destroying' if res != SUCCESS
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
class Smessage
|
358
|
+
include ThemisCommon
|
359
|
+
include ThemisImport
|
360
|
+
|
361
|
+
def initialize(private_key, peer_public_key)
|
362
|
+
if not Themis.valid_key(private_key)
|
363
|
+
raise ThemisError, "Secure Message: invalid private key"
|
364
|
+
end
|
365
|
+
if not Themis.valid_key(peer_public_key)
|
366
|
+
raise ThemisError, "Secure Message: invalid public key"
|
367
|
+
end
|
368
|
+
if not Themis.private_key(private_key)
|
369
|
+
raise ThemisError, "Secure Message: public key used instead of private"
|
370
|
+
end
|
371
|
+
if not Themis.public_key(peer_public_key)
|
372
|
+
raise ThemisError, "Secure Message: private key used instead of public"
|
373
|
+
end
|
374
|
+
|
375
|
+
@private_key, @private_key_length = string_to_pointer_size(private_key)
|
376
|
+
@peer_public_key, @peer_public_key_length =
|
377
|
+
string_to_pointer_size(peer_public_key)
|
378
|
+
end
|
379
|
+
|
380
|
+
def wrap(message)
|
381
|
+
message_, message_length_ = string_to_pointer_size(message)
|
382
|
+
|
383
|
+
wrapped_message_length = FFI::MemoryPointer.new(:uint)
|
384
|
+
res = themis_secure_message_encrypt(
|
385
|
+
@private_key, @private_key_length, @peer_public_key,
|
386
|
+
@peer_public_key_length, message_, message_length_,
|
387
|
+
nil, wrapped_message_length)
|
388
|
+
if res != BUFFER_TOO_SMALL
|
389
|
+
raise ThemisError, "Secure Message failed to encrypt: #{res}"
|
390
|
+
end
|
391
|
+
|
392
|
+
wrapped_message = FFI::MemoryPointer.new(
|
393
|
+
:char, wrapped_message_length.read_uint)
|
394
|
+
res = themis_secure_message_encrypt(
|
395
|
+
@private_key, @private_key_length, @peer_public_key,
|
396
|
+
@peer_public_key_length, message_, message_length_,
|
397
|
+
wrapped_message, wrapped_message_length)
|
398
|
+
if res != SUCCESS
|
399
|
+
raise ThemisError, "Secure Message failed to encrypt: #{res}"
|
400
|
+
end
|
401
|
+
|
402
|
+
wrapped_message.get_bytes(0, wrapped_message_length.read_uint)
|
403
|
+
end
|
404
|
+
|
405
|
+
def unwrap(message)
|
406
|
+
message_, message_length_ = string_to_pointer_size(message)
|
407
|
+
unwrapped_message_length = FFI::MemoryPointer.new(:uint)
|
408
|
+
res = themis_secure_message_decrypt(
|
409
|
+
@private_key, @private_key_length, @peer_public_key,
|
410
|
+
@peer_public_key_length, message_, message_length_,
|
411
|
+
nil, unwrapped_message_length)
|
412
|
+
if res != BUFFER_TOO_SMALL
|
413
|
+
raise ThemisError, "Secure Message failed to decrypt: #{res}"
|
414
|
+
end
|
415
|
+
|
416
|
+
unwrapped_message = FFI::MemoryPointer.new(
|
417
|
+
:char, unwrapped_message_length.read_uint)
|
418
|
+
res = themis_secure_message_decrypt(
|
419
|
+
@private_key, @private_key_length, @peer_public_key,
|
420
|
+
@peer_public_key_length, message_, message_length_,
|
421
|
+
unwrapped_message, unwrapped_message_length)
|
422
|
+
if res != SUCCESS
|
423
|
+
raise ThemisError, "Secure Message failed to decrypt: #{res}"
|
424
|
+
end
|
425
|
+
|
426
|
+
unwrapped_message.get_bytes(0, unwrapped_message_length.read_uint)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def Ssign(*args)
|
431
|
+
s_sign(*args)
|
432
|
+
end
|
433
|
+
deprecate :Ssign, :s_sign, 2018, 6
|
434
|
+
|
435
|
+
def s_sign(private_key, message)
|
436
|
+
if not valid_key(private_key)
|
437
|
+
raise ThemisError, "Secure Message: invalid private key"
|
438
|
+
end
|
439
|
+
if not private_key(private_key)
|
440
|
+
raise ThemisError, "Secure Message: public key used instead of private"
|
441
|
+
end
|
442
|
+
|
443
|
+
private_key_, private_key_length_ = string_to_pointer_size(private_key)
|
444
|
+
message_, message_length_ = string_to_pointer_size(message)
|
445
|
+
|
446
|
+
wrapped_message_length = FFI::MemoryPointer.new(:uint)
|
447
|
+
res = themis_secure_message_sign(
|
448
|
+
private_key_, private_key_length_, message_,
|
449
|
+
message_length_, nil, wrapped_message_length)
|
450
|
+
if res != BUFFER_TOO_SMALL
|
451
|
+
raise ThemisError, "Secure Message failed to sign: #{res}"
|
452
|
+
end
|
453
|
+
|
454
|
+
wrapped_message = FFI::MemoryPointer.new(
|
455
|
+
:char, wrapped_message_length.read_uint)
|
456
|
+
res = themis_secure_message_sign(
|
457
|
+
private_key_, private_key_length_, message_,
|
458
|
+
message_length_, wrapped_message, wrapped_message_length)
|
459
|
+
if res != SUCCESS
|
460
|
+
raise ThemisError, "Secure Message failed to sign: #{res}"
|
461
|
+
end
|
462
|
+
|
463
|
+
wrapped_message.get_bytes(0, wrapped_message_length.read_uint)
|
464
|
+
end
|
465
|
+
|
466
|
+
def Sverify(*args)
|
467
|
+
s_verify(*args)
|
468
|
+
end
|
469
|
+
deprecate :Sverify, :s_verify, 2018, 6
|
470
|
+
|
471
|
+
def s_verify(peer_public_key, message)
|
472
|
+
if not valid_key(peer_public_key)
|
473
|
+
raise ThemisError, "Secure Message: invalid public key"
|
474
|
+
end
|
475
|
+
if not public_key(peer_public_key)
|
476
|
+
raise ThemisError, "Secure Message: private key used instead of public"
|
477
|
+
end
|
478
|
+
|
479
|
+
public_key_, public_key_length_ = string_to_pointer_size(peer_public_key)
|
480
|
+
message_, message_length_ = string_to_pointer_size(message)
|
481
|
+
|
482
|
+
unwrapped_message_length = FFI::MemoryPointer.new(:uint)
|
483
|
+
res = themis_secure_message_verify(
|
484
|
+
public_key_, public_key_length_, message_,
|
485
|
+
message_length_, nil, unwrapped_message_length)
|
486
|
+
if res != BUFFER_TOO_SMALL
|
487
|
+
raise ThemisError, "Secure Message failed to verify: #{res}"
|
488
|
+
end
|
489
|
+
|
490
|
+
unwrapped_message = FFI::MemoryPointer.new(
|
491
|
+
:char, unwrapped_message_length.read_uint)
|
492
|
+
res = themis_secure_message_verify(
|
493
|
+
public_key_, public_key_length_, message_,
|
494
|
+
message_length_, unwrapped_message, unwrapped_message_length)
|
495
|
+
if res != SUCCESS
|
496
|
+
raise ThemisError, "Secure Message failed to verify: #{res}"
|
497
|
+
end
|
498
|
+
|
499
|
+
unwrapped_message.get_bytes(0, unwrapped_message_length.read_uint)
|
500
|
+
end
|
501
|
+
|
502
|
+
def gen_sym_key
|
503
|
+
key_length = FFI::MemoryPointer.new(:uint)
|
504
|
+
|
505
|
+
res = themis_gen_sym_key(nil, key_length)
|
506
|
+
if res != BUFFER_TOO_SMALL
|
507
|
+
raise ThemisError, "failed to get symmetric key size: #{res}"
|
508
|
+
end
|
509
|
+
|
510
|
+
key = FFI::MemoryPointer.new(:char, key_length.read_uint)
|
511
|
+
|
512
|
+
res = themis_gen_sym_key(key, key_length)
|
513
|
+
if res != SUCCESS
|
514
|
+
raise ThemisError, "failed to generate symmetric key: #{res}"
|
515
|
+
end
|
516
|
+
|
517
|
+
return key.get_bytes(0, key_length.read_uint)
|
518
|
+
end
|
519
|
+
|
520
|
+
# Scell base class is retained for compatibility.
|
521
|
+
# New code should use ScellSeal, ScellTokenProtect, or ScellContextImprint.
|
522
|
+
class Scell
|
523
|
+
include ThemisCommon
|
524
|
+
include ThemisImport
|
525
|
+
|
526
|
+
SEAL_MODE = 0
|
527
|
+
TOKEN_PROTECT_MODE = 1
|
528
|
+
CONTEXT_IMPRINT_MODE = 2
|
529
|
+
|
530
|
+
def initialize(key, mode)
|
531
|
+
# We could have replaced this with "self.new" but it's not possible
|
532
|
+
# to override new *and* keep Scell as superclass of ScellSeal et al.
|
533
|
+
# So we keep an instance of appropriate class here and never call
|
534
|
+
# superclass initialize in subclasses.
|
535
|
+
case mode
|
536
|
+
when SEAL_MODE
|
537
|
+
@cell = ScellSeal.new(key)
|
538
|
+
when TOKEN_PROTECT_MODE
|
539
|
+
@cell = ScellTokenProtect.new(key)
|
540
|
+
when CONTEXT_IMPRINT_MODE
|
541
|
+
@cell = ScellContextImprint.new(key)
|
542
|
+
else
|
543
|
+
raise ThemisError, "unknown Secure Cell mode: #{mode}"
|
544
|
+
end
|
545
|
+
warn "NOTE: #{self.class.name} is deprecated; use #{@cell.class.name} instead."
|
546
|
+
end
|
547
|
+
|
548
|
+
def encrypt(message, context = nil)
|
549
|
+
@cell.encrypt(message, context)
|
550
|
+
end
|
551
|
+
|
552
|
+
def decrypt(message, context = nil)
|
553
|
+
@cell.decrypt(message, context)
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
557
|
+
# Secure Cell in Seal mode.
|
558
|
+
class ScellSeal < Scell
|
559
|
+
include ThemisCommon
|
560
|
+
include ThemisImport
|
561
|
+
|
562
|
+
# Make a new Secure Cell with given key.
|
563
|
+
# The key must not be empty and is treated as binary data.
|
564
|
+
# You can use Themis::gen_sym_key to generate new keys.
|
565
|
+
def initialize(key)
|
566
|
+
if empty? key
|
567
|
+
raise ThemisError, "key cannot be empty"
|
568
|
+
end
|
569
|
+
@key, @key_length = string_to_pointer_size(key)
|
570
|
+
end
|
571
|
+
|
572
|
+
# Encrypts message with given optional context.
|
573
|
+
# The context is cryptographically combined with message but is not included
|
574
|
+
# into encrypted data, you will need to provide the same context for decryption.
|
575
|
+
# Resulting encrypted message includes authentication token.
|
576
|
+
# Message must not be empty, but context may be omitted.
|
577
|
+
# Both message and context are treated as binary data.
|
578
|
+
def encrypt(message, context = nil)
|
579
|
+
if empty? message
|
580
|
+
raise ThemisError, "message cannot be empty"
|
581
|
+
end
|
582
|
+
|
583
|
+
message_, message_length_ = string_to_pointer_size(message)
|
584
|
+
context_, context_length_ =
|
585
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
586
|
+
|
587
|
+
encrypted_length = FFI::MemoryPointer.new(:uint)
|
588
|
+
res = themis_secure_cell_encrypt_seal(
|
589
|
+
@key, @key_length, context_, context_length_,
|
590
|
+
message_, message_length_, nil, encrypted_length)
|
591
|
+
if res != BUFFER_TOO_SMALL
|
592
|
+
raise ThemisError.new(res), "encrypt failed"
|
593
|
+
end
|
594
|
+
|
595
|
+
encrypted_message = FFI::MemoryPointer.new(:char, encrypted_length.read_uint)
|
596
|
+
res = themis_secure_cell_encrypt_seal(
|
597
|
+
@key, @key_length, context_, context_length_,
|
598
|
+
message_, message_length_, encrypted_message, encrypted_length)
|
599
|
+
if res != SUCCESS
|
600
|
+
raise ThemisError.new(res), "encrypt failed"
|
601
|
+
end
|
602
|
+
|
603
|
+
encrypted_message.get_bytes(0, encrypted_length.read_uint)
|
604
|
+
end
|
605
|
+
|
606
|
+
# Decrypts message with given context.
|
607
|
+
# The context must be the same as the one used during encryption,
|
608
|
+
# or be omitted or set to nil if no context were used.
|
609
|
+
# Decrypted message is returned as binary data.
|
610
|
+
def decrypt(message, context = nil)
|
611
|
+
if empty? message
|
612
|
+
raise ThemisError, "message cannot be empty"
|
613
|
+
end
|
614
|
+
|
615
|
+
message_, message_length_ = string_to_pointer_size(message)
|
616
|
+
context_, context_length_ =
|
617
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
618
|
+
|
619
|
+
decrypted_length = FFI::MemoryPointer.new(:uint)
|
620
|
+
res = themis_secure_cell_decrypt_seal(
|
621
|
+
@key, @key_length, context_, context_length_,
|
622
|
+
message_, message_length_, nil, decrypted_length)
|
623
|
+
if res != BUFFER_TOO_SMALL
|
624
|
+
raise ThemisError.new(res), "decrypt failed"
|
625
|
+
end
|
626
|
+
|
627
|
+
decrypted_message = FFI::MemoryPointer.new(:char, decrypted_length.read_uint)
|
628
|
+
res = themis_secure_cell_decrypt_seal(
|
629
|
+
@key, @key_length, context_, context_length_,
|
630
|
+
message_, message_length_, decrypted_message, decrypted_length)
|
631
|
+
if res != SUCCESS
|
632
|
+
raise ThemisError.new(res), "decrypt failed"
|
633
|
+
end
|
634
|
+
|
635
|
+
decrypted_message.get_bytes(0, decrypted_length.read_uint)
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
# Secure Cell in Seal mode.
|
640
|
+
class ScellSealPassphrase < ScellSeal
|
641
|
+
include ThemisCommon
|
642
|
+
include ThemisImport
|
643
|
+
|
644
|
+
# Make a new Secure Cell with given passphrase.
|
645
|
+
# The passphrase must not be empty.
|
646
|
+
# If the passphrase is not binary it will be encoded in UTF-8 by default,
|
647
|
+
# you can use optional "encoding:" argument to use a different encoding.
|
648
|
+
def initialize(passphrase, encoding: Encoding::UTF_8)
|
649
|
+
if empty? passphrase
|
650
|
+
raise ThemisError, "passphrase cannot be empty"
|
651
|
+
end
|
652
|
+
if passphrase.encoding != Encoding::BINARY
|
653
|
+
passphrase = passphrase.encode(encoding)
|
654
|
+
end
|
655
|
+
@passphrase, @passphrase_length = string_to_pointer_size(passphrase)
|
656
|
+
end
|
657
|
+
|
658
|
+
# Encrypts message with given optional context.
|
659
|
+
# The context is cryptographically combined with message but is not included
|
660
|
+
# into encrypted data, you will need to provide the same context for decryption.
|
661
|
+
# Resulting encrypted message includes authentication token.
|
662
|
+
# Message must not be empty, but context may be omitted.
|
663
|
+
# Both message and context are treated as binary data.
|
664
|
+
def encrypt(message, context = nil)
|
665
|
+
if empty? message
|
666
|
+
raise ThemisError, "message cannot be empty"
|
667
|
+
end
|
668
|
+
|
669
|
+
message_, message_length_ = string_to_pointer_size(message)
|
670
|
+
context_, context_length_ =
|
671
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
672
|
+
|
673
|
+
encrypted_length = FFI::MemoryPointer.new(:uint)
|
674
|
+
res = themis_secure_cell_encrypt_seal_with_passphrase(
|
675
|
+
@passphrase, @passphrase_length, context_, context_length_,
|
676
|
+
message_, message_length_, nil, encrypted_length)
|
677
|
+
if res != BUFFER_TOO_SMALL
|
678
|
+
raise ThemisError.new(res), "encrypt failed"
|
679
|
+
end
|
680
|
+
|
681
|
+
encrypted_message = FFI::MemoryPointer.new(:char, encrypted_length.read_uint)
|
682
|
+
res = themis_secure_cell_encrypt_seal_with_passphrase(
|
683
|
+
@passphrase, @passphrase_length, context_, context_length_,
|
684
|
+
message_, message_length_, encrypted_message, encrypted_length)
|
685
|
+
if res != SUCCESS
|
686
|
+
raise ThemisError.new(res), "encrypt failed"
|
687
|
+
end
|
688
|
+
|
689
|
+
encrypted_message.get_bytes(0, encrypted_length.read_uint)
|
690
|
+
end
|
691
|
+
|
692
|
+
# Decrypts message with given context.
|
693
|
+
# The context must be the same as the one used during encryption,
|
694
|
+
# or be omitted or set to nil if no context were used.
|
695
|
+
# Decrypted message is returned as binary data.
|
696
|
+
def decrypt(message, context = nil)
|
697
|
+
if empty? message
|
698
|
+
raise ThemisError, "message cannot be empty"
|
699
|
+
end
|
700
|
+
|
701
|
+
message_, message_length_ = string_to_pointer_size(message)
|
702
|
+
context_, context_length_ =
|
703
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
704
|
+
|
705
|
+
decrypted_length = FFI::MemoryPointer.new(:uint)
|
706
|
+
res = themis_secure_cell_decrypt_seal_with_passphrase(
|
707
|
+
@passphrase, @passphrase_length, context_, context_length_,
|
708
|
+
message_, message_length_, nil, decrypted_length)
|
709
|
+
if res != BUFFER_TOO_SMALL
|
710
|
+
raise ThemisError.new(res), "decrypt failed"
|
711
|
+
end
|
712
|
+
|
713
|
+
decrypted_message = FFI::MemoryPointer.new(:char, decrypted_length.read_uint)
|
714
|
+
res = themis_secure_cell_decrypt_seal_with_passphrase(
|
715
|
+
@passphrase, @passphrase_length, context_, context_length_,
|
716
|
+
message_, message_length_, decrypted_message, decrypted_length)
|
717
|
+
if res != SUCCESS
|
718
|
+
raise ThemisError.new(res), "decrypt failed"
|
719
|
+
end
|
720
|
+
|
721
|
+
decrypted_message.get_bytes(0, decrypted_length.read_uint)
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
# Secure Cell in Token Protect mode.
|
726
|
+
class ScellTokenProtect < Scell
|
727
|
+
include ThemisCommon
|
728
|
+
include ThemisImport
|
729
|
+
|
730
|
+
# Make a new Secure Cell with given key.
|
731
|
+
# The key must not be empty and is treated as binary data.
|
732
|
+
# You can use Themis::gen_sym_key to generate new keys.
|
733
|
+
def initialize(key)
|
734
|
+
if empty? key
|
735
|
+
raise ThemisError, "key cannot be empty"
|
736
|
+
end
|
737
|
+
@key, @key_length = string_to_pointer_size(key)
|
738
|
+
end
|
739
|
+
|
740
|
+
# Encrypts message with given optional context.
|
741
|
+
# The context is cryptographically combined with message but is not included
|
742
|
+
# into encrypted data, you will need to provide the same context for decryption.
|
743
|
+
# Resulting encrypted message (the same length as input) and authentication token
|
744
|
+
# are returned separately; you will need to provide them both for decryption.
|
745
|
+
# Message must not be empty, but context may be omitted.
|
746
|
+
# Both message and context are treated as binary data.
|
747
|
+
def encrypt(message, context = nil)
|
748
|
+
if empty? message
|
749
|
+
raise ThemisError, "message cannot be empty"
|
750
|
+
end
|
751
|
+
|
752
|
+
message_, message_length_ = string_to_pointer_size(message)
|
753
|
+
context_, context_length_ =
|
754
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
755
|
+
|
756
|
+
auth_token_length = FFI::MemoryPointer.new(:uint)
|
757
|
+
encrypted_length = FFI::MemoryPointer.new(:uint)
|
758
|
+
res = themis_secure_cell_encrypt_token_protect(
|
759
|
+
@key, @key_length, context_, context_length_, message_, message_length_,
|
760
|
+
nil, auth_token_length, nil, encrypted_length)
|
761
|
+
if res != BUFFER_TOO_SMALL
|
762
|
+
raise ThemisError.new(res), "encrypt failed"
|
763
|
+
end
|
764
|
+
|
765
|
+
auth_token = FFI::MemoryPointer.new(:char, auth_token_length.read_uint)
|
766
|
+
encrypted_message = FFI::MemoryPointer.new(:char, encrypted_length.read_uint)
|
767
|
+
res = themis_secure_cell_encrypt_token_protect(
|
768
|
+
@key, @key_length, context_, context_length_, message_, message_length_,
|
769
|
+
auth_token, auth_token_length, encrypted_message, encrypted_length)
|
770
|
+
if res != SUCCESS
|
771
|
+
raise ThemisError.new(res), "encrypt failed"
|
772
|
+
end
|
773
|
+
|
774
|
+
[encrypted_message.get_bytes(0, encrypted_length.read_uint),
|
775
|
+
auth_token.get_bytes(0, auth_token_length.read_uint),]
|
776
|
+
end
|
777
|
+
|
778
|
+
# Decrypts message with given authentication token and context.
|
779
|
+
# The context must be the same as the one used during encryption,
|
780
|
+
# or be omitted or set to nil if no context were used.
|
781
|
+
# The token also must be the one returned during encryption.
|
782
|
+
# Decrypted message is returned as binary data.
|
783
|
+
def decrypt(message, token = nil, context = nil)
|
784
|
+
# For compatibility with older API we allow the message and token to be
|
785
|
+
# provided as a list in the first argument. In this case the second one
|
786
|
+
# contains (an optional) context. Then there is no third argument.
|
787
|
+
if message.kind_of? Array
|
788
|
+
context = token
|
789
|
+
message, token = message
|
790
|
+
end
|
791
|
+
|
792
|
+
if empty? message
|
793
|
+
raise ThemisError, "message cannot be empty"
|
794
|
+
end
|
795
|
+
if empty? token
|
796
|
+
raise ThemisError, "token cannot be empty"
|
797
|
+
end
|
798
|
+
|
799
|
+
message_, message_length_ = string_to_pointer_size(message)
|
800
|
+
token_, token_length_ = string_to_pointer_size(token)
|
801
|
+
context_, context_length_ =
|
802
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
803
|
+
|
804
|
+
decrypted_length = FFI::MemoryPointer.new(:uint)
|
805
|
+
res = themis_secure_cell_decrypt_token_protect(
|
806
|
+
@key, @key_length, context_, context_length_,
|
807
|
+
message_, message_length_, token_, token_length_,
|
808
|
+
nil, decrypted_length)
|
809
|
+
if res != BUFFER_TOO_SMALL
|
810
|
+
raise ThemisError.new(res), "decrypt failed"
|
811
|
+
end
|
812
|
+
|
813
|
+
decrypted_message = FFI::MemoryPointer.new(:char, decrypted_length.read_uint)
|
814
|
+
res = themis_secure_cell_decrypt_token_protect(
|
815
|
+
@key, @key_length, context_, context_length_,
|
816
|
+
message_, message_length_, token_, token_length_,
|
817
|
+
decrypted_message, decrypted_length)
|
818
|
+
if res != SUCCESS
|
819
|
+
raise ThemisError.new(res), "decrypt failed"
|
820
|
+
end
|
821
|
+
|
822
|
+
decrypted_message.get_bytes(0, decrypted_length.read_uint)
|
823
|
+
end
|
824
|
+
end
|
825
|
+
|
826
|
+
# Secure Cell in Context Imprint mode.
|
827
|
+
class ScellContextImprint < Scell
|
828
|
+
include ThemisCommon
|
829
|
+
include ThemisImport
|
830
|
+
|
831
|
+
# Make a new Secure Cell with given key.
|
832
|
+
# The key must not be empty and is treated as binary data.
|
833
|
+
# You can use Themis::gen_sym_key to generate new keys.
|
834
|
+
def initialize(key)
|
835
|
+
if empty? key
|
836
|
+
raise ThemisError, "key cannot be empty"
|
837
|
+
end
|
838
|
+
@key, @key_length = string_to_pointer_size(key)
|
839
|
+
end
|
840
|
+
|
841
|
+
# Encrypts message with given context.
|
842
|
+
# The context is cryptographically combined with message but is not included
|
843
|
+
# into encrypted data, you will need to provide the same context for decryption.
|
844
|
+
# Resulting encrypted message has the same length as input and does not include
|
845
|
+
# authentication data, so its integrity cannot be verified.
|
846
|
+
# Message and context must not be empty, both are treated as binary data.
|
847
|
+
def encrypt(message, context)
|
848
|
+
if empty? message
|
849
|
+
raise ThemisError, "message cannot be empty"
|
850
|
+
end
|
851
|
+
if empty? context
|
852
|
+
raise ThemisError, "context cannot be empty"
|
853
|
+
end
|
854
|
+
|
855
|
+
message_, message_length_ = string_to_pointer_size(message)
|
856
|
+
context_, context_length_ =
|
857
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
858
|
+
|
859
|
+
encrypted_length = FFI::MemoryPointer.new(:uint)
|
860
|
+
res = themis_secure_cell_encrypt_context_imprint(
|
861
|
+
@key, @key_length, message_, message_length_,
|
862
|
+
context_, context_length_, nil, encrypted_length)
|
863
|
+
if res != BUFFER_TOO_SMALL
|
864
|
+
raise ThemisError.new(res), "encrypt failed"
|
865
|
+
end
|
866
|
+
|
867
|
+
encrypted_message = FFI::MemoryPointer.new(:char, encrypted_length.read_uint)
|
868
|
+
res = themis_secure_cell_encrypt_context_imprint(
|
869
|
+
@key, @key_length, message_, message_length_,
|
870
|
+
context_, context_length_, encrypted_message, encrypted_length)
|
871
|
+
if res != SUCCESS
|
872
|
+
raise ThemisError.new(res), "encrypt failed"
|
873
|
+
end
|
874
|
+
|
875
|
+
encrypted_message.get_bytes(0, encrypted_length.read_uint)
|
876
|
+
end
|
877
|
+
|
878
|
+
# Decrypts message with given context.
|
879
|
+
# The context must be the same as the one used during encryption.
|
880
|
+
# Since Context Imprint mode does not include authentication data,
|
881
|
+
# integrity of the resulting message is not guaranteed.
|
882
|
+
# You need to verify it via some other means.
|
883
|
+
# Decrypted message is returned as binary data.
|
884
|
+
def decrypt(message, context)
|
885
|
+
if empty? message
|
886
|
+
raise ThemisError, "message cannot be empty"
|
887
|
+
end
|
888
|
+
if empty? context
|
889
|
+
raise ThemisError, "message cannot be empty"
|
890
|
+
end
|
891
|
+
|
892
|
+
message_, message_length_ = string_to_pointer_size(message)
|
893
|
+
context_, context_length_ =
|
894
|
+
context.nil? ? [nil, 0] : string_to_pointer_size(context)
|
895
|
+
|
896
|
+
decrypted_length = FFI::MemoryPointer.new(:uint)
|
897
|
+
res = themis_secure_cell_decrypt_context_imprint(
|
898
|
+
@key, @key_length, message_, message_length_,
|
899
|
+
context_, context_length_, nil, decrypted_length)
|
900
|
+
if res != BUFFER_TOO_SMALL
|
901
|
+
raise ThemisError.new(res), "decrypt failed"
|
902
|
+
end
|
903
|
+
|
904
|
+
decrypted_message = FFI::MemoryPointer.new(:char, decrypted_length.read_uint)
|
905
|
+
res = themis_secure_cell_decrypt_context_imprint(
|
906
|
+
@key, @key_length, message_, message_length_,
|
907
|
+
context_, context_length_, decrypted_message, decrypted_length)
|
908
|
+
if res != SUCCESS
|
909
|
+
raise ThemisError.new(res), "decrypt failed"
|
910
|
+
end
|
911
|
+
|
912
|
+
decrypted_message.get_bytes(0, decrypted_length.read_uint)
|
913
|
+
end
|
914
|
+
end
|
915
|
+
|
916
|
+
class Scomparator
|
917
|
+
include ThemisCommon
|
918
|
+
include ThemisImport
|
919
|
+
|
920
|
+
MATCH = 21
|
921
|
+
NOT_MATCH = 22
|
922
|
+
NOT_READY = 0
|
923
|
+
|
924
|
+
def initialize(shared_secret)
|
925
|
+
shared_secret_buf, shared_secret_length =
|
926
|
+
string_to_pointer_size(shared_secret)
|
927
|
+
@comparator = secure_comparator_create
|
928
|
+
raise ThemisError, 'Secure Comparator failed creating' if @comparator.null?
|
929
|
+
res = secure_comparator_append_secret(
|
930
|
+
@comparator, shared_secret_buf, shared_secret_length)
|
931
|
+
if res != SUCCESS
|
932
|
+
raise ThemisError, 'Secure Comparator failed appending secret'
|
933
|
+
end
|
934
|
+
end
|
935
|
+
|
936
|
+
def finalize
|
937
|
+
res = secure_comparator_destroy(@comparator)
|
938
|
+
if res != SUCCESS
|
939
|
+
raise ThemisError, 'Secure Comparator failed destroying'
|
940
|
+
end
|
941
|
+
end
|
942
|
+
|
943
|
+
def begin_compare
|
944
|
+
res_length = FFI::MemoryPointer.new(:uint)
|
945
|
+
res = secure_comparator_begin_compare(@comparator, nil, res_length)
|
946
|
+
if res != BUFFER_TOO_SMALL
|
947
|
+
raise(ThemisError,
|
948
|
+
'Secure Comparator failed making initialisation message')
|
949
|
+
end
|
950
|
+
|
951
|
+
res_buffer = FFI::MemoryPointer.new(:char, res_length.read_uint)
|
952
|
+
res = secure_comparator_begin_compare(@comparator, res_buffer, res_length)
|
953
|
+
if res != SUCCESS && res != SEND_AS_IS
|
954
|
+
raise(ThemisError,
|
955
|
+
'Secure Comparator failed making initialisation message')
|
956
|
+
end
|
957
|
+
|
958
|
+
res_buffer.get_bytes(0, res_length.read_uint)
|
959
|
+
end
|
960
|
+
|
961
|
+
def proceed_compare(control_message)
|
962
|
+
message, message_length = string_to_pointer_size(control_message)
|
963
|
+
res_length = FFI::MemoryPointer.new(:uint)
|
964
|
+
|
965
|
+
res = secure_comparator_proceed_compare(
|
966
|
+
@comparator, message, message_length, nil, res_length)
|
967
|
+
return '' if res == SUCCESS
|
968
|
+
if res != BUFFER_TOO_SMALL
|
969
|
+
raise ThemisError, 'Secure Comparator failed proceeding message'
|
970
|
+
end
|
971
|
+
|
972
|
+
res_buffer = FFI::MemoryPointer.new(:char, res_length.read_uint)
|
973
|
+
res = secure_comparator_proceed_compare(
|
974
|
+
@comparator, message, message_length, res_buffer, res_length)
|
975
|
+
if res != SUCCESS && res != SEND_AS_IS
|
976
|
+
raise ThemisError, 'Secure Comparator failed proceeding message'
|
977
|
+
end
|
978
|
+
|
979
|
+
res_buffer.get_bytes(0, res_length.read_uint)
|
980
|
+
end
|
981
|
+
|
982
|
+
def result
|
983
|
+
secure_comparator_get_result(@comparator)
|
984
|
+
end
|
985
|
+
end
|
986
|
+
|
987
|
+
module_function :Ssign
|
988
|
+
module_function :Sverify
|
989
|
+
module_function :s_sign
|
990
|
+
module_function :s_verify
|
991
|
+
module_function :gen_sym_key
|
992
|
+
end
|