ttcrypt 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f88c032607b33e66a47343f5993bb7884925d17f
4
- data.tar.gz: 7ca31bdfa0f0401b1e6cbd3c4c0ce8b19f0f6a6a
3
+ metadata.gz: b88f2dc4431b1ba173947a270240d8fa9108037c
4
+ data.tar.gz: c5118f3a7a1d341143436cebc6ab5db76bc4281c
5
5
  SHA512:
6
- metadata.gz: 3842c52dc96065852cf4d0cf854e0960f165ddb6421cc3efd7b5eae28a1509928949587dd0241caee0a97875cbe823ab07c86070afd5ac33ab4c0464d1cda2da
7
- data.tar.gz: 0f26cfda18f8aca504cf6a00505fd933326fb03fb4c1262262fb1fc75e02d057d1858cc7a38ba43815d1aa21529265849b0d46b876ece5b7de9e69fbbae7c65b
6
+ metadata.gz: 54eb96a7ba642dd2ea8c565f8e80c3f9362274cb20577a424cd8ba7058bbc194bcba7209f070a0e198c500d9dd5c9b7ba8d80f90a32a02920fa09ca020301edc
7
+ data.tar.gz: 35612669bd04001643923078904ed3f2822c0eb533f1b7d0102b38375c63d364816005f317425790d8281ef3d5cbeb8c2dd2df773663a8d7250dd9ac37f37eca
data/README.md CHANGED
@@ -8,9 +8,13 @@ variants and othe cryptoprimitives widely used in Thrift projects, namely:
8
8
  * RSAES-OAEP encryption
9
9
  * RSASS-PSS signing
10
10
  * Pollard 'rho' factorization
11
+ * Fast orime generation
11
12
  * SHA1 and SHA256 hashes (under development)
12
13
  * RJ256/256 (under development)
13
14
 
15
+ All long operation are being preformed releasing GVL so other ruby threads can execute while ttcrypt
16
+ thinks.
17
+
14
18
  ## Installation
15
19
 
16
20
  Current implementation targeted fro MRI ruby 2.0+.
@@ -193,6 +193,9 @@ namespace thrift {
193
193
  Convert to BIE ENDIAN bytes array.
194
194
  */
195
195
  byte_buffer to_byte_buffer() const noexcept {
196
+ // Workaround for some Andoid targets
197
+ if( *this == 0 )
198
+ return byte_buffer::pad(0, 1);
196
199
  size_t count = (mpz_sizeinbase (val, 2) + 7) / 8;
197
200
  byte_buffer res = byte_buffer(count);
198
201
  size_t count2 = count;
@@ -26,6 +26,7 @@
26
26
 
27
27
  #include <iostream>
28
28
  #include <string.h>
29
+ #include <memory>
29
30
  #include "text_utils.h"
30
31
 
31
32
  using namespace std;
@@ -110,13 +111,11 @@ namespace thrift {
110
111
  }
111
112
  }
112
113
 
113
-
114
- /**
115
- Fill constructor. Create buffer with specified size and fill value
116
- */
117
- byte_buffer(byte fill, size_t size)
118
- : buffer(new byte[size]), length(size), _capacity(size) {
119
- memset( buffer.get(), fill, size);
114
+ template<typename T>
115
+ static byte_buffer pad(T fill, size_t size) {
116
+ byte_buffer result(size);
117
+ memset( result.data().get(), (int)fill, size);
118
+ return result;
120
119
  }
121
120
 
122
121
  shared_ptr<byte> data() const noexcept {
@@ -27,25 +27,6 @@ using namespace thrift;
27
27
  using namespace std;
28
28
 
29
29
  inline big_integer rho(const big_integer& n) {
30
- /*
31
- BigInteger divisor;
32
- BigInteger c = new BigInteger(N.bitLength(), random);
33
- BigInteger x = new BigInteger(N.bitLength(), random);
34
- BigInteger xx = x;
35
-
36
- // check divisibility by 2
37
- if (N.mod(two).compareTo(BigInteger.ZERO) == 0) return two;
38
-
39
- do {
40
- x = x.multiply(x).mod(N).add(c).mod(N);
41
- xx = xx.multiply(xx).mod(N).add(c).mod(N);
42
- xx = xx.multiply(xx).mod(N).add(c).mod(N);
43
- divisor = x.subtract(xx).gcd(N);
44
- } while ((divisor.compareTo(BigInteger.ONE)) == 0);
45
-
46
- return divisor;
47
- }
48
- */
49
30
  big_integer divisor;
50
31
  auto c = big_integer::random_bits(n.bit_length());
51
32
  auto x = big_integer::random_bits(n.bit_length());
@@ -21,10 +21,9 @@
21
21
  along with this program. If not, see <http://www.gnu.org/licenses/>.
22
22
  */
23
23
 
24
+ #include <future>
24
25
  #include "rsa_key.h"
25
26
  #include "ttcrypt.h"
26
- #include <assert.h>
27
- #include <future>
28
27
 
29
28
  using namespace ttcrypt;
30
29
  using namespace thrift;
@@ -34,13 +33,14 @@ namespace ttcrypt {
34
33
  static byte_buffer mgf1(const byte_buffer& z, size_t l) {
35
34
  const size_t hLen = 20;
36
35
  byte_buffer t;
37
- for (unsigned i = 0; i <= l / hLen; i++)
36
+ for (unsigned i = 0; i <= l / hLen; i++) {
38
37
  t += sha1(z + i2osp(i, 4));
38
+ }
39
39
  return byte_buffer(t, 0, l - 1);
40
40
  }
41
41
 
42
42
  byte_buffer eme_oaep_encode(const byte_buffer& message, size_t emLen,
43
- const byte_buffer& p, const byte_buffer* pseed) {
43
+ const byte_buffer* p, const byte_buffer* pseed) {
44
44
  const size_t hLen = 20;
45
45
  const size_t hLen2 = 2 * hLen;
46
46
 
@@ -51,19 +51,19 @@ byte_buffer eme_oaep_encode(const byte_buffer& message, size_t emLen,
51
51
  if (mLen >= emLen - 1 - hLen2 || mLen > emLen - 2 * hLen2 - 1)
52
52
  throw rsa_key::error("message too long");
53
53
 
54
- byte_buffer ps = byte_buffer('\0', emLen - mLen - hLen2 - 1);
55
- byte_buffer pHash = sha1(p);
56
- byte_buffer db = pHash + ps + "\001" + message;
57
- byte_buffer seed = (pseed != 0) ? *pseed : byte_buffer::random(hLen);
58
- byte_buffer dbMask = mgf1(seed, emLen - hLen);
59
- byte_buffer maskedDb = db ^ dbMask;
60
- byte_buffer seedMask = mgf1(maskedDb, hLen);
61
- byte_buffer maskedSeed = seed ^ seedMask;
54
+ auto ps = byte_buffer::pad('\0', emLen - mLen - hLen2 - 1);
55
+ auto pHash = sha1(p ? *p : "");
56
+ auto db = pHash + ps + "\001" + message;
57
+ auto seed = (pseed != 0) ? *pseed : byte_buffer::random(hLen);
58
+ auto dbMask = mgf1(seed, emLen - hLen);
59
+ auto maskedDb = db ^ dbMask;
60
+ auto seedMask = mgf1(maskedDb, hLen);
61
+ auto maskedSeed = seed ^ seedMask;
62
62
 
63
63
  return maskedSeed + maskedDb;
64
64
  }
65
65
 
66
- byte_buffer eme_oaep_decode(const byte_buffer& message, const byte_buffer& p) {
66
+ byte_buffer eme_oaep_decode(const byte_buffer& message, const byte_buffer* p) {
67
67
  const size_t hLen = 20;
68
68
  if (message.size() < hLen * 2 + 1)
69
69
  throw rsa_key::error("message is too short");
@@ -74,11 +74,11 @@ byte_buffer eme_oaep_decode(const byte_buffer& message, const byte_buffer& p) {
74
74
  auto seed = maskedSeed ^ seedMask;
75
75
  auto db_mask = mgf1(seed, message.size() - hLen);
76
76
  auto db = maskedDb ^ db_mask;
77
- auto pHash = sha1(p);
77
+ auto pHash = sha1(p ? *p : "");
78
78
 
79
79
  int index = db.index_of('\001', hLen);
80
80
  if (index < 0)
81
- throw rsa_key::error("message is invalid");
81
+ throw rsa_key::error("message is invalid (no 1)");
82
82
 
83
83
  byte_buffer pHash2(db, 0, hLen - 1);
84
84
  byte_buffer ps(db, hLen, index - 1);
@@ -86,7 +86,7 @@ byte_buffer eme_oaep_decode(const byte_buffer& message, const byte_buffer& p) {
86
86
 
87
87
  for (auto x : ps) {
88
88
  if (x != '\0')
89
- throw rsa_key::error("message is invalid");
89
+ throw rsa_key::error("message is invalid (zero padding)");
90
90
  }
91
91
 
92
92
  if (pHash2 != pHash)
@@ -96,9 +96,9 @@ byte_buffer eme_oaep_decode(const byte_buffer& message, const byte_buffer& p) {
96
96
  }
97
97
 
98
98
  byte_buffer rsa_key::rsadp(const byte_buffer& ciphertext) const {
99
- big_integer c = big_integer(ciphertext);
99
+ big_integer c = ciphertext;
100
100
  if (c >= n - 1)
101
- throw rsa_key::error("cipertext is too long");
101
+ throw rsa_key::error("ciphertext is too long");
102
102
  if (fast_key) {
103
103
  // Fast
104
104
  auto m1 = powmod_sec((c % p), dp, p);
@@ -135,9 +135,9 @@ byte_buffer emsa_pss_encode(const byte_buffer& message, size_t emBits,
135
135
  if (emLen < hLen + sLen + 2)
136
136
  throw rsa_key::error("invliad salt length");
137
137
 
138
- auto M1 = byte_buffer('\0', 8) + mHash + salt;
138
+ auto M1 = byte_buffer::pad('\0', 8) + mHash + salt;
139
139
  auto H = hash(M1);
140
- auto PS = byte_buffer('\0', emLen - sLen - hLen - 2);
140
+ auto PS = byte_buffer::pad('\0', emLen - sLen - hLen - 2);
141
141
  auto DB = PS.append_byte(1) + salt;
142
142
  auto dbMask = mgf1(H, emLen - hLen - 1);
143
143
 
@@ -195,7 +195,7 @@ bool emsa_pss_verify(const byte_buffer& source_message,
195
195
 
196
196
  byte_buffer salt(DB, -sLen, -1);
197
197
 
198
- auto M1 = byte_buffer('\0', 8) + mHash + salt;
198
+ auto M1 = byte_buffer::pad('\0', 8) + mHash + salt;
199
199
  auto H1 = hash(M1);
200
200
  return H == H1;
201
201
  }
@@ -278,9 +278,14 @@ rsa_key rsa_key::generate(unsigned int k, size_t e) {
278
278
 
279
279
  // v2.2 Algorithm
280
280
  while (true) {
281
+ #ifdef NO_FUTURE
282
+ auto q = prime(k - k / 2);
283
+ auto p = prime(k/2);
284
+ #else
281
285
  auto future = std::async(std::launch::async, [k] {return prime(k/2);});
282
286
  auto q = prime(k - k / 2);
283
287
  auto p = future.get();
288
+ #endif
284
289
  if (p == q)
285
290
  continue;
286
291
 
@@ -302,8 +307,7 @@ rsa_key rsa_key::generate(unsigned int k, size_t e) {
302
307
  throw logic_error("pq generation failed");
303
308
  }
304
309
 
305
- void rsa_key::set(string name, const thrift::big_integer &value) {
306
- std::transform(name.begin(), name.end(), name.begin(), ::tolower);
310
+ void rsa_key::set(const string& name, const thrift::big_integer &value) {
307
311
  switch (name[0]) {
308
312
  case 'e':
309
313
  e = value;
@@ -369,5 +373,219 @@ unordered_map<string, big_integer> rsa_key::get_params(bool include_all) const
369
373
  return params;
370
374
  }
371
375
 
376
+ static ostream *pout;
377
+
378
+ #define LHEX(text,data) {*pout<<text<<":\n"<<data.hex(16)<<endl;}
379
+
380
+ #define REQUIRE(x) if(!(x)){*pout<<"Failed "<<(#x)<<" @"<<__FILE__<<":"<<__LINE__<<endl; return false;}
381
+
382
+
383
+ bool rsa_key::self_test(ostream& out) {
384
+ pout = &out;
385
+ {
386
+ out << "we start..." << endl;
387
+ big_integer mi = pow(2_b,1024) - 173_b;
388
+
389
+ if( big_integer(mi.to_byte_buffer()) != mi ) {
390
+ out << "Decoding problem" << endl;
391
+ return false;
392
+ }
393
+ byte_buffer res = i2osp(65537_b);
394
+ if( res.hex() != "01 00 01") {
395
+ out << "i2osp fail: " << res.hex() << endl;
396
+ return false;
397
+ }
398
+
399
+ mi = os2ip(res);
400
+ if( mi != 65537_b ) {
401
+ out << "I2OSP/OS2IP failure: Result is not 65537: " << mi << endl;
402
+ return false;
403
+ }
404
+
405
+ mi = pow(2_b,1023) - 1_b;
406
+ byte_buffer x = rsadp( rsaep(mi.to_byte_buffer()) );
407
+
408
+ if( big_integer(x) != mi ) {
409
+ out << "Big integer failure: " << big_integer(x) << endl;
410
+ return false;
411
+ }
412
+
413
+
414
+ byte_buffer src("hello!");
415
+ if( i2osp( os2ip(src), 6) != src ) {
416
+ out << "Failed osp2: " << i2osp( os2ip(src), 6) << endl;
417
+ return false;
418
+ }
419
+
420
+ string sres = i2osp(254,3).hex();
421
+ if( sres != "00 00 fe" ) {
422
+ out << "i20sp padding failure: " << sres << endl;
423
+ return false;
424
+ }
425
+
426
+ if( sha1("abc") != decode_hex("a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d") ) {
427
+ out << "SHA1 failed: " << sha1("abc").hex() << endl;
428
+ return false;
429
+ }
430
+
431
+ if( sha1("") != decode_hex("da39a3ee 5e6b4b0d 3255bfef 95601890 afd80709") ) {
432
+ out << "SHA1 of empty string failed: " << sha1("").hex() << endl;
433
+ return false;
434
+ }
435
+
436
+ res = eme_oaep_decode(eme_oaep_encode(src, 127, 0, 0), 0);
437
+ if( res != src ) {
438
+ out << "OAEP failed: " << res;
439
+ return false;
440
+ }
441
+
442
+ }
443
+ {
444
+ out << "RSAES test" << endl;
445
+ auto message = decode_hex("d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49");
446
+
447
+ auto seed = decode_hex("aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 f0 6c b5 8f");
448
+
449
+ auto encoded_message = decode_hex("\
450
+ eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2 ca 82 31 0b 26 dc d8 7d 5c 68\
451
+ f1 ee a8 f5 52 67 c3 1b 2e 8b b4 25 1f 84 d7 e0 b2 c0 46 26 f5 af f9 3e dc\
452
+ fb 25 c9 c2 b3 ff 8a e1 0e 83 9a 2d db 4c dc fe 4f f4 77 28 b4 a1 b7 c1 36\
453
+ 2b aa d2 9a b4 8d 28 69 d5 02 41 21 43 58 11 59 1b e3 92 f9 82 fb 3e 87 d0\
454
+ 95 ae b4 04 48 db 97 2f 3a c1 4f 7b c2 75 19 52 81 ce 32 d2 f1 b7 6d 4d 35\
455
+ 3e 2d");
456
+
457
+ auto encrypted_message = decode_hex("\
458
+ 12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 39 a3 3d 1e 99 6f c8 2a 94\
459
+ cc d3 00 74 c9 5d f7 63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 53 c1\
460
+ 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb 6d 84 b1 c3 1d 65 4a 19 70 e5 78\
461
+ 3b d6 eb 96 a0 24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 da 95 36 ad\
462
+ 87 00 c8 4f c9 13 0a de a7 4e 55 8d 51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06\
463
+ 3e 09 55");
464
+
465
+ auto n = decode_hex("\
466
+ bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 36 8d 07 ee d4 10 43 a4\
467
+ 40 d6 b6 f0 74 54 f5 1f b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48\
468
+ 76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f af b8 e0 a3 df c7 37 72\
469
+ 3e e6 b4 b7 d9 3a 25 84 ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e\
470
+ e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f e2 53 72 98 ca 2a 8f 59\
471
+ 46 f8 e5 fd 09 1d bd cb");
472
+
473
+ unsigned e = 0x11;
474
+
475
+ auto p = decode_hex("\
476
+ ee cf ae 81 b1 b9 b3 c9 08 81 0b 10 a1 b5 60 01 99 eb 9f 44 ae f4 fd a4\
477
+ 93 b8 1a 9e 3d 84 f6 32 12 4e f0 23 6e 5d 1e 3b 7e 28 fa e7 aa 04 0a 2d\
478
+ 5b 25 21 76 45 9d 1f 39 75 41 ba 2a 58 fb 65 99");
479
+
480
+ auto q = decode_hex("\
481
+ c9 7f b1 f0 27 f4 53 f6 34 12 33 ea aa d1 d9 35 3f 6c 42 d0 88 66 b1 d0\
482
+ 5a 0f 20 35 02 8b 9d 86 98 40 b4 16 66 b4 2e 92 ea 0d a3 b4 32 04 b5 cf\
483
+ ce 33 52 52 4d 04 16 a5 a4 41 e7 00 af 46 15 03");
484
+
485
+ // auto dP = decode_hex("\
486
+ // 54 49 4c a6 3e ba 03 37 e4 e2 40 23 fc d6 9a 5a eb 07 dd dc 01 83 a4 d0\
487
+ // ac 9b 54 b0 51 f2 b1 3e d9 49 09 75 ea b7 74 14 ff 59 c1 f7 69 2e 9a 2e\
488
+ // 20 2b 38 fc 91 0a 47 41 74 ad c9 3c 1f 67 c9 81");
489
+ //
490
+ // auto dQ = decode_hex("\
491
+ // 47 1e 02 90 ff 0a f0 75 03 51 b7 f8 78 86 4c a9 61 ad bd 3a 8a 7e 99 1c\
492
+ // 5c 05 56 a9 4c 31 46 a7 f9 80 3f 8f 6f 8a e3 42 e9 31 fd 8a e4 7a 22 0d\
493
+ // 1b 99 a4 95 84 98 07 fe 39 f9 24 5a 98 36 da 3d");
494
+ //
495
+ // auto qInv = decode_hex("\
496
+ // b0 6c 4f da bb 63 01 19 8d 26 5b db ae 94 23 b3 80 f2 71 f7 34 53 88 50\
497
+ // 93 07 7f cd 39 e2 11 9f c9 86 32 15 4f 58 83 b1 67 a9 67 bf 40 2b 4e 9e\
498
+ // 2e 0f 96 56 e6 98 ea 36 66 ed fb 25 79 80 39 f7");
499
+
500
+ rsa_key key(n, e, p, q);
501
+ key.debug_seed(seed);
502
+
503
+ REQUIRE( key.encrypt(message).hex() == encrypted_message.hex() );
504
+ REQUIRE( key.decrypt(encrypted_message).hex() == message.hex() );
505
+
506
+ rsa_key key2(n, e, p, q);
507
+ REQUIRE( key2.is_private() == true);
508
+
509
+ REQUIRE( key2.decrypt(encrypted_message).hex() == message.hex() );
510
+ }
511
+ {
512
+ out << "Sign test" << endl;
513
+
514
+ auto signing_salt = decode_hex("e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8 3b ce 7e 61");
515
+
516
+ auto message = decode_hex("85 9e ef 2f d7 8a ca 00 30 8b dc 47 11 93 bf 55"
517
+ "bf 9d 78 db 8f 8a 67 2b 48 46 34 f3 c9 c2 6e 64"
518
+ "78 ae 10 26 0f e0 dd 8c 08 2e 53 a5 29 3a f2 17"
519
+ "3c d5 0c 6d 5d 35 4f eb f7 8b 26 02 1c 25 c0 27"
520
+ "12 e7 8c d4 69 4c 9f 46 97 77 e4 51 e7 f8 e9 e0"
521
+ "4c d3 73 9c 6b bf ed ae 48 7f b5 56 44 e9 ca 74"
522
+ "ff 77 a5 3c b7 29 80 2f 6e d4 a5 ff a8 ba 15 98"
523
+ "90 fc");
524
+ auto EM = decode_hex(
525
+ "66 e4 67 2e 83 6a d1 21 ba 24 4b ed 65 76 b8 67"
526
+ "d9 a4 47 c2 8a 6e 66 a5 b8 7d ee 7f bc 7e 65 af"
527
+ "50 57 f8 6f ae 89 84 d9 ba 7f 96 9a d6 fe 02 a4"
528
+ "d7 5f 74 45 fe fd d8 5b 6d 3a 47 7c 28 d2 4b a1"
529
+ "e3 75 6f 79 2d d1 dc e8 ca 94 44 0e cb 52 79 ec"
530
+ "d3 18 3a 31 1f c8 96 da 1c b3 93 11 af 37 ea 4a"
531
+ "75 e2 4b db fd 5c 1d a0 de 7c ec df 1a 89 6f 9d"
532
+ "8b c8 16 d9 7c d7 a2 c4 3b ad 54 6f be 8c fe bc");
533
+
534
+ //# RSA modulus n:
535
+ auto n = decode_hex("\
536
+ a2 ba 40 ee 07 e3 b2 bd 2f 02 ce 22 7f 36 a1 95\
537
+ 02 44 86 e4 9c 19 cb 41 bb bd fb ba 98 b2 2b 0e\
538
+ 57 7c 2e ea ff a2 0d 88 3a 76 e6 5e 39 4c 69 d4\
539
+ b3 c0 5a 1e 8f ad da 27 ed b2 a4 2b c0 00 fe 88\
540
+ 8b 9b 32 c2 2d 15 ad d0 cd 76 b3 e7 93 6e 19 95\
541
+ 5b 22 0d d1 7d 4e a9 04 b1 ec 10 2b 2e 4d e7 75\
542
+ 12 22 aa 99 15 10 24 c7 cb 41 cc 5e a2 1d 00 ee\
543
+ b4 1f 7c 80 08 34 d2 c6 e0 6b ce 3b ce 7e a9 a5");
544
+
545
+ //# RSA public exponent e:
546
+ auto e = 0x010001;
547
+ //
548
+ //# Prime p:
549
+ auto p = decode_hex("\
550
+ d1 7f 65 5b f2 7c 8b 16 d3 54 62 c9 05 cc 04 a2\
551
+ 6f 37 e2 a6 7f a9 c0 ce 0d ce d4 72 39 4a 0d f7\
552
+ 43 fe 7f 92 9e 37 8e fd b3 68 ed df f4 53 cf 00\
553
+ 7a f6 d9 48 e0 ad e7 57 37 1f 8a 71 1e 27 8f 6b");
554
+
555
+ //# Prime q:
556
+ auto q = decode_hex("\
557
+ c6 d9 2b 6f ee 74 14 d1 35 8c e1 54 6f b6 29 87\
558
+ 53 0b 90 bd 15 e0 f1 49 63 a5 e2 63 5a db 69 34\
559
+ 7e c0 c0 1b 2a b1 76 3f d8 ac 1a 59 2f b2 27 57\
560
+ 46 3a 98 24 25 bb 97 a3 a4 37 c5 bf 86 d0 3f 2f");
561
+
562
+ auto signature = decode_hex("\
563
+ 8d aa 62 7d 3d e7 59 5d 63 05 6c 7e c6 59 e5 44\
564
+ 06 f1 06 10 12 8b aa e8 21 c8 b2 a0 f3 93 6d 54\
565
+ dc 3b dc e4 66 89 f6 b7 95 1b b1 8e 84 05 42 76\
566
+ 97 18 d5 71 5d 21 0d 85 ef bb 59 61 92 03 2c 42\
567
+ be 4c 29 97 2c 85 62 75 eb 6d 5a 45 f0 5f 51 87\
568
+ 6f c6 74 3d ed dd 28 ca ec 9b b3 0e a9 9e 02 c3\
569
+ 48 82 69 60 4f e4 97 f7 4c cd 7c 7f ca 16 71 89\
570
+ 71 23 cb d3 0d ef 5d 54 a2 b5 53 6a d9 0a 74 7e");
571
+
572
+ auto padded = emsa_pss_encode(message, 1023, sha1, &signing_salt);
573
+ REQUIRE( padded.hex() == EM.hex() );
574
+ REQUIRE(true == emsa_pss_verify(message, padded, 1023, sha1, signing_salt.size()));
575
+ REQUIRE(false == emsa_pss_verify(message+"!", padded, 1023, sha1, signing_salt.size()));
576
+ padded.set(0, padded[0] ^ 3);
577
+ REQUIRE(false == emsa_pss_verify(message, padded, 1023, sha1, signing_salt.size()));
578
+
579
+ rsa_key key(n, e, p, q);
580
+ auto s = key.sign(message, sha1, &signing_salt);
581
+ REQUIRE( s == signature );
582
+ REQUIRE( key.verify(message, s, sha1, signing_salt.size()) == true );
583
+
584
+ s = key.sign(message+"!", sha1, &signing_salt);
585
+ REQUIRE( s != signature );
586
+ }
587
+ return true;
588
+ }
589
+
372
590
  }
373
591
 
@@ -33,8 +33,8 @@ namespace ttcrypt {
33
33
 
34
34
  using namespace thrift;
35
35
 
36
- byte_buffer eme_oaep_encode( const byte_buffer& message,size_t emLen, const byte_buffer& p=byte_buffer(), const byte_buffer *seed=nullptr);
37
- byte_buffer eme_oaep_decode(const byte_buffer& message,const byte_buffer& p="");
36
+ byte_buffer eme_oaep_encode( const byte_buffer& message,size_t emLen, const byte_buffer* p=0, const byte_buffer *seed=nullptr);
37
+ byte_buffer eme_oaep_decode(const byte_buffer& message,const byte_buffer* p=0);
38
38
 
39
39
  byte_buffer emsa_pss_encode(const byte_buffer& message,size_t emBits,byte_buffer (*hash)(const byte_buffer&),const byte_buffer* salt);
40
40
  bool emsa_pss_verify(const byte_buffer& source_message,
@@ -80,7 +80,7 @@ namespace ttcrypt {
80
80
  Set the named parameter to a given value. Supported values are: n, e, d, p, q, dp, dq, qinv.
81
81
  Not case sesitive. Call normalize_key() when done changing parameters.
82
82
  */
83
- void set(string name, const big_integer& value);
83
+ void set(const string& name, const big_integer& value);
84
84
 
85
85
  /**
86
86
  Construct private key from parts. If not all parts are provided, recalculates missing ones that
@@ -123,7 +123,7 @@ namespace ttcrypt {
123
123
  RSAES-OAEP encrypt a message.
124
124
  */
125
125
  byte_buffer encrypt(const byte_buffer& plaintext) const {
126
- return rsaep(eme_oaep_encode(plaintext, byte_size - 1,"", pseed));
126
+ return rsaep(eme_oaep_encode(plaintext, byte_size - 1, 0, pseed));
127
127
  }
128
128
 
129
129
  /**
@@ -132,7 +132,9 @@ namespace ttcrypt {
132
132
  byte_buffer decrypt(const byte_buffer& ciphertext) const {
133
133
  return eme_oaep_decode( rsadp( ciphertext) );
134
134
  }
135
-
135
+
136
+ bool self_test(ostream& os);
137
+
136
138
  /**
137
139
  Create RSASSA-PSS signature for a given message. Requires private key.
138
140
  @param message what to sign
@@ -216,6 +218,8 @@ namespace ttcrypt {
216
218
  _use_blinding = use;
217
219
  }
218
220
 
221
+ byte_buffer get_e() const { return e.to_byte_buffer(); }
222
+
219
223
  private:
220
224
  big_integer n, e, p, q, d, dp, dq, q_inv;
221
225
  unsigned byte_size=0, bits_size=0;
@@ -20,8 +20,13 @@
20
20
  along with this program. If not, see <http://www.gnu.org/licenses/>.
21
21
  */
22
22
 
23
+ #include <stdarg.h>
23
24
  #include "text_utils.h"
24
25
 
26
+ template<typename X>
27
+ X ABS(X val) {
28
+ return val < 0 ? -val : val;
29
+ }
25
30
 
26
31
  std::string sformat(const std::string fmt_str, ...) {
27
32
  int final_n, n = ((int)fmt_str.size()) * 2; /* reserve 2 times as much as the length of the fmt_str */
@@ -35,7 +40,7 @@ std::string sformat(const std::string fmt_str, ...) {
35
40
  final_n = vsnprintf(&formatted[0], n, fmt_str.c_str(), ap);
36
41
  va_end(ap);
37
42
  if (final_n < 0 || final_n >= n)
38
- n += abs(final_n - n + 1);
43
+ n += ABS(final_n - n + 1);
39
44
  else
40
45
  break;
41
46
  }
@@ -54,7 +59,7 @@ std::string vsformat(const std::string fmt_str, va_list args) {
54
59
  final_n = vsnprintf(&formatted[0], n-1, fmt_str.c_str(), c);
55
60
  va_end(c);
56
61
  if (final_n < 0 || final_n >= n)
57
- n += abs(final_n - n + 1);
62
+ n += ABS(final_n - n + 1);
58
63
  else
59
64
  break;
60
65
  }
@@ -25,6 +25,7 @@
25
25
  #define __zcoin__text_utils__
26
26
 
27
27
  #include <iostream>
28
+ #include <memory>
28
29
 
29
30
  std::string sformat(const std::string fmt_str, ...);
30
31
  std::string vsformat(const std::string fmt_str, va_list args);
@@ -45,7 +45,7 @@ byte_buffer ttcrypt::i2osp(const big_integer& i, size_t block_size) noexcept {
45
45
  if( block_size > 0 && res.size() != block_size ) {
46
46
  size_t pad_length = block_size - res.size() % block_size;
47
47
  if( pad_length > 0 )
48
- return byte_buffer('\0', pad_length) + res;
48
+ return byte_buffer::pad('\0', pad_length) + res;
49
49
  }
50
50
  return res;
51
51
  }
@@ -118,6 +118,25 @@ static VALUE factorize(VALUE self, VALUE composite) {
118
118
  });
119
119
  }
120
120
 
121
+ static VALUE _generate_prime(VALUE self, VALUE bits) {
122
+ return wrap_exceptions([=] {
123
+ unsigned nbits = FIX2INT(bits);
124
+ big_integer prime;
125
+ ruby_unblock([nbits, &prime] {
126
+ auto min = pow(2_b, nbits-1);
127
+ auto max = 2*min - 1;
128
+ big_integer random;
129
+ do {
130
+ random = big_integer::random_between(min, max);
131
+ prime = next_prime(random);
132
+ } while( prime > max );
133
+ if( prime.bit_length() != nbits )
134
+ throw std::logic_error("random generation logic failed");
135
+ });
136
+ return to_hex_value(prime);
137
+ });
138
+ }
139
+
121
140
  typedef byte_buffer (*hash_t)(const byte_buffer &);
122
141
 
123
142
  static hash_t hash_provider(VALUE name) {
@@ -213,6 +232,7 @@ void Init_ttcrypt(void) {
213
232
  VALUE ttcrypt_module = rb_define_module("TTCrypt");
214
233
 
215
234
  rb_define_method(ttcrypt_module, "_factorize", (ruby_method) factorize, 1);
235
+ rb_define_method(ttcrypt_module, "_generate_prime", (ruby_method) _generate_prime, 1);
216
236
 
217
237
  rsa_class = rb_define_class_under(ttcrypt_module, "RsaKey", rb_cObject);
218
238
  rb_define_alloc_func(rsa_class, rsa_alloc);
@@ -1,5 +1,5 @@
1
1
  module TTCrypt
2
2
 
3
- VERSION = '0.0.2'
3
+ VERSION = '0.0.3'
4
4
 
5
5
  end
data/lib/ttcrypt.rb CHANGED
@@ -13,6 +13,13 @@ module TTCrypt
13
13
  _factorize(hex).map { |x| x.to_i(16) }
14
14
  end
15
15
 
16
+ # Generate random probable prime number with a given bits length. This implementation will generate
17
+ # prime such as 2^(bits-1) < prime < 2 ^ bits.
18
+ #
19
+ def generate_prime bits
20
+ _generate_prime(bits).to_i(16)
21
+ end
22
+
16
23
  # Implementation of RSAES-OAEP encryption and RSASSA-PSS signing
17
24
  # accroding to pkcs#1 v2.2 specification. Does NOT implement any previous cryptographically
18
25
  # weak shcemes (like 1.5 signature) - go use openssl for itm but it does compromise private
@@ -137,6 +144,6 @@ end
137
144
  require 'ttcrypt/ttcrypt'
138
145
 
139
146
  module TTCrypt
140
- module_function :factorize, :_factorize
147
+ module_function :factorize, :_factorize, :generate_prime, :_generate_prime
141
148
  end
142
149
 
data/spec/ttcrypt_spec.rb CHANGED
@@ -16,9 +16,21 @@ describe 'rsa-oaep' do
16
16
  factors[0].should == p2
17
17
  factors[1].should == p1
18
18
 
19
- val = 177130
19
+ val = 177130
20
20
  factors = TTCrypt.factorize(val)
21
- factors.reduce(1){|all, x| x*all}.should == val
21
+ factors.reduce(1) { |all, x| x*all }.should == val
22
+ end
23
+
24
+ it 'should generate primes' do
25
+ bits = 35
26
+ primes = 2.times.map {
27
+ x = TTCrypt.generate_prime bits
28
+ x.should > (1<<(bits-1))
29
+ x.should < (1<<(bits))
30
+ x
31
+ }
32
+ primes.sort!
33
+ TTCrypt.factorize(primes[0] * primes[1]).sort.should == primes
22
34
  end
23
35
 
24
36
  it 'should generate keys in background' do
@@ -96,7 +108,7 @@ describe 'rsa-oaep' do
96
108
  end
97
109
  end
98
110
 
99
- it 'should construct from components' do
111
+ it 'should construct from components and decrypt' do
100
112
  init_test_vectors1
101
113
  key = TTCrypt::RsaKey.new e: @e, p: @p, q: @q
102
114
  key.p.should == @p
@@ -108,6 +120,20 @@ describe 'rsa-oaep' do
108
120
  key.decrypt(key.extract_public.encrypt(@message)).should == @message
109
121
  end
110
122
 
123
+ it 'should properly encrypt' do
124
+ init_test_vectors1
125
+ key = TTCrypt::RsaKey.new e: @e, p: @p, q: @q
126
+ key.p.should == @p
127
+ key.q.should == @q
128
+ key.e.should == @e
129
+ key.should be_private
130
+ key.n.should_not be_nil
131
+ key.decrypt(key.encrypt(@message)).should == @message
132
+ key.decrypt(key.extract_public.encrypt(@message)).should == @message
133
+ end
134
+
135
+ it 'should properly sign'
136
+
111
137
  def init_test_vectors1
112
138
  @n = h2s <<-End
113
139
  bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 36 8d 07 ee d4 10 43 a4
@@ -146,7 +172,7 @@ describe 'rsa-oaep' do
146
172
 
147
173
  def h2s hex
148
174
  hex = hex.gsub(/\s+/, '')
149
- hex.chars.each_slice(2).map{|x,y| (x.to_i(16)<<4 | y.to_i(16)).chr}.join
175
+ hex.chars.each_slice(2).map { |x, y| (x.to_i(16)<<4 | y.to_i(16)).chr }.join
150
176
  end
151
177
 
152
178
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ttcrypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergeych
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-19 00:00:00.000000000 Z
11
+ date: 2014-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler