self_crypto 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
+ }