self_crypto 0.0.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.
- checksums.yaml +7 -0
- data/Rakefile +19 -0
- data/ext/self_crypto/account.c +292 -0
- data/ext/self_crypto/extconf.rb +15 -0
- data/ext/self_crypto/omemo.c +170 -0
- data/ext/self_crypto/pk.c +15 -0
- data/ext/self_crypto/pk_decryption.c +129 -0
- data/ext/self_crypto/pk_encryption.c +93 -0
- data/ext/self_crypto/pk_signing.c +102 -0
- data/ext/self_crypto/sas.c +190 -0
- data/ext/self_crypto/self_crypto.c +68 -0
- data/ext/self_crypto/self_crypto.h +15 -0
- data/ext/self_crypto/session.c +363 -0
- data/ext/self_crypto/utility.c +143 -0
- data/lib/self_crypto.rb +14 -0
- data/lib/self_crypto/account.rb +30 -0
- data/lib/self_crypto/group_message.rb +34 -0
- data/lib/self_crypto/group_session.rb +8 -0
- data/lib/self_crypto/message.rb +6 -0
- data/lib/self_crypto/olm_error.rb +70 -0
- data/lib/self_crypto/olm_message.rb +25 -0
- data/lib/self_crypto/pre_key_message.rb +6 -0
- data/lib/self_crypto/sas.rb +28 -0
- data/lib/self_crypto/sas_data.rb +71 -0
- data/lib/self_crypto/session.rb +16 -0
- data/lib/self_crypto/utility.rb +7 -0
- data/lib/self_crypto/version.rb +5 -0
- data/test/examples/test_bob_no_answer.rb +62 -0
- data/test/examples/test_exchange.rb +60 -0
- data/test/spec/test_account.rb +100 -0
- data/test/unit/test_account_methods.rb +64 -0
- metadata +134 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <assert.h>
|
3
|
+
#include <stdbool.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
|
6
|
+
#include "sodium.h"
|
7
|
+
#include "self_olm/olm.h"
|
8
|
+
#include "self_omemo.h"
|
9
|
+
|
10
|
+
void account_init(void);
|
11
|
+
void session_init(void);
|
12
|
+
void utility_init(void);
|
13
|
+
void group_session_init(void);
|
14
|
+
void pk_init(void);
|
15
|
+
void sas_init(void);
|
16
|
+
|
17
|
+
static VALUE get_olm_version(VALUE self)
|
18
|
+
{
|
19
|
+
char buffer[20U];
|
20
|
+
uint8_t major = 0U;
|
21
|
+
uint8_t minor = 0U;
|
22
|
+
uint8_t patch = 0U;
|
23
|
+
|
24
|
+
olm_get_library_version(&major, &minor, &patch);
|
25
|
+
|
26
|
+
snprintf(buffer, sizeof(buffer), "%u.%u.%u", major, minor, patch);
|
27
|
+
|
28
|
+
return rb_str_new2(buffer);
|
29
|
+
}
|
30
|
+
|
31
|
+
void Init_self_crypto(void)
|
32
|
+
{
|
33
|
+
rb_require("openssl");
|
34
|
+
rb_require("json");
|
35
|
+
rb_require("self_crypto/olm_error");
|
36
|
+
|
37
|
+
rb_define_singleton_method(rb_eval_string("SelfCrypto"), "olm_version", get_olm_version, 0);
|
38
|
+
|
39
|
+
account_init();
|
40
|
+
session_init();
|
41
|
+
group_session_init();
|
42
|
+
utility_init();
|
43
|
+
pk_init();
|
44
|
+
sas_init();
|
45
|
+
}
|
46
|
+
|
47
|
+
void raise_olm_error(const char *error)
|
48
|
+
{
|
49
|
+
rb_funcall(rb_eval_string("SelfCrypto::OlmError"), rb_intern("raise_from_string"), 1, rb_str_new2(error));
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE get_random(size_t size)
|
53
|
+
{
|
54
|
+
return rb_funcall(rb_eval_string("OpenSSL::Random"), rb_intern("random_bytes"), 1, SIZET2NUM(size));
|
55
|
+
}
|
56
|
+
|
57
|
+
VALUE dup_string(VALUE str)
|
58
|
+
{
|
59
|
+
return rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
|
60
|
+
}
|
61
|
+
|
62
|
+
void* malloc_or_raise(size_t len) {
|
63
|
+
void * ptr = malloc(len);
|
64
|
+
if (ptr == NULL) {
|
65
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
66
|
+
}
|
67
|
+
return ptr;
|
68
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#ifndef SELF_CRYPTO_H
|
2
|
+
#define SELF_CRYPTO_H
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
|
6
|
+
/* convert error string to exception and raise it */
|
7
|
+
void raise_olm_error(const char *error);
|
8
|
+
VALUE get_random(size_t size);
|
9
|
+
|
10
|
+
/* necessary to avoid copy-on-write weirdness */
|
11
|
+
VALUE dup_string(VALUE str);
|
12
|
+
|
13
|
+
void* malloc_or_raise(size_t len) __attribute__((malloc));
|
14
|
+
|
15
|
+
#endif
|
@@ -0,0 +1,363 @@
|
|
1
|
+
#include "self_olm/olm.h"
|
2
|
+
#include "self_crypto.h"
|
3
|
+
|
4
|
+
static VALUE last_error(VALUE self)
|
5
|
+
{
|
6
|
+
OlmSession *this;
|
7
|
+
Data_Get_Struct(self, OlmSession, this);
|
8
|
+
|
9
|
+
return rb_str_new2(olm_session_last_error(this));
|
10
|
+
}
|
11
|
+
|
12
|
+
static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
13
|
+
{
|
14
|
+
VALUE pickle, password;
|
15
|
+
OlmSession *this;
|
16
|
+
Data_Get_Struct(self, OlmSession, this);
|
17
|
+
|
18
|
+
(void)rb_scan_args(argc, argv, "11", &pickle, &password);
|
19
|
+
|
20
|
+
if(rb_obj_is_kind_of(pickle, rb_cString) != Qtrue){
|
21
|
+
|
22
|
+
rb_raise(rb_eTypeError, "pickle must be kind of String");
|
23
|
+
}
|
24
|
+
|
25
|
+
if(password != Qnil){
|
26
|
+
|
27
|
+
if(rb_obj_is_kind_of(password, rb_cString) != Qtrue){
|
28
|
+
|
29
|
+
rb_raise(rb_eTypeError, "password must be kind of String");
|
30
|
+
}
|
31
|
+
}
|
32
|
+
else{
|
33
|
+
|
34
|
+
password = rb_str_new2("");
|
35
|
+
}
|
36
|
+
|
37
|
+
if(olm_unpickle_session(this, RSTRING_PTR(password), RSTRING_LEN(password), RSTRING_PTR(dup_string(pickle)), RSTRING_LEN(pickle)) == olm_error()){
|
38
|
+
|
39
|
+
raise_olm_error(olm_session_last_error(this));
|
40
|
+
}
|
41
|
+
|
42
|
+
return self;
|
43
|
+
}
|
44
|
+
|
45
|
+
static VALUE initialize_outbound(VALUE self, VALUE account, VALUE identity, VALUE one_time_key)
|
46
|
+
{
|
47
|
+
size_t size;
|
48
|
+
OlmSession *this;
|
49
|
+
OlmAccount *a;
|
50
|
+
|
51
|
+
Data_Get_Struct(self, OlmSession, this);
|
52
|
+
Data_Get_Struct(account, OlmAccount, a);
|
53
|
+
|
54
|
+
size = olm_create_outbound_session_random_length(this);
|
55
|
+
|
56
|
+
if(rb_obj_is_instance_of(account, rb_eval_string("SelfCrypto::Account")) != Qtrue){
|
57
|
+
|
58
|
+
rb_raise(rb_eTypeError, "account must be an instance of SelfCrypto::Account");
|
59
|
+
}
|
60
|
+
if(rb_obj_is_kind_of(identity, rb_eval_string("String")) != Qtrue){
|
61
|
+
|
62
|
+
rb_raise(rb_eTypeError, "identity must be kind of String");
|
63
|
+
}
|
64
|
+
if(rb_obj_is_kind_of(one_time_key, rb_eval_string("String")) != Qtrue){
|
65
|
+
|
66
|
+
rb_raise(rb_eTypeError, "one_time_key must be kind of String");
|
67
|
+
}
|
68
|
+
|
69
|
+
if(olm_create_outbound_session(this, a,
|
70
|
+
RSTRING_PTR(identity), RSTRING_LEN(identity),
|
71
|
+
RSTRING_PTR(one_time_key), RSTRING_LEN(one_time_key),
|
72
|
+
RSTRING_PTR(get_random(size)), size
|
73
|
+
) == olm_error()){
|
74
|
+
raise_olm_error(olm_session_last_error(this));
|
75
|
+
}
|
76
|
+
|
77
|
+
return self;
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE initialize_inbound(int argc, VALUE *argv, VALUE self)
|
81
|
+
{
|
82
|
+
VALUE account, one_time_message, identity;
|
83
|
+
|
84
|
+
identity = Qnil;
|
85
|
+
|
86
|
+
(void)rb_scan_args(argc, argv, "21", &account, &one_time_message, &identity);
|
87
|
+
|
88
|
+
OlmSession *this;
|
89
|
+
Data_Get_Struct(self, OlmSession, this);
|
90
|
+
|
91
|
+
OlmAccount *a;
|
92
|
+
Data_Get_Struct(account, OlmAccount, a);
|
93
|
+
|
94
|
+
if(rb_obj_is_kind_of(one_time_message, rb_eval_string("SelfCrypto::PreKeyMessage")) != Qtrue){
|
95
|
+
|
96
|
+
rb_raise(rb_eTypeError, "one_time_message must be kind of PreKeyMessage");
|
97
|
+
}
|
98
|
+
|
99
|
+
one_time_message = rb_funcall(one_time_message, rb_intern("to_s"), 0);
|
100
|
+
|
101
|
+
if(identity == Qnil){
|
102
|
+
|
103
|
+
if(olm_create_inbound_session(this, a,
|
104
|
+
RSTRING_PTR(dup_string(one_time_message)), RSTRING_LEN(one_time_message)
|
105
|
+
) == olm_error()){
|
106
|
+
raise_olm_error(olm_session_last_error(this));
|
107
|
+
}
|
108
|
+
}
|
109
|
+
else{
|
110
|
+
|
111
|
+
if(olm_create_inbound_session_from(this, a,
|
112
|
+
RSTRING_PTR(identity), RSTRING_LEN(identity),
|
113
|
+
RSTRING_PTR(dup_string(one_time_message)), RSTRING_LEN(one_time_message)
|
114
|
+
) == olm_error()){
|
115
|
+
raise_olm_error(olm_session_last_error(this));
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
return self;
|
120
|
+
}
|
121
|
+
|
122
|
+
static VALUE has_received_message(VALUE self)
|
123
|
+
{
|
124
|
+
OlmSession *this;
|
125
|
+
Data_Get_Struct(self, OlmSession, this);
|
126
|
+
|
127
|
+
return (olm_session_has_received_message(this) == 0) ? Qfalse : Qtrue;
|
128
|
+
}
|
129
|
+
|
130
|
+
static VALUE get_session_id(VALUE self)
|
131
|
+
{
|
132
|
+
OlmSession *this;
|
133
|
+
Data_Get_Struct(self, OlmSession, this);
|
134
|
+
|
135
|
+
size_t size = olm_session_id_length(this);
|
136
|
+
uint8_t buf[size];
|
137
|
+
|
138
|
+
if(olm_session_id(this, buf, size) != size){
|
139
|
+
|
140
|
+
raise_olm_error(olm_session_last_error(this));
|
141
|
+
}
|
142
|
+
|
143
|
+
return rb_str_new((char *)buf, size);
|
144
|
+
}
|
145
|
+
|
146
|
+
static VALUE will_receive(int argc, VALUE *argv, VALUE self)
|
147
|
+
{
|
148
|
+
VALUE one_time_message, identity;
|
149
|
+
size_t result;
|
150
|
+
OlmSession *this;
|
151
|
+
Data_Get_Struct(self, OlmSession, this);
|
152
|
+
|
153
|
+
identity = Qnil;
|
154
|
+
|
155
|
+
(void)rb_scan_args(argc, argv, "11", &one_time_message, &identity);
|
156
|
+
|
157
|
+
if(rb_obj_is_kind_of(one_time_message, rb_eval_string("SelfCrypto::PreKeyMessage")) != Qtrue){
|
158
|
+
|
159
|
+
rb_raise(rb_eTypeError, "one_time_message must be kind of PreKeyMessage");
|
160
|
+
}
|
161
|
+
|
162
|
+
one_time_message = rb_funcall(one_time_message, rb_intern("to_s"), 0);
|
163
|
+
|
164
|
+
if(identity == Qnil){
|
165
|
+
|
166
|
+
result = olm_matches_inbound_session(this,
|
167
|
+
RSTRING_PTR(dup_string(one_time_message)), RSTRING_LEN(one_time_message)
|
168
|
+
);
|
169
|
+
}
|
170
|
+
else{
|
171
|
+
|
172
|
+
result = olm_matches_inbound_session_from(this,
|
173
|
+
RSTRING_PTR(identity), RSTRING_LEN(identity),
|
174
|
+
RSTRING_PTR(dup_string(one_time_message)), RSTRING_LEN(one_time_message)
|
175
|
+
);
|
176
|
+
}
|
177
|
+
|
178
|
+
if(result == olm_error()){
|
179
|
+
|
180
|
+
raise_olm_error(olm_session_last_error(this));
|
181
|
+
}
|
182
|
+
|
183
|
+
return (result == 1) ? Qtrue : Qfalse;
|
184
|
+
}
|
185
|
+
|
186
|
+
static VALUE message_type(VALUE self)
|
187
|
+
{
|
188
|
+
OlmSession *this;
|
189
|
+
VALUE retval;
|
190
|
+
Data_Get_Struct(self, OlmSession, this);
|
191
|
+
|
192
|
+
if(olm_encrypt_message_type(this) == OLM_MESSAGE_TYPE_PRE_KEY){
|
193
|
+
|
194
|
+
retval = rb_eval_string("SelfCrypto::PreKeyMessage");
|
195
|
+
}
|
196
|
+
else if(olm_encrypt_message_type(this) == OLM_MESSAGE_TYPE_MESSAGE){
|
197
|
+
|
198
|
+
retval = rb_eval_string("SelfCrypto::Message");
|
199
|
+
}
|
200
|
+
else{
|
201
|
+
|
202
|
+
rb_bug("olm_encrypt_message_type()");
|
203
|
+
}
|
204
|
+
|
205
|
+
return retval;
|
206
|
+
}
|
207
|
+
|
208
|
+
static VALUE encrypt(VALUE self, VALUE plain)
|
209
|
+
{
|
210
|
+
size_t cipher_size, random_size;
|
211
|
+
void *ptr;
|
212
|
+
OlmSession *this;
|
213
|
+
VALUE retval, type;
|
214
|
+
Data_Get_Struct(self, OlmSession, this);
|
215
|
+
|
216
|
+
cipher_size = olm_encrypt_message_length(this, RSTRING_LEN(plain));
|
217
|
+
random_size = olm_encrypt_random_length(this);
|
218
|
+
|
219
|
+
if((ptr = malloc(cipher_size)) == NULL){
|
220
|
+
|
221
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
222
|
+
}
|
223
|
+
|
224
|
+
type = message_type(self);
|
225
|
+
|
226
|
+
if(olm_encrypt(this, RSTRING_PTR(plain), RSTRING_LEN(plain),
|
227
|
+
RSTRING_PTR(get_random(random_size)), random_size,
|
228
|
+
ptr, cipher_size
|
229
|
+
) == olm_error()){
|
230
|
+
free(ptr);
|
231
|
+
raise_olm_error(olm_session_last_error(this));
|
232
|
+
}
|
233
|
+
|
234
|
+
retval = rb_funcall(type, rb_intern("new"), 1, rb_str_new(ptr, cipher_size));
|
235
|
+
|
236
|
+
free(ptr);
|
237
|
+
|
238
|
+
return retval;
|
239
|
+
}
|
240
|
+
|
241
|
+
static VALUE decrypt(VALUE self, VALUE cipher)
|
242
|
+
{
|
243
|
+
size_t plain_size, plain_max, type;
|
244
|
+
void *ptr;
|
245
|
+
OlmSession *this;
|
246
|
+
VALUE retval, data;
|
247
|
+
Data_Get_Struct(self, OlmSession, this);
|
248
|
+
|
249
|
+
if(rb_obj_is_kind_of(cipher, rb_eval_string("SelfCrypto::Message")) == Qtrue){
|
250
|
+
|
251
|
+
type = OLM_MESSAGE_TYPE_MESSAGE;
|
252
|
+
}
|
253
|
+
else if(rb_obj_is_kind_of(cipher, rb_eval_string("SelfCrypto::PreKeyMessage")) == Qtrue){
|
254
|
+
|
255
|
+
type = OLM_MESSAGE_TYPE_PRE_KEY;
|
256
|
+
}
|
257
|
+
else{
|
258
|
+
|
259
|
+
rb_raise(rb_eTypeError, "cipher must be kind of Message or PreKeyMessage");
|
260
|
+
}
|
261
|
+
|
262
|
+
data = rb_funcall(cipher, rb_intern("to_s"), 0);
|
263
|
+
|
264
|
+
if((plain_max = olm_decrypt_max_plaintext_length(this, type, RSTRING_PTR(dup_string(data)), RSTRING_LEN(data))) == olm_error()){
|
265
|
+
|
266
|
+
raise_olm_error(olm_session_last_error(this));
|
267
|
+
}
|
268
|
+
|
269
|
+
/* size of output will be less than size of input */
|
270
|
+
if((ptr = malloc(plain_max)) == NULL){
|
271
|
+
|
272
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
273
|
+
}
|
274
|
+
|
275
|
+
if((plain_size = olm_decrypt(this,
|
276
|
+
type,
|
277
|
+
RSTRING_PTR(dup_string(data)), RSTRING_LEN(data),
|
278
|
+
ptr, plain_max)) == olm_error())
|
279
|
+
{
|
280
|
+
free(ptr);
|
281
|
+
raise_olm_error(olm_session_last_error(this));
|
282
|
+
}
|
283
|
+
|
284
|
+
retval = rb_str_new(ptr, plain_size);
|
285
|
+
|
286
|
+
free(ptr);
|
287
|
+
|
288
|
+
return retval;
|
289
|
+
}
|
290
|
+
|
291
|
+
static VALUE to_pickle(int argc, VALUE *argv, VALUE self)
|
292
|
+
{
|
293
|
+
VALUE password, retval;
|
294
|
+
OlmSession *this;
|
295
|
+
void *ptr;
|
296
|
+
size_t size;
|
297
|
+
Data_Get_Struct(self, OlmSession, this);
|
298
|
+
|
299
|
+
(void)rb_scan_args(argc, argv, "01", &password);
|
300
|
+
|
301
|
+
password = (password == Qnil) ? rb_str_new2("") : password;
|
302
|
+
|
303
|
+
size = olm_pickle_session_length(this);
|
304
|
+
|
305
|
+
if((ptr = malloc(size)) == NULL){
|
306
|
+
|
307
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
308
|
+
}
|
309
|
+
|
310
|
+
if(olm_pickle_session(this, RSTRING_PTR(password), RSTRING_LEN(password), ptr, size) != size){
|
311
|
+
|
312
|
+
free(ptr);
|
313
|
+
raise_olm_error(olm_session_last_error(this));
|
314
|
+
}
|
315
|
+
|
316
|
+
retval = rb_str_new(ptr, size);
|
317
|
+
|
318
|
+
free(ptr);
|
319
|
+
|
320
|
+
return retval;
|
321
|
+
}
|
322
|
+
|
323
|
+
static void _free(void *ptr)
|
324
|
+
{
|
325
|
+
olm_clear_session(ptr);
|
326
|
+
free(ptr);
|
327
|
+
}
|
328
|
+
|
329
|
+
static VALUE _alloc(VALUE klass)
|
330
|
+
{
|
331
|
+
OlmSession *this;
|
332
|
+
VALUE self;
|
333
|
+
|
334
|
+
self = Data_Wrap_Struct(klass, 0, _free, calloc(1, olm_session_size()));
|
335
|
+
|
336
|
+
Data_Get_Struct(self, OlmSession, this);
|
337
|
+
|
338
|
+
(void)olm_session((void *)this);
|
339
|
+
|
340
|
+
return self;
|
341
|
+
}
|
342
|
+
|
343
|
+
void session_init(void)
|
344
|
+
{
|
345
|
+
VALUE cRubyOLM = rb_define_module("SelfCrypto");
|
346
|
+
VALUE cSession = rb_define_class_under(cRubyOLM, "Session", rb_cObject);
|
347
|
+
VALUE cSessionOut = rb_define_class_under(cRubyOLM, "OutboundSession", cSession);
|
348
|
+
VALUE cSessionIn = rb_define_class_under(cRubyOLM, "InboundSession", cSession);
|
349
|
+
|
350
|
+
rb_define_alloc_func(cSession, _alloc);
|
351
|
+
|
352
|
+
rb_define_method(cSessionOut, "initialize", initialize_outbound, 3);
|
353
|
+
rb_define_method(cSessionIn, "initialize", initialize_inbound, -1);
|
354
|
+
|
355
|
+
rb_define_method(cSession, "initialize", initialize, -1);
|
356
|
+
rb_define_method(cSession, "id", get_session_id, 0);
|
357
|
+
rb_define_method(cSession, "last_error", last_error, 0);
|
358
|
+
rb_define_method(cSession, "has_received_message", has_received_message, 0);
|
359
|
+
rb_define_method(cSession, "encrypt", encrypt, 1);
|
360
|
+
rb_define_method(cSession, "decrypt", decrypt, 1);
|
361
|
+
rb_define_method(cSession, "to_pickle", to_pickle, -1);
|
362
|
+
rb_define_method(cSession, "will_receive?", will_receive, -1);
|
363
|
+
}
|
@@ -0,0 +1,143 @@
|
|
1
|
+
#include "self_olm/olm.h"
|
2
|
+
#include "self_crypto.h"
|
3
|
+
#include "sodium.h"
|
4
|
+
|
5
|
+
static VALUE last_error(VALUE self)
|
6
|
+
{
|
7
|
+
OlmUtility *this;
|
8
|
+
Data_Get_Struct(self, OlmUtility, this);
|
9
|
+
|
10
|
+
return rb_str_new2(olm_utility_last_error(this));
|
11
|
+
}
|
12
|
+
|
13
|
+
static VALUE ed25519_verify(VALUE self, VALUE data, VALUE key, VALUE signature)
|
14
|
+
{
|
15
|
+
VALUE retval = Qtrue;
|
16
|
+
OlmUtility *this;
|
17
|
+
Data_Get_Struct(self, OlmUtility, this);
|
18
|
+
|
19
|
+
if(olm_ed25519_verify(this, RSTRING_PTR(key), RSTRING_LEN(key), RSTRING_PTR(data), RSTRING_LEN(data), RSTRING_PTR(dup_string(signature)), RSTRING_LEN(signature)) == olm_error()){
|
20
|
+
|
21
|
+
retval = Qfalse;
|
22
|
+
}
|
23
|
+
|
24
|
+
return retval;
|
25
|
+
}
|
26
|
+
|
27
|
+
static VALUE ed25519_pk_to_curve25519(VALUE self, VALUE ed25519_pk)
|
28
|
+
{
|
29
|
+
VALUE curve25519_sk;
|
30
|
+
void *pk_ptr, *dec_ptr, *enc_ptr;
|
31
|
+
size_t pk_sz, dec_sz, enc_sz, success;
|
32
|
+
|
33
|
+
if(rb_obj_is_kind_of(ed25519_pk, rb_eval_string("String")) != Qtrue){
|
34
|
+
rb_raise(rb_eTypeError, "ed25519_pk must be kind of String");
|
35
|
+
}
|
36
|
+
|
37
|
+
pk_sz = crypto_sign_publickeybytes();
|
38
|
+
|
39
|
+
if((dec_ptr = malloc(pk_sz)) == NULL){
|
40
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
41
|
+
}
|
42
|
+
|
43
|
+
success = sodium_base642bin(
|
44
|
+
dec_ptr,
|
45
|
+
pk_sz,
|
46
|
+
RSTRING_PTR(ed25519_pk),
|
47
|
+
RSTRING_LEN(ed25519_pk),
|
48
|
+
NULL,
|
49
|
+
&dec_sz,
|
50
|
+
NULL,
|
51
|
+
sodium_base64_VARIANT_ORIGINAL_NO_PADDING
|
52
|
+
);
|
53
|
+
|
54
|
+
if(success != 0) {
|
55
|
+
free(dec_ptr);
|
56
|
+
rb_raise(rb_eTypeError, "could not convert ed25519 public key");
|
57
|
+
}
|
58
|
+
|
59
|
+
if((pk_ptr = malloc(pk_sz)) == NULL){
|
60
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
61
|
+
}
|
62
|
+
|
63
|
+
success = crypto_sign_ed25519_pk_to_curve25519(
|
64
|
+
pk_ptr,
|
65
|
+
dec_ptr
|
66
|
+
);
|
67
|
+
|
68
|
+
free(dec_ptr);
|
69
|
+
|
70
|
+
if(success != 0) {
|
71
|
+
free(pk_ptr);
|
72
|
+
rb_raise(rb_eTypeError, "could not convert ed25519 public key");
|
73
|
+
}
|
74
|
+
|
75
|
+
enc_sz = sodium_base64_ENCODED_LEN(pk_sz, sodium_base64_VARIANT_ORIGINAL_NO_PADDING);
|
76
|
+
|
77
|
+
if((enc_ptr = malloc(enc_sz)) == NULL){
|
78
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
79
|
+
}
|
80
|
+
|
81
|
+
sodium_bin2base64(
|
82
|
+
enc_ptr,
|
83
|
+
enc_sz,
|
84
|
+
pk_ptr,
|
85
|
+
pk_sz,
|
86
|
+
sodium_base64_VARIANT_ORIGINAL_NO_PADDING
|
87
|
+
);
|
88
|
+
|
89
|
+
free(pk_ptr);
|
90
|
+
|
91
|
+
curve25519_sk = rb_str_new(enc_ptr, enc_sz);
|
92
|
+
|
93
|
+
free(enc_ptr);
|
94
|
+
|
95
|
+
return curve25519_sk;
|
96
|
+
}
|
97
|
+
|
98
|
+
static VALUE sha256(VALUE self, VALUE data)
|
99
|
+
{
|
100
|
+
size_t size;
|
101
|
+
OlmUtility *this;
|
102
|
+
Data_Get_Struct(self, OlmUtility, this);
|
103
|
+
|
104
|
+
size = olm_sha256_length(this);
|
105
|
+
uint8_t buf[size];
|
106
|
+
|
107
|
+
(void)olm_sha256(this, RSTRING_PTR(data), RSTRING_LEN(data), buf, size);
|
108
|
+
|
109
|
+
return rb_str_new(buf, size);
|
110
|
+
}
|
111
|
+
|
112
|
+
static void _free(void *ptr)
|
113
|
+
{
|
114
|
+
olm_clear_utility(ptr);
|
115
|
+
free(ptr);
|
116
|
+
}
|
117
|
+
|
118
|
+
static VALUE _alloc(VALUE klass)
|
119
|
+
{
|
120
|
+
OlmUtility *this;
|
121
|
+
VALUE self;
|
122
|
+
|
123
|
+
self = Data_Wrap_Struct(klass, 0, _free, calloc(1, olm_utility_size()));
|
124
|
+
|
125
|
+
Data_Get_Struct(self, OlmUtility, this);
|
126
|
+
|
127
|
+
(void)olm_utility((void *)this);
|
128
|
+
|
129
|
+
return self;
|
130
|
+
}
|
131
|
+
|
132
|
+
void utility_init(void)
|
133
|
+
{
|
134
|
+
VALUE cRubyOLM = rb_define_module("SelfCrypto");
|
135
|
+
VALUE cUtil = rb_define_module_under(cRubyOLM, "Util");
|
136
|
+
VALUE cUtility = rb_define_class_under(cRubyOLM, "Utility", rb_cObject);
|
137
|
+
|
138
|
+
rb_define_alloc_func(cUtility, _alloc);
|
139
|
+
|
140
|
+
rb_define_method(cUtility, "sha256", sha256, 1);
|
141
|
+
rb_define_method(cUtility, "ed25519_verify", ed25519_verify, 3);
|
142
|
+
rb_define_module_function(cUtil, "ed25519_pk_to_curve25519", ed25519_pk_to_curve25519, 1);
|
143
|
+
}
|