ttcrypt 0.0.2

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.
@@ -0,0 +1,67 @@
1
+ //
2
+ // sha256.h
3
+ // iGlomp
4
+ //
5
+ // Created by Sergey Chernov on 28.10.11.
6
+ // Copyright (c) 2011 Thrift. All rights reserved.
7
+ //
8
+
9
+ #ifndef iGlomp_sha256_h
10
+ #define iGlomp_sha256_h
11
+
12
+ /* Declarations of functions and data types used for SHA256 and SHA224 sum
13
+ library functions.
14
+ Copyright (C) 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
15
+
16
+ This program is free software: you can redistribute it and/or modify
17
+ it under the terms of the GNU General Public License as published by
18
+ the Free Software Foundation, either version 3 of the License, or
19
+ (at your option) any later version.
20
+
21
+ This program is distributed in the hope that it will be useful,
22
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ GNU General Public License for more details.
25
+
26
+ You should have received a copy of the GNU General Public License
27
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
28
+
29
+ typedef unsigned char uint8;
30
+ typedef unsigned int uint32;
31
+
32
+ #ifndef SHA256_H
33
+ # define SHA256_H 1
34
+
35
+ # include <stdio.h>
36
+ # include <stdint.h>
37
+
38
+ # ifdef __cplusplus
39
+ extern "C" {
40
+ # endif
41
+
42
+ /* Structure to save state of computation between the single steps. */
43
+ typedef struct sha256_ctx
44
+ {
45
+ uint32_t state[8];
46
+
47
+ uint32_t total[2];
48
+ size_t buflen;
49
+ uint8 buffer[64];
50
+ } sha256_context;
51
+
52
+ enum { SHA224_DIGEST_SIZE = 224 / 8 };
53
+ enum { SHA256_DIGEST_SIZE = 256 / 8 };
54
+
55
+ void sha256_starts( sha256_context *ctx );
56
+ void sha256_update( sha256_context *ctx, uint8 *input, uint32 length );
57
+ void sha256_finish( sha256_context *ctx, uint8 digest[32] );
58
+
59
+
60
+
61
+ # ifdef __cplusplus
62
+ }
63
+ # endif
64
+
65
+
66
+ #endif
67
+ #endif
@@ -0,0 +1,63 @@
1
+ //
2
+ // text_utils.cpp
3
+ //
4
+ // Created by Sergey Chernov on 01.06.14.
5
+ // Copyright (c) 2014 thrift. All rights reserved.
6
+ //
7
+
8
+ /*
9
+ This program is free software: you can redistribute it and/or modify
10
+ it under the terms of the GNU General Public License as published by
11
+ the Free Software Foundation, either version 3 of the License, or
12
+ (at your option) any later version.
13
+
14
+ This program is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ GNU General Public License for more details.
18
+
19
+ You should have received a copy of the GNU General Public License
20
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
21
+ */
22
+
23
+ #include "text_utils.h"
24
+
25
+
26
+ std::string sformat(const std::string fmt_str, ...) {
27
+ int final_n, n = ((int)fmt_str.size()) * 2; /* reserve 2 times as much as the length of the fmt_str */
28
+ std::string str;
29
+ std::unique_ptr<char[]> formatted;
30
+ va_list ap;
31
+ while(1) {
32
+ formatted.reset(new char[n]); /* wrap the plain char array into the unique_ptr */
33
+ // strcpy(&formatted[0], fmt_str.c_str());
34
+ va_start(ap, fmt_str);
35
+ final_n = vsnprintf(&formatted[0], n, fmt_str.c_str(), ap);
36
+ va_end(ap);
37
+ if (final_n < 0 || final_n >= n)
38
+ n += abs(final_n - n + 1);
39
+ else
40
+ break;
41
+ }
42
+ return std::string(formatted.get());
43
+ }
44
+
45
+ std::string vsformat(const std::string fmt_str, va_list args) {
46
+ int final_n, n = ((int)fmt_str.size()) * 2; /* reserve 2 times as much as the length of the fmt_str */
47
+ std::string str;
48
+ std::unique_ptr<char[]> formatted;
49
+ while(1) {
50
+ formatted.reset(new char[n]); /* wrap the plain char array into the unique_ptr */
51
+ // strcpy(&formatted[0], fmt_str.c_str());
52
+ va_list c;
53
+ va_copy(c, args);
54
+ final_n = vsnprintf(&formatted[0], n-1, fmt_str.c_str(), c);
55
+ va_end(c);
56
+ if (final_n < 0 || final_n >= n)
57
+ n += abs(final_n - n + 1);
58
+ else
59
+ break;
60
+ }
61
+ return std::string(formatted.get());
62
+ }
63
+
@@ -0,0 +1,64 @@
1
+ //
2
+ // text_utils.h
3
+ // zcoin
4
+ //
5
+ // Created by Sergey Chernov on 01.06.14.
6
+ // Copyright (c) 2014 thrift. All rights reserved.
7
+ //
8
+
9
+ /*
10
+ This program is free software: you can redistribute it and/or modify
11
+ it under the terms of the GNU General Public License as published by
12
+ the Free Software Foundation, either version 3 of the License, or
13
+ (at your option) any later version.
14
+
15
+ This program is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ GNU General Public License for more details.
19
+
20
+ You should have received a copy of the GNU General Public License
21
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
22
+ */
23
+
24
+ #ifndef __zcoin__text_utils__
25
+ #define __zcoin__text_utils__
26
+
27
+ #include <iostream>
28
+
29
+ std::string sformat(const std::string fmt_str, ...);
30
+ std::string vsformat(const std::string fmt_str, va_list args);
31
+
32
+ #ifdef DEBUG
33
+
34
+ template <class T> void log_d(const T& object,const std::string& msg) {
35
+ std::cout << (object.to_string() + ": " + msg) << std::endl;
36
+ }
37
+
38
+ template <class T> void log_d(T *const object,const std::string& msg) {
39
+ log_d(*object, msg);
40
+ }
41
+
42
+ inline void log_d(const std::string format, ...) {
43
+ va_list ap;
44
+ va_start(ap, format);
45
+ std::cout << vsformat(format, ap) << std::endl;
46
+ va_end(ap);
47
+ }
48
+
49
+ #else
50
+
51
+ #define log_d(...)
52
+
53
+ #endif
54
+
55
+ template <class T>
56
+ void stopwatch(T text, std::function<void(void)> block) {
57
+ std::cout << "Starting " << text << "...";
58
+ std::cout.flush();
59
+ clock_t start = clock();
60
+ block();
61
+ std::cout << " done, " << (clock() - start)/1000.0 << "ms " << std::endl;
62
+ }
63
+
64
+ #endif /* defined(__zcoin__text_utils__) */
@@ -0,0 +1,51 @@
1
+ /*
2
+ ttcrypt.cpp
3
+
4
+ Created by Sergey Chernov on 03.06.14.
5
+ Copyright (c) 2014 thrift. All rights reserved.
6
+
7
+
8
+ This program is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation, either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ This program is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ */
21
+
22
+ #include "ttcrypt.h"
23
+ #include "sha1.h"
24
+ #include "sha256.h"
25
+
26
+ using namespace thrift;
27
+
28
+ byte_buffer ttcrypt::sha1(const byte_buffer& data) noexcept {
29
+ byte_buffer res(20);
30
+ sha1::calc(data.data().get(), (int)data.size(), res.data().get() );
31
+ return res;
32
+ }
33
+
34
+ byte_buffer ttcrypt::sha256(const thrift::byte_buffer &data) noexcept {
35
+ byte_buffer res(32);
36
+ sha256_ctx ctx;
37
+ sha256_starts(&ctx);
38
+ sha256_update(&ctx, data.data().get(), (uint32) data.size());
39
+ sha256_finish(&ctx, res.data().get());
40
+ return res;
41
+ }
42
+
43
+ byte_buffer ttcrypt::i2osp(const big_integer& i, size_t block_size) noexcept {
44
+ byte_buffer res = i.to_byte_buffer();
45
+ if( block_size > 0 && res.size() != block_size ) {
46
+ size_t pad_length = block_size - res.size() % block_size;
47
+ if( pad_length > 0 )
48
+ return byte_buffer('\0', pad_length) + res;
49
+ }
50
+ return res;
51
+ }
@@ -0,0 +1,45 @@
1
+ /*
2
+ ttcrypt.h
3
+ zcoin
4
+
5
+ Created by Sergey Chernov on 03.06.14.
6
+ Copyright (c) 2014 thrift. All rights reserved.
7
+
8
+ This program is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU General Public License as published by
10
+ the Free Software Foundation, either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ This program is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU General Public License for more details.
17
+
18
+ You should have received a copy of the GNU General Public License
19
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ */
21
+
22
+ #ifndef __zcoin__ttcrypt__
23
+ #define __zcoin__ttcrypt__
24
+
25
+ #include <iostream>
26
+ #include "byte_buffer.h"
27
+ #include "big_integer.h"
28
+
29
+ using namespace thrift;
30
+
31
+ namespace ttcrypt {
32
+
33
+ byte_buffer sha1(const byte_buffer& data) noexcept;
34
+ byte_buffer sha256(const byte_buffer& data) noexcept;
35
+
36
+ byte_buffer i2osp(const big_integer& i, size_t block_size=0) noexcept;
37
+
38
+ inline big_integer os2ip(const byte_buffer& buffer) noexcept {
39
+ return big_integer(buffer);
40
+ }
41
+
42
+ }
43
+
44
+
45
+ #endif /* defined(__zcoin__ttcrypt__) */
@@ -0,0 +1,234 @@
1
+ /*
2
+ * TTCrypt ruby bindings
3
+ *
4
+ * Copyright (C) 2014 Thrift, Sergey S. Chernov
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+ #include <iostream>
20
+ #include <stdlib.h>
21
+
22
+ #include "ruby_cpp_tools.h"
23
+
24
+ #include "byte_buffer.h"
25
+ #include "pollard_rho.h"
26
+ #include "rsa_key.h"
27
+
28
+ extern "C" {
29
+ #include <ruby.h>
30
+ #include <ruby/thread.h>
31
+
32
+ void Init_ttcrypt(void);
33
+ }
34
+
35
+ using namespace thrift;
36
+ using namespace ttcrypt;
37
+
38
+ using namespace std;
39
+
40
+ static VALUE rsa_exception;
41
+ static VALUE rsa_class;
42
+
43
+ VALUE wrap_exceptions(const std::function<VALUE()>& block) {
44
+ try {
45
+ return block();
46
+ } catch (const rsa_key::error& e) {
47
+ rb_raise(rsa_exception, "%s", e.what());
48
+ } catch (const std::exception& e) {
49
+ rb_raise(rb_eStandardError, "%s", e.what());
50
+ } catch (...) {
51
+ rb_raise(rsa_exception, "unknown exception");
52
+ }
53
+ return Qnil;
54
+ }
55
+
56
+ rsa_key* rsa_ptr(VALUE self) {
57
+ rsa_key *pkey;
58
+ Data_Get_Struct(self, rsa_key, pkey);
59
+ return pkey;
60
+ }
61
+
62
+ rsa_key& rsa(VALUE self) {
63
+ return *rsa_ptr(self);
64
+ }
65
+
66
+ extern "C" {
67
+
68
+ static VALUE rsa_generate(VALUE self, VALUE length) {
69
+ return wrap_exceptions([=] {
70
+ unsigned l = NUM2UINT(length);
71
+ rsa_key *pkey = rsa_ptr(self);
72
+ ruby_unblock([=] {*pkey = rsa_key::generate(l);});
73
+ return self;
74
+ });
75
+ }
76
+
77
+ static VALUE rsa_bits(VALUE self) {
78
+ return INT2NUM(rsa(self).size_in_bits());
79
+ }
80
+
81
+ static VALUE rsa_encrypt(VALUE self, VALUE rb_data) {
82
+ return wrap_exceptions([=] {
83
+ byte_buffer res;
84
+ auto data = value_to_byte_buffer(rb_data);
85
+ ruby_unblock([&] {
86
+ res = rsa(self).encrypt(data);
87
+ });
88
+ return to_rb_string(res);
89
+ });
90
+ }
91
+
92
+ static VALUE rsa_decrypt(VALUE self, VALUE rb_data) {
93
+ return wrap_exceptions([=] {
94
+ byte_buffer res;
95
+ rsa_key& key = rsa(self);
96
+ auto data = value_to_byte_buffer(rb_data);
97
+ ruby_unblock([&res,&data,&key] {
98
+ res = key.decrypt(data);
99
+ });
100
+ return to_rb_string(res);
101
+ });
102
+ }
103
+
104
+ static VALUE factorize(VALUE self, VALUE composite) {
105
+ return wrap_exceptions([=] {
106
+ string s = value_to_string(composite);
107
+
108
+ vector<big_integer> factors;
109
+ ruby_unblock([s,&factors] {
110
+ factors = pollard_rho::factorize(decode_hex(s));
111
+ });
112
+
113
+ VALUE result = rb_ary_new();
114
+ for (auto factor : factors) {
115
+ rb_ary_push(result, to_hex_value(factor));
116
+ }
117
+ return result;
118
+ });
119
+ }
120
+
121
+ typedef byte_buffer (*hash_t)(const byte_buffer &);
122
+
123
+ static hash_t hash_provider(VALUE name) {
124
+ string n = value_to_string(name);
125
+ if (n == "sha256")
126
+ return sha256;
127
+ else if (n == "sha1")
128
+ return sha1;
129
+ else
130
+ throw invalid_argument("not supported hash: " + n);
131
+ }
132
+
133
+ static VALUE rsa_sign(VALUE self, VALUE message, VALUE signature_method) {
134
+ return wrap_exceptions([=] {
135
+ byte_buffer m = value_to_byte_buffer(message);
136
+ byte_buffer res;
137
+ hash_t hash = hash_provider(signature_method);
138
+
139
+ ruby_unblock([&] {
140
+ res = rsa(self).sign(m, hash);
141
+ });
142
+
143
+ return to_value(res);
144
+ });
145
+ }
146
+
147
+ static VALUE rsa_verify(VALUE self, VALUE message, VALUE signature,
148
+ VALUE signature_method) {
149
+ return wrap_exceptions([=] {
150
+ byte_buffer m = value_to_byte_buffer(message);
151
+ byte_buffer s = value_to_byte_buffer(signature);
152
+ bool res;
153
+ hash_t hash = hash_provider(signature_method);
154
+
155
+ ruby_unblock([&] {
156
+ res = rsa(self).verify(m, s, hash);
157
+ });
158
+
159
+ return res ? Qtrue : Qfalse;
160
+ });
161
+ }
162
+
163
+ static VALUE rsa_extract_public(VALUE self) {
164
+ return wrap_exceptions([=] {
165
+ rsa_key &me = rsa(self);
166
+ VALUE res = rb_class_new_instance(0,NULL,rsa_class);
167
+ rsa_key &pub = rsa(res);
168
+ pub = me.public_key();
169
+ return res;
170
+ });
171
+ }
172
+
173
+ static VALUE rsa_components(VALUE self) {
174
+ return wrap_exceptions([=] {
175
+ rsa_key& key = rsa(self);
176
+ VALUE hash = rb_hash_new();
177
+ for(auto x: key.get_params()) {
178
+ rb_hash_aset(hash,to_rb_sym(x.first),to_rb_string(x.second.to_byte_buffer()));
179
+ }
180
+ return hash;
181
+ });
182
+ }
183
+
184
+ static int do_set_param(VALUE key,VALUE data,VALUE obj) {
185
+ rsa(obj).set(value_to_string(key), value_to_byte_buffer(data));
186
+ return ST_CONTINUE;
187
+ }
188
+
189
+ static VALUE rsa_set_params(VALUE self,VALUE hash) {
190
+ return wrap_exceptions([=]{
191
+ rb_hash_foreach(hash, (int (*)(...)) do_set_param, self);
192
+ rsa(self).normalize_key();
193
+ return Qnil;
194
+ });
195
+ }
196
+
197
+ static VALUE rsa_is_private(VALUE self) {
198
+ return rsa(self).is_private() ? Qtrue : Qfalse;
199
+ }
200
+
201
+ static void rsa_free(void* ptr) {
202
+ delete (ttcrypt::rsa_key*) ptr;
203
+ }
204
+
205
+ static VALUE rsa_alloc(VALUE klass) {
206
+ return Data_Wrap_Struct(klass, 0, rsa_free, new ttcrypt::rsa_key);
207
+ }
208
+
209
+ }
210
+
211
+ void Init_ttcrypt(void) {
212
+
213
+ VALUE ttcrypt_module = rb_define_module("TTCrypt");
214
+
215
+ rb_define_method(ttcrypt_module, "_factorize", (ruby_method) factorize, 1);
216
+
217
+ rsa_class = rb_define_class_under(ttcrypt_module, "RsaKey", rb_cObject);
218
+ rb_define_alloc_func(rsa_class, rsa_alloc);
219
+ rb_define_method(rsa_class, "_generate", (ruby_method) rsa_generate, 1);
220
+ rb_define_method(rsa_class, "_bits", (ruby_method) rsa_bits, 0);
221
+ rb_define_method(rsa_class, "_encrypt", (ruby_method) rsa_encrypt, 1);
222
+ rb_define_method(rsa_class, "_decrypt", (ruby_method) rsa_decrypt, 1);
223
+ rb_define_method(rsa_class, "_sign", (ruby_method) rsa_sign, 2);
224
+ rb_define_method(rsa_class, "_verify", (ruby_method) rsa_verify, 3);
225
+ rb_define_method(rsa_class, "extract_public",
226
+ (ruby_method) rsa_extract_public, 0);
227
+ rb_define_method(rsa_class, "_is_private", (ruby_method) rsa_is_private, 0);
228
+ rb_define_method(rsa_class, "_components", (ruby_method) rsa_components, 0);
229
+ rb_define_method(rsa_class, "_set_params", (ruby_method) rsa_set_params, 1);
230
+
231
+ rsa_exception = rb_define_class_under(rsa_class, "Error",
232
+ rb_eStandardError);
233
+ }
234
+
@@ -0,0 +1,5 @@
1
+ module TTCrypt
2
+
3
+ VERSION = '0.0.2'
4
+
5
+ end
data/lib/ttcrypt.rb ADDED
@@ -0,0 +1,142 @@
1
+ # Thrift cryptographics primitives: fast c++ implementation, only strong schemes,
2
+ # releases GVL on long operations so other threads can be executed in parallel.
3
+ module TTCrypt
4
+ # Your code goes here...
5
+
6
+ # Pollard 'rho' prime factorization. Allows execution of other ruby
7
+ # threads in parallel (releases GVL)
8
+ #
9
+ # @return [int] array of prime factors
10
+ def factorize composite
11
+ hex = composite.to_i.to_s(16)
12
+ hex = '0' + hex if (hex.length & 1) == 1
13
+ _factorize(hex).map { |x| x.to_i(16) }
14
+ end
15
+
16
+ # Implementation of RSAES-OAEP encryption and RSASSA-PSS signing
17
+ # accroding to pkcs#1 v2.2 specification. Does NOT implement any previous cryptographically
18
+ # weak shcemes (like 1.5 signature) - go use openssl for itm but it does compromise private
19
+ # key.
20
+ #
21
+ # All time consuming operations are executed releasing GVL so other threads can run in parallel
22
+ # in the multicore hardware.
23
+ #
24
+ class RsaKey
25
+
26
+ # raised when some parameters of RSAES are invalid, e.g.
27
+ # message/representation is too long, encrypted message or representation
28
+ # is not properly padded
29
+ class Error < StandardError
30
+ end
31
+
32
+ ACCEPTED_PARAMS = %i|n e p q d|
33
+
34
+ def initialize ** params
35
+ set_params(params)
36
+ end
37
+
38
+ def set_params ** params
39
+ res = {}
40
+ params.each { |k, v|
41
+ ACCEPTED_PARAMS.include?(k) or raise ArgumentError, "unknown key component"
42
+ res[k.to_s] = v.to_s.force_encoding(Encoding::BINARY)
43
+ }
44
+ _set_params res
45
+ end
46
+
47
+ # Generate private key (that contains public key too) of the desired bit
48
+ # length (recommended at least 2048).
49
+ def self.generate bits_strength
50
+ k = RsaKey.new
51
+ k._generate(bits_strength)
52
+ end
53
+
54
+ # Get key size in bits
55
+ def bits
56
+ _bits
57
+ end
58
+
59
+ # Encrypt message with public key using RSAES-OAEP scheme
60
+ # (pkcs#1 v.2.2).
61
+ def encrypt message
62
+ message.force_encoding Encoding::BINARY
63
+ _encrypt message
64
+ end
65
+
66
+ # Decrypt message with private key using RSAES-OAEP scheme
67
+ # (pkcs#1 v.2.2). Requires private key
68
+ #
69
+ def decrypt message
70
+ message.force_encoding Encoding::BINARY
71
+ _decrypt message
72
+ end
73
+
74
+ # Sign the message using pkcs#1 v2.2 RSASSA-PSS
75
+ # process. Requires private key.
76
+ #
77
+ #@param [String] message to sign
78
+ #@param [Symbol|String] hash function used (:sha1 or :sha256)
79
+ #@return [bool] true if the signature is consistent
80
+ def sign message, hash_name
81
+ message.force_encoding Encoding::BINARY
82
+ _sign message, hash_name.to_s.downcase
83
+ end
84
+
85
+ # Check message signature signed with pkcs#1 v2.2 RSASSA-PSS
86
+ # process
87
+ #
88
+ #@param [String] message to verify
89
+ #@param [String] signature
90
+ #@param [Symbol|String] hash function used (:sha1 or :sha256)
91
+ #@return [bool] true if the signature is consistent
92
+ def verify message, signature, hash_name=:sha1
93
+ message.force_encoding Encoding::BINARY
94
+ signature.force_encoding Encoding::BINARY
95
+ _verify message, signature, hash_name.to_s.downcase
96
+ end
97
+
98
+ # Extract public key from a private (or public) key
99
+ # @return [RsaKey] public key instance
100
+ def extract_public
101
+ # native implementation: this is for indexing only
102
+ end
103
+
104
+ # true if self contains private key
105
+ def private?
106
+ _is_private
107
+ end
108
+
109
+ # Get key components as hash. Components are binary strings, indexes are symbols
110
+ # e.g. :n, :e
111
+ def components
112
+ @components ||= _components
113
+ end
114
+
115
+ # @return [String] P component or nil
116
+ def p
117
+ components[:p]
118
+ end
119
+
120
+ def q
121
+ components[:q]
122
+ end
123
+
124
+ def n
125
+ components[:n]
126
+ end
127
+
128
+ def e
129
+ components[:e]
130
+ end
131
+
132
+ end
133
+ end
134
+
135
+ # it should require native lib after module definition above
136
+ # otherwise won't work!
137
+ require 'ttcrypt/ttcrypt'
138
+
139
+ module TTCrypt
140
+ module_function :factorize, :_factorize
141
+ end
142
+
@@ -0,0 +1,17 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end