self_crypto 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 34537603a575a2b32c468b332dd83e91ba2516c8c09984fb99d8f55910cdb680
|
4
|
+
data.tar.gz: 5e3a683e167fcdb4126bed5de9282d4d4e5c694ef54158d4dacd146b8d180d8e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d0133166300cd4f784af606550459c670bdc0dde4a6db1a74e70fd0dcba36baae7a1e50604d923d0f0da25b3b59378d4418f0c671dadd1eb931faff780958be4
|
7
|
+
data.tar.gz: 498ad6f393d8683d9250ce56957d09d026283449a3964e3f5193a0ad1512bfce887eb67c75a99a8ded80768de075289b728328b18e494de4e15ac0d0ee248385
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/extensiontask'
|
3
|
+
|
4
|
+
Rake::ExtensionTask.new do |ext|
|
5
|
+
ext.name = "self_crypto"
|
6
|
+
ext.ext_dir = "ext/self_crypto"
|
7
|
+
ext.lib_dir = "lib/self_crypto"
|
8
|
+
end
|
9
|
+
|
10
|
+
task :test => :compile
|
11
|
+
|
12
|
+
Rake::TestTask.new do |t|
|
13
|
+
t.name = :test
|
14
|
+
t.libs << "lib"
|
15
|
+
t.test_files = FileList["test/**/test_*.rb"]
|
16
|
+
t.verbose = true
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => :test
|
@@ -0,0 +1,292 @@
|
|
1
|
+
#include "sodium.h"
|
2
|
+
#include "self_olm/olm.h"
|
3
|
+
#include "self_crypto.h"
|
4
|
+
|
5
|
+
static VALUE last_error(VALUE self)
|
6
|
+
{
|
7
|
+
OlmAccount *this;
|
8
|
+
Data_Get_Struct(self, OlmAccount, this);
|
9
|
+
|
10
|
+
return rb_funcall(rb_eval_string("SelfCrypto::OlmError"), rb_intern("from_string"), 1, rb_str_new2(olm_account_last_error(this)));
|
11
|
+
}
|
12
|
+
|
13
|
+
static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
14
|
+
{
|
15
|
+
VALUE pickle, password, seed, opts;
|
16
|
+
size_t size;
|
17
|
+
OlmAccount *this;
|
18
|
+
Data_Get_Struct(self, OlmAccount, this);
|
19
|
+
|
20
|
+
(void)rb_scan_args(argc, argv, "0:", &opts);
|
21
|
+
|
22
|
+
opts = (opts == Qnil) ? rb_hash_new(): opts;
|
23
|
+
|
24
|
+
pickle = rb_hash_aref(opts, ID2SYM(rb_intern("pickle")));
|
25
|
+
password = rb_hash_aref(opts, ID2SYM(rb_intern("password")));
|
26
|
+
seed = rb_hash_aref(opts, ID2SYM(rb_intern("seed")));
|
27
|
+
|
28
|
+
if(pickle != Qnil){
|
29
|
+
|
30
|
+
if(rb_obj_is_kind_of(pickle, rb_cString) != Qtrue){
|
31
|
+
|
32
|
+
rb_raise(rb_eTypeError, "pickle must be kind of String");
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
if(password != Qnil){
|
37
|
+
|
38
|
+
if(rb_obj_is_kind_of(password, rb_cString) != Qtrue){
|
39
|
+
|
40
|
+
rb_raise(rb_eTypeError, "password must be kind of String");
|
41
|
+
}
|
42
|
+
}
|
43
|
+
else{
|
44
|
+
|
45
|
+
password = rb_str_new2("");
|
46
|
+
}
|
47
|
+
|
48
|
+
if(pickle != Qnil){
|
49
|
+
|
50
|
+
if(olm_unpickle_account(this, RSTRING_PTR(password), RSTRING_LEN(password), RSTRING_PTR(dup_string(pickle)), RSTRING_LEN(pickle)) == olm_error()){
|
51
|
+
|
52
|
+
raise_olm_error(olm_account_last_error(this));
|
53
|
+
}
|
54
|
+
}
|
55
|
+
if(seed != Qnil){
|
56
|
+
if(olm_create_account_derrived_keys(this, RSTRING_PTR(seed), RSTRING_LEN(seed)) == olm_error()){
|
57
|
+
|
58
|
+
raise_olm_error(olm_account_last_error(this));
|
59
|
+
}
|
60
|
+
}
|
61
|
+
else{
|
62
|
+
|
63
|
+
size = olm_create_account_random_length(this);
|
64
|
+
|
65
|
+
if(olm_create_account(this, RSTRING_PTR(get_random(size)), size) == olm_error()){
|
66
|
+
|
67
|
+
raise_olm_error(olm_account_last_error(this));
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
return self;
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE identity_keys(VALUE self)
|
75
|
+
{
|
76
|
+
OlmAccount *this;
|
77
|
+
size_t size;
|
78
|
+
Data_Get_Struct(self, OlmAccount, this);
|
79
|
+
|
80
|
+
size = olm_account_identity_keys_length(this);
|
81
|
+
uint8_t buf[size];
|
82
|
+
|
83
|
+
if(olm_account_identity_keys(this, buf, size) != size){
|
84
|
+
|
85
|
+
raise_olm_error(olm_account_last_error(this));
|
86
|
+
}
|
87
|
+
|
88
|
+
return rb_funcall(rb_eval_string("JSON"), rb_intern("parse"), 1, rb_str_new((char *)buf, size));
|
89
|
+
}
|
90
|
+
|
91
|
+
static VALUE generate_one_time_keys(VALUE self, VALUE number)
|
92
|
+
{
|
93
|
+
size_t size;
|
94
|
+
OlmAccount *this;
|
95
|
+
Data_Get_Struct(self, OlmAccount, this);
|
96
|
+
|
97
|
+
size = olm_account_generate_one_time_keys_random_length(this, NUM2SIZET(number));
|
98
|
+
|
99
|
+
if(olm_account_generate_one_time_keys(this, NUM2SIZET(number), RSTRING_PTR(get_random(size)), size) == olm_error()){
|
100
|
+
|
101
|
+
raise_olm_error(olm_account_last_error(this));
|
102
|
+
}
|
103
|
+
|
104
|
+
return self;
|
105
|
+
}
|
106
|
+
|
107
|
+
static VALUE one_time_keys_size(VALUE self)
|
108
|
+
{
|
109
|
+
OlmAccount *this;
|
110
|
+
Data_Get_Struct(self, OlmAccount, this);
|
111
|
+
|
112
|
+
return SIZET2NUM(olm_account_one_time_keys_length(this));
|
113
|
+
}
|
114
|
+
|
115
|
+
static VALUE one_time_keys(VALUE self)
|
116
|
+
{
|
117
|
+
VALUE retval;
|
118
|
+
size_t size;
|
119
|
+
void *ptr;
|
120
|
+
OlmAccount *this;
|
121
|
+
Data_Get_Struct(self, OlmAccount, this);
|
122
|
+
|
123
|
+
size = olm_account_one_time_keys_length(this);
|
124
|
+
|
125
|
+
// add an additional byte to stop this from overflowing
|
126
|
+
if((ptr = malloc(size+1)) == NULL){
|
127
|
+
|
128
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
129
|
+
}
|
130
|
+
|
131
|
+
if(olm_account_one_time_keys(this, ptr, size) != size){
|
132
|
+
|
133
|
+
free(ptr);
|
134
|
+
raise_olm_error(olm_account_last_error(this));
|
135
|
+
}
|
136
|
+
|
137
|
+
retval = rb_funcall(rb_eval_string("JSON"), rb_intern("parse"), 1, rb_str_new(ptr, size));
|
138
|
+
|
139
|
+
free(ptr);
|
140
|
+
|
141
|
+
return retval;
|
142
|
+
}
|
143
|
+
|
144
|
+
static VALUE sign(VALUE self, VALUE message)
|
145
|
+
{
|
146
|
+
VALUE retval;
|
147
|
+
size_t size;
|
148
|
+
void *ptr;
|
149
|
+
OlmAccount *this;
|
150
|
+
Data_Get_Struct(self, OlmAccount, this);
|
151
|
+
|
152
|
+
size = olm_account_signature_length(this);
|
153
|
+
|
154
|
+
if((ptr = malloc(size)) == NULL){
|
155
|
+
|
156
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
157
|
+
}
|
158
|
+
|
159
|
+
if(olm_account_sign(this, RSTRING_PTR(message), RSTRING_LEN(message), ptr, size) == olm_error()){
|
160
|
+
|
161
|
+
free(ptr);
|
162
|
+
raise_olm_error(olm_account_last_error(this));
|
163
|
+
}
|
164
|
+
|
165
|
+
retval = rb_str_new(ptr, size);
|
166
|
+
|
167
|
+
free(ptr);
|
168
|
+
|
169
|
+
return retval;
|
170
|
+
}
|
171
|
+
|
172
|
+
static VALUE mark_keys_as_published(VALUE self)
|
173
|
+
{
|
174
|
+
OlmAccount *this;
|
175
|
+
Data_Get_Struct(self, OlmAccount, this);
|
176
|
+
|
177
|
+
(void)olm_account_mark_keys_as_published(this);
|
178
|
+
|
179
|
+
return self;
|
180
|
+
}
|
181
|
+
|
182
|
+
static VALUE max_number_of_one_time_keys(VALUE self)
|
183
|
+
{
|
184
|
+
OlmAccount *this;
|
185
|
+
Data_Get_Struct(self, OlmAccount, this);
|
186
|
+
|
187
|
+
return SIZET2NUM(olm_account_max_number_of_one_time_keys(this));
|
188
|
+
}
|
189
|
+
|
190
|
+
static VALUE remove_one_time_keys(VALUE self, VALUE session)
|
191
|
+
{
|
192
|
+
OlmAccount *this;
|
193
|
+
Data_Get_Struct(self, OlmAccount, this);
|
194
|
+
|
195
|
+
OlmSession *s;
|
196
|
+
Data_Get_Struct(session, OlmSession, s);
|
197
|
+
|
198
|
+
if(olm_remove_one_time_keys(this, s) == olm_error()){
|
199
|
+
|
200
|
+
raise_olm_error(olm_account_last_error(this));
|
201
|
+
}
|
202
|
+
|
203
|
+
return self;
|
204
|
+
}
|
205
|
+
|
206
|
+
static VALUE outbound_session(VALUE self, VALUE identity_key, VALUE pre_key)
|
207
|
+
{
|
208
|
+
return rb_funcall(rb_eval_string("SelfCrypto::OutboundSession"), rb_intern("new"), 3, self, identity_key, pre_key);
|
209
|
+
}
|
210
|
+
|
211
|
+
static VALUE inbound_session(int argc, VALUE *argv, VALUE self)
|
212
|
+
{
|
213
|
+
VALUE args[] = {self, Qnil, Qnil};
|
214
|
+
|
215
|
+
(void)rb_scan_args(argc, argv, "11", &args[1], &args[2]);
|
216
|
+
|
217
|
+
return rb_class_new_instance(sizeof(args)/sizeof(*args), args, rb_eval_string("SelfCrypto::InboundSession"));
|
218
|
+
}
|
219
|
+
|
220
|
+
static VALUE to_pickle(int argc, VALUE *argv, VALUE self)
|
221
|
+
{
|
222
|
+
VALUE password, retval;
|
223
|
+
OlmAccount *this;
|
224
|
+
void *ptr;
|
225
|
+
size_t size;
|
226
|
+
Data_Get_Struct(self, OlmAccount, this);
|
227
|
+
|
228
|
+
(void)rb_scan_args(argc, argv, "01", &password);
|
229
|
+
|
230
|
+
password = (password == Qnil) ? rb_str_new2("") : password;
|
231
|
+
|
232
|
+
size = olm_pickle_account_length(this);
|
233
|
+
|
234
|
+
if((ptr = malloc(size)) == NULL){
|
235
|
+
|
236
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
237
|
+
}
|
238
|
+
|
239
|
+
if(olm_pickle_account(this, RSTRING_PTR(password), RSTRING_LEN(password), ptr, size) != size){
|
240
|
+
|
241
|
+
free(ptr);
|
242
|
+
raise_olm_error(olm_account_last_error(this));
|
243
|
+
}
|
244
|
+
|
245
|
+
retval = rb_str_new(ptr, size);
|
246
|
+
|
247
|
+
free(ptr);
|
248
|
+
|
249
|
+
return retval;
|
250
|
+
}
|
251
|
+
|
252
|
+
static void _free(void *ptr)
|
253
|
+
{
|
254
|
+
olm_clear_account(ptr);
|
255
|
+
free(ptr);
|
256
|
+
}
|
257
|
+
|
258
|
+
static VALUE _alloc(VALUE klass)
|
259
|
+
{
|
260
|
+
OlmAccount *this;
|
261
|
+
VALUE self;
|
262
|
+
|
263
|
+
self = Data_Wrap_Struct(klass, 0, _free, calloc(1, olm_account_size()));
|
264
|
+
|
265
|
+
Data_Get_Struct(self, OlmAccount, this);
|
266
|
+
|
267
|
+
(void)olm_account((void *)this);
|
268
|
+
|
269
|
+
return self;
|
270
|
+
}
|
271
|
+
|
272
|
+
void account_init(void)
|
273
|
+
{
|
274
|
+
VALUE cRubyOLM = rb_define_module("SelfCrypto");
|
275
|
+
VALUE cAccount = rb_define_class_under(cRubyOLM, "Account", rb_cObject);
|
276
|
+
|
277
|
+
rb_define_alloc_func(cAccount, _alloc);
|
278
|
+
|
279
|
+
rb_define_method(cAccount, "initialize", initialize, -1);
|
280
|
+
rb_define_method(cAccount, "identity_keys", identity_keys, 0);
|
281
|
+
rb_define_method(cAccount, "one_time_keys", one_time_keys, 0);
|
282
|
+
rb_define_method(cAccount, "one_time_keys_size", one_time_keys_size, 0);
|
283
|
+
rb_define_method(cAccount, "generate_one_time_keys", generate_one_time_keys, 1);
|
284
|
+
rb_define_method(cAccount, "last_error", last_error, 0);
|
285
|
+
rb_define_method(cAccount, "sign", sign, 1);
|
286
|
+
rb_define_method(cAccount, "mark_keys_as_published", mark_keys_as_published, 0);
|
287
|
+
rb_define_method(cAccount, "max_number_of_one_time_keys", max_number_of_one_time_keys, 0);
|
288
|
+
rb_define_method(cAccount, "remove_one_time_keys", remove_one_time_keys, 1);
|
289
|
+
rb_define_method(cAccount, "outbound_session", outbound_session, 2);
|
290
|
+
rb_define_method(cAccount, "inbound_session", inbound_session, -1);
|
291
|
+
rb_define_method(cAccount, "to_pickle", to_pickle, -1);
|
292
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
$CFLAGS = " -std=c99"
|
4
|
+
|
5
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
6
|
+
|
7
|
+
pkg_config('self_olm')
|
8
|
+
pkg_config('self_omemo')
|
9
|
+
pkg_config("sodium")
|
10
|
+
|
11
|
+
abort "Missing sodium" unless have_library("sodium")
|
12
|
+
abort "Missing omemo" unless have_library("self_omemo")
|
13
|
+
abort "Missing olm" unless have_library("self_olm")
|
14
|
+
|
15
|
+
create_makefile('self_crypto/self_crypto')
|
@@ -0,0 +1,170 @@
|
|
1
|
+
#include "sodium.h"
|
2
|
+
#include "self_olm/olm.h"
|
3
|
+
#include "self_omemo.h"
|
4
|
+
#include "self_crypto.h"
|
5
|
+
|
6
|
+
static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
7
|
+
{
|
8
|
+
VALUE identity;
|
9
|
+
GroupSession *this;
|
10
|
+
|
11
|
+
Data_Get_Struct(self, GroupSession, this);
|
12
|
+
|
13
|
+
(void)rb_scan_args(argc, argv, "1", &identity);
|
14
|
+
|
15
|
+
if(identity != Qnil){
|
16
|
+
if(rb_obj_is_kind_of(identity, rb_cString) != Qtrue){
|
17
|
+
rb_raise(rb_eTypeError, "identity must be kind of String");
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
omemo_set_identity(this, RSTRING_PTR(identity));
|
22
|
+
|
23
|
+
return self;
|
24
|
+
}
|
25
|
+
|
26
|
+
static VALUE add_participant(VALUE self, VALUE identity, VALUE session)
|
27
|
+
{
|
28
|
+
GroupSession *this;
|
29
|
+
OlmSession *s;
|
30
|
+
|
31
|
+
Data_Get_Struct(self, GroupSession, this);
|
32
|
+
Data_Get_Struct(session, OlmSession, s);
|
33
|
+
|
34
|
+
if(rb_obj_is_kind_of(identity, rb_eval_string("String")) != Qtrue){
|
35
|
+
rb_raise(rb_eTypeError, "identity must be kind of String");
|
36
|
+
}
|
37
|
+
|
38
|
+
if(
|
39
|
+
rb_obj_is_instance_of(session, rb_eval_string("SelfCrypto::Session")) != Qtrue &&
|
40
|
+
rb_obj_is_instance_of(session, rb_eval_string("SelfCrypto::InboundSession")) != Qtrue &&
|
41
|
+
rb_obj_is_instance_of(session, rb_eval_string("SelfCrypto::OutboundSession")) != Qtrue
|
42
|
+
){
|
43
|
+
rb_raise(rb_eTypeError, "session must be an instance of SelfCrypto::Session, SelfCrypto::InboundSession or SelfCrypto::OutboundSession");
|
44
|
+
}
|
45
|
+
|
46
|
+
omemo_add_group_participant(this, RSTRING_PTR(identity), s);
|
47
|
+
|
48
|
+
return identity;
|
49
|
+
}
|
50
|
+
|
51
|
+
static VALUE encrypt(VALUE self, VALUE plaintext)
|
52
|
+
{
|
53
|
+
GroupSession *this;
|
54
|
+
VALUE ciphertext;
|
55
|
+
void *ptr;
|
56
|
+
size_t ciphertext_sz;
|
57
|
+
|
58
|
+
Data_Get_Struct(self, GroupSession, this);
|
59
|
+
|
60
|
+
if(rb_obj_is_kind_of(plaintext, rb_eval_string("String")) != Qtrue){
|
61
|
+
rb_raise(rb_eTypeError, "plaintext must be kind of String");
|
62
|
+
}
|
63
|
+
|
64
|
+
ciphertext_sz = omemo_encrypted_size(this, RSTRING_LEN(plaintext));
|
65
|
+
|
66
|
+
if (ciphertext_sz == 0) {
|
67
|
+
rb_raise(rb_eTypeError, "could not get size of encrypted message");
|
68
|
+
}
|
69
|
+
|
70
|
+
if((ptr = malloc(ciphertext_sz)) == NULL){
|
71
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
72
|
+
}
|
73
|
+
|
74
|
+
ciphertext_sz = omemo_encrypt(
|
75
|
+
this,
|
76
|
+
RSTRING_PTR(plaintext),
|
77
|
+
RSTRING_LEN(plaintext),
|
78
|
+
ptr,
|
79
|
+
ciphertext_sz
|
80
|
+
);
|
81
|
+
|
82
|
+
if(ciphertext_sz == 0) {
|
83
|
+
free(ptr);
|
84
|
+
rb_raise(rb_eTypeError, "failed to encrypt");
|
85
|
+
}
|
86
|
+
|
87
|
+
ciphertext = rb_funcall(rb_eval_string("SelfCrypto::GroupMessage"), rb_intern("new"), 1, rb_str_new(ptr, ciphertext_sz));
|
88
|
+
|
89
|
+
free(ptr);
|
90
|
+
|
91
|
+
return ciphertext;
|
92
|
+
}
|
93
|
+
|
94
|
+
static VALUE decrypt(VALUE self, VALUE sender, VALUE ciphertext)
|
95
|
+
{
|
96
|
+
GroupSession *this;
|
97
|
+
VALUE plaintext;
|
98
|
+
void *ptr;
|
99
|
+
size_t plaintext_sz;
|
100
|
+
|
101
|
+
Data_Get_Struct(self, GroupSession, this);
|
102
|
+
|
103
|
+
if(rb_obj_is_kind_of(sender, rb_eval_string("String")) != Qtrue){
|
104
|
+
rb_raise(rb_eTypeError, "sender must be kind of String");
|
105
|
+
}
|
106
|
+
|
107
|
+
if(rb_obj_is_kind_of(ciphertext, rb_eval_string("String")) != Qtrue){
|
108
|
+
rb_raise(rb_eTypeError, "ciphertext must be kind of String");
|
109
|
+
}
|
110
|
+
|
111
|
+
plaintext_sz = omemo_decrypted_size(this, RSTRING_PTR(ciphertext), RSTRING_LEN(ciphertext));
|
112
|
+
|
113
|
+
if (plaintext_sz == 0) {
|
114
|
+
rb_raise(rb_eTypeError, "could not get size of decrypted message");
|
115
|
+
}
|
116
|
+
|
117
|
+
if((ptr = malloc(plaintext_sz)) == NULL){
|
118
|
+
rb_raise(rb_eNoMemError, "%s()", __FUNCTION__);
|
119
|
+
}
|
120
|
+
|
121
|
+
plaintext_sz = omemo_decrypt(
|
122
|
+
this,
|
123
|
+
RSTRING_PTR(sender),
|
124
|
+
ptr,
|
125
|
+
plaintext_sz,
|
126
|
+
RSTRING_PTR(ciphertext),
|
127
|
+
RSTRING_LEN(ciphertext)
|
128
|
+
);
|
129
|
+
|
130
|
+
if(plaintext_sz == 0) {
|
131
|
+
free(ptr);
|
132
|
+
rb_raise(rb_eTypeError, "failed to decrypt");
|
133
|
+
}
|
134
|
+
|
135
|
+
plaintext = rb_str_new(ptr, plaintext_sz);
|
136
|
+
|
137
|
+
free(ptr);
|
138
|
+
|
139
|
+
return plaintext;
|
140
|
+
}
|
141
|
+
|
142
|
+
static void _free(void *ptr)
|
143
|
+
{
|
144
|
+
omemo_destroy_group_session(ptr);
|
145
|
+
}
|
146
|
+
|
147
|
+
static VALUE _alloc(VALUE klass)
|
148
|
+
{
|
149
|
+
GroupSession *this;
|
150
|
+
VALUE self;
|
151
|
+
|
152
|
+
self = Data_Wrap_Struct(klass, 0, _free, omemo_create_group_session());
|
153
|
+
|
154
|
+
Data_Get_Struct(self, GroupSession, this);
|
155
|
+
|
156
|
+
return self;
|
157
|
+
}
|
158
|
+
|
159
|
+
void group_session_init()
|
160
|
+
{
|
161
|
+
VALUE cRubyOLM = rb_define_module("SelfCrypto");
|
162
|
+
VALUE cGroupSession = rb_define_class_under(cRubyOLM, "GroupSession", rb_cObject);
|
163
|
+
|
164
|
+
rb_define_alloc_func(cGroupSession, _alloc);
|
165
|
+
|
166
|
+
rb_define_method(cGroupSession, "initialize", initialize, -1);
|
167
|
+
rb_define_method(cGroupSession, "add_participant", add_participant, 2);
|
168
|
+
rb_define_method(cGroupSession, "encrypt", encrypt, 1);
|
169
|
+
rb_define_method(cGroupSession, "decrypt", decrypt, 2);
|
170
|
+
}
|