PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Anumber.cpp

https://github.com/Proch92/RSA
C++ | 920 lines | 724 code | 196 blank | 0 comment | 195 complexity | e6f2210067ae052484bdf99ac962f442 MD5 | raw file
  1. #include "stdlib.h"
  2. #include "stdio.h"
  3. #include "string.h"
  4. #include "time.h"
  5. #include "math.h"
  6. #include "Anumber.h"
  7. Anumber karatsuba(const Anumber&, const Anumber&);
  8. Anumber schoolbook(Anumber, Anumber);
  9. Anumber eucEx(Anumber&, Anumber&, Anumber&, Anumber&);
  10. Anumber::Anumber() {
  11. sign = false;
  12. srand(time(NULL));
  13. }
  14. Anumber::Anumber(const Anumber& init) {
  15. int i;
  16. for(i=0; i!=BUFLEN; i++)
  17. buffer[i] = init.buffer[i];
  18. sign = init.sign;
  19. srand(time(NULL));
  20. }
  21. Anumber::Anumber(char* init) {
  22. if(*init == '-') {
  23. sign = true;
  24. init++;
  25. }
  26. else sign = false;
  27. int lung = strlen(init);
  28. memset(buffer, 0, BUFLEN - lung);
  29. strncpy(buffer + (BUFLEN - lung), init, lung);
  30. char *ptr;
  31. ptr = buffer + (BUFLEN - lung);
  32. int i;
  33. for(i=0; i!=lung; i++) {
  34. *ptr -= 48;
  35. ptr++;
  36. }
  37. srand(time(NULL));
  38. }
  39. Anumber::Anumber(char* init, int size) {
  40. sign = false;
  41. int lung = size;
  42. memset(buffer, 0, BUFLEN - lung);
  43. strncpy(buffer + (BUFLEN - lung), init, lung);
  44. char *ptr;
  45. ptr = buffer + (BUFLEN - lung);
  46. int i;
  47. for(i=0; i!=lung; i++) {
  48. *ptr -= 48;
  49. ptr++;
  50. }
  51. srand(time(NULL));
  52. }
  53. Anumber::Anumber(int init) {
  54. sign = (init < 0);
  55. memset(buffer, 0, BUFLEN);
  56. char *ptr;
  57. ptr = buffer + (BUFLEN - 1);
  58. while(init != 0) {
  59. *ptr = init % 10;
  60. init /= 10;
  61. ptr--;
  62. }
  63. srand(time(NULL));
  64. }
  65. int Anumber::len() {
  66. int i=0;
  67. bool found = false;
  68. while(!found && i != BUFLEN) {
  69. if(buffer[i] != 0) found = true;
  70. else i++;
  71. }
  72. return BUFLEN - i;
  73. }
  74. void Anumber::shr(int shift) {
  75. int i;
  76. for(i=BUFLEN - 1; i>=0; i--) {
  77. if(i < shift) buffer[i] = 0;
  78. else buffer[i] = buffer[i - shift];
  79. }
  80. }
  81. Anumber Anumber::invers(Anumber m) { //not working
  82. Anumber x(0);
  83. Anumber y(0);
  84. Anumber d;
  85. Anumber e(*this);
  86. d = eucEx(e, m, x, y);
  87. Anumber b(1);
  88. if ((b % d) == 0)
  89. return (x * (b / d)) % m;
  90. else {
  91. printf("error in key generation. [invers]\n");
  92. return Anumber(0);
  93. }
  94. }
  95. Anumber eucEx(Anumber &a, Anumber &b, Anumber &x, Anumber &y) {
  96. if(b == 0) {
  97. x = 1; y = 0;
  98. return a;
  99. }
  100. x = 0; y = 1;
  101. Anumber lastx(1);
  102. Anumber lasty(0);
  103. Anumber q(0);
  104. while(!(b == 0)) {
  105. q = a / b;
  106. Anumber tempa(a);
  107. a = b;
  108. b = tempa % b;
  109. Anumber tempx(x);
  110. x = lastx - (q * x);
  111. lastx = tempx;
  112. Anumber tempy(y);
  113. y = lasty - (q * y);
  114. lasty = tempy;
  115. }
  116. x = lastx;
  117. y = lasty;
  118. return a;
  119. }
  120. void Anumber::split(Anumber *half1, Anumber *half2, int lung) {
  121. int i;
  122. int med = lung / 2;
  123. char *tmp = buffer + (BUFLEN - lung);
  124. char *tmp1 = half1->buffer + (BUFLEN - (lung - med));
  125. char *tmp2 = half2->buffer + (BUFLEN - med);
  126. for(i=0; i!=(lung - med); i++) {
  127. *tmp1 = *tmp;
  128. tmp++;
  129. tmp1++;
  130. }
  131. for(i=0; i!=med; i++) {
  132. *tmp2 = *tmp;
  133. tmp++;
  134. tmp2++;
  135. }
  136. }
  137. void Anumber::random() {
  138. sign = false;
  139. int i;
  140. int len = BUFLEN / 10;
  141. for(i=BUFLEN - 1; i>=BUFLEN - len; i--)
  142. buffer[i] = rand()%10;
  143. }
  144. void Anumber::random(int len) {
  145. sign = false;
  146. int i;
  147. for(i=BUFLEN - 1; i>=BUFLEN - len; i--)
  148. buffer[i] = rand()%10;
  149. }
  150. void Anumber::show() {
  151. if(!len()) {
  152. printf("0\n");
  153. return;
  154. }
  155. if(sign)
  156. printf("-");
  157. int i;
  158. for(i=BUFLEN - len(); i!=BUFLEN; i++)
  159. printf("%d", buffer[i]);
  160. printf("\n");
  161. }
  162. void Anumber::show_all() {
  163. if(sign)
  164. printf("-");
  165. int i;
  166. for(i=0; i!=BUFLEN; i++)
  167. printf("%d", buffer[i]);
  168. printf("\n");
  169. }
  170. void Anumber::exp10(int shift) {
  171. if(shift == 0) return;
  172. int i;
  173. for(i = shift; i!=BUFLEN; i++) {
  174. buffer[i - shift] = buffer[i];
  175. if(i >= BUFLEN - shift) buffer[i] = 0;
  176. }
  177. }
  178. int Anumber::Alog10() { //it is supposed that the number is a 10 pow (i dont check the is10pow())
  179. int i;
  180. int returning = 0;
  181. bool found = false;
  182. for(i = 0; i!=BUFLEN && !found; i++)
  183. if(buffer[i] == 1) found = true;
  184. if(found)
  185. for(; i!=BUFLEN; i++)
  186. returning++;
  187. return returning;
  188. }
  189. bool Anumber::is10pow(){
  190. int i;
  191. bool found = false;
  192. for(i = 0; i!=BUFLEN && !found; i++) {
  193. if(buffer[i] > 1) return false;
  194. if(buffer[i] == 1) found = true;
  195. }
  196. if(found)
  197. for(; i!=BUFLEN; i++)
  198. if(buffer[i] != 0) return false;
  199. if(found) return true;
  200. return false;
  201. }
  202. Anumber Anumber::pow(Anumber exp) {
  203. Anumber base(*this);
  204. int oplen = exp.len();
  205. char* exp2 = (char*) malloc(oplen * oplen);
  206. int i=0;
  207. while(!(exp == 0)) {
  208. exp2[i] = exp % 2;
  209. exp /= 2;
  210. i++;
  211. }
  212. int len2 = i;
  213. Anumber pow(1);
  214. for(i=len2 - 1; i>=0; i--) {
  215. pow *= pow;
  216. if(exp2[i])
  217. pow *= base;
  218. }
  219. free(exp2);
  220. return pow;
  221. }
  222. Anumber Anumber::modExp(Anumber exp, const Anumber& mod) {
  223. int oplen = exp.len();
  224. char* exp2 = (char*) malloc(oplen * oplen);
  225. int i=0;
  226. while(!(exp == 0)) {
  227. exp2[i] = exp % 2;
  228. exp /= 2;
  229. i++;
  230. }
  231. int len2 = i;
  232. Anumber base(*this);
  233. Anumber result(1);
  234. for(i=0; i!=len2; i++) {
  235. if(exp2[i]) result = (result * base) % mod;
  236. base = (base * base) % mod;
  237. }
  238. free(exp2);
  239. return result;
  240. }
  241. void Anumber::operator = (const Anumber& op) {
  242. int i;
  243. for(i=0; i!=BUFLEN; i++)
  244. buffer[i] = op.buffer[i];
  245. sign = op.sign;
  246. }
  247. void Anumber::operator = (char op) {
  248. if(abs(op) < 10) {
  249. buffer[BUFLEN - 1] = op;
  250. sign = (op < 0);
  251. }
  252. }
  253. void Anumber::operator += (const Anumber& op) {
  254. char carry = 0;
  255. int i;
  256. for(i = BUFLEN - 1; i>=0; i--) {
  257. buffer[i] += op.buffer[i] + carry;
  258. if(buffer[i] > 9) {
  259. carry = 1;
  260. buffer[i] -= 10;
  261. }
  262. else carry = 0;
  263. }
  264. }
  265. void Anumber::operator -= (const Anumber& op) {
  266. char carry = 0;
  267. int i;
  268. for(i = BUFLEN - 1; i>=0; i--) {
  269. buffer[i] -= op.buffer[i] + carry;
  270. if(buffer[i] < 0) {
  271. carry = 1;
  272. buffer[i] += 10;
  273. }
  274. else carry = 0;
  275. }
  276. if(carry) sign = !sign;
  277. }
  278. Anumber Anumber::operator ++ () {
  279. char carry = 0;
  280. int i;
  281. i = BUFLEN - 1;
  282. buffer[i] += 1;
  283. if(buffer[i] > 9) {
  284. carry = 1;
  285. buffer[i] -= 10;
  286. }
  287. i--;
  288. for(; i>=0; i--) {
  289. buffer[i] += carry;
  290. if(buffer[i] > 9) {
  291. carry = 1;
  292. buffer[i] -= 10;
  293. }
  294. else carry = 0;
  295. }
  296. return *this;
  297. }
  298. Anumber Anumber::operator + (const Anumber& op) {
  299. Anumber result;
  300. if(!sign && !op.sign) {
  301. result = *this;
  302. result += op;
  303. result.sign = false;
  304. }
  305. else if(sign && op.sign) {
  306. result = *this;
  307. result += op;
  308. result.sign = true;
  309. }
  310. else if(sign ^ op.sign) {
  311. if(sign) {
  312. if(Aabs(*this) > op) {
  313. result = *this;
  314. result -= op;
  315. result.sign = true;
  316. }
  317. else {
  318. result = op;
  319. result -= *this;
  320. result.sign = false;
  321. }
  322. }
  323. else {
  324. if(*this > Aabs(op)) {
  325. result = *this;
  326. result -= op;
  327. result.sign = false;
  328. }
  329. else {
  330. result = op;
  331. result -= *this;
  332. result.sign = true;
  333. }
  334. }
  335. }
  336. return result;
  337. }
  338. Anumber Anumber::operator - (const Anumber& op) {
  339. Anumber result;
  340. if(!sign && !op.sign) {
  341. if(*this > op) {
  342. result = *this;
  343. result -= op;
  344. result.sign = false;
  345. }
  346. else {
  347. result = op;
  348. result -= *this;
  349. result.sign = true;
  350. }
  351. }
  352. else if(sign && op.sign) {
  353. if(*this > op) {
  354. result = op;
  355. result -= *this;
  356. result.sign = false;
  357. }
  358. else {
  359. result = *this;
  360. result -= op;
  361. result.sign = true;
  362. }
  363. }
  364. else if(sign ^ op.sign) {
  365. result = *this;
  366. result += op;
  367. if(sign)
  368. result.sign = true;
  369. else
  370. result.sign = false;
  371. }
  372. return result;
  373. }
  374. Anumber Anumber::operator - (char op) {
  375. Anumber returning(*this);
  376. if(op == 1) { //only 1 admitted... dont make 0 - 1 !!!!!!!!! OVERFLOW
  377. char carry = 0;
  378. int i;
  379. i = BUFLEN - 1;
  380. returning.buffer[i] -= 1;
  381. if(returning.buffer[i] < 0) {
  382. carry = 1;
  383. returning.buffer[i] += 10;
  384. }
  385. i--;
  386. for(; i>=0; i--) {
  387. returning.buffer[i] -= carry;
  388. if(returning.buffer[i] < 0) {
  389. carry = 1;
  390. returning.buffer[i] += 10;
  391. }
  392. else carry = 0;
  393. }
  394. return returning;
  395. }
  396. else printf("attenzione sottrazione per un numero char diverso da 1!!!\n");
  397. return returning;
  398. }
  399. bool Anumber::operator == (int num) {
  400. if(num == 0)
  401. return !(len());
  402. if(num == 1 && len() == 1 && buffer[BUFLEN - 1] == 1)
  403. return true;
  404. return false; //it counts only 0 and 1
  405. }
  406. bool Anumber::operator == (const Anumber& op) {
  407. if(sign != op.sign) return false;
  408. bool found = false;
  409. int i = 0;
  410. while (!found && i!=BUFLEN) {
  411. if(buffer[i] != op.buffer[i])
  412. found = true;
  413. i++;
  414. }
  415. return !found;
  416. }
  417. bool Anumber::operator != (int num) { //DOES NOT WORK PROPERLY
  418. if(num == 0) {
  419. int i = 0, lung = len();
  420. bool found = false;
  421. while(!found && i<lung) {
  422. if(buffer[i] != 0) found = true;
  423. i++;
  424. }
  425. return found;
  426. }
  427. return false; //it counts only 0
  428. }
  429. bool Anumber::operator > (const Anumber& op) {
  430. if(sign && !op.sign) return false;
  431. if(!sign && op.sign) return true;
  432. int i=0;
  433. while(i!=BUFLEN) {
  434. if(buffer[i] != op.buffer[i])
  435. return (buffer[i] > op.buffer[i]) ^ sign;
  436. i++;
  437. }
  438. return false;
  439. }
  440. bool Anumber::operator < (const Anumber& op) {
  441. if(sign && !op.sign) return true;
  442. if(!sign && op.sign) return false;
  443. int i=0;
  444. while(i!=BUFLEN) {
  445. if(buffer[i] != op.buffer[i])
  446. return (buffer[i] < op.buffer[i]) ^ sign;
  447. i++;
  448. }
  449. return false;
  450. }
  451. void Anumber::operator *= (const Anumber& op) {
  452. if(Aiszero(op) || *this == 0) {
  453. sign = false;
  454. memset(buffer, 0, BUFLEN);
  455. }
  456. else {
  457. *this = karatsuba(*this, op);
  458. sign = (sign ^ op.sign);
  459. }
  460. }
  461. void Anumber::operator *= (int num) {
  462. if(num == 0 || *this == 0) {
  463. sign = false;
  464. memset(buffer, 0, BUFLEN);
  465. return;
  466. }
  467. float shift = log10(num);
  468. if(num % 10 == 0) {
  469. if(shift == 0) return;
  470. int i;
  471. for(i = shift; i!=BUFLEN; i++) {
  472. buffer[i - (int)shift] = buffer[i];
  473. if(i >= BUFLEN - shift) buffer[i] = 0;
  474. }
  475. }
  476. else {
  477. int i;
  478. Anumber result(0);
  479. for(i=0; i!=num; i++)
  480. result += *this;
  481. *this = result;
  482. }
  483. }
  484. Anumber Anumber::operator * (const Anumber& op) {
  485. Anumber result(*this);
  486. result *= op;
  487. return result;
  488. }
  489. Anumber Anumber::operator * (int num) {
  490. Anumber result(*this);
  491. result *= num;
  492. return result;
  493. }
  494. Anumber Anumber::operator / (const Anumber& op) {
  495. Anumber result(*this);
  496. result /= op;
  497. return result;
  498. }
  499. Anumber Anumber::operator / (char op) {
  500. Anumber result(*this);
  501. result /= op;
  502. return result;
  503. }
  504. bool smaller(const Anumber& num1, const Anumber& num2, int k, int m) {
  505. int i = BUFLEN - m;
  506. while(i != BUFLEN) {
  507. if(num1.buffer[i - k - 1] != num2.buffer[i - 1])
  508. return (num1.buffer[i - k - 1] < num2.buffer[i - 1]);
  509. else i++;
  510. }
  511. return (num1.buffer[i - k - 1] < num2.buffer[i - 1]);
  512. }
  513. void Anumber::operator /= (const Anumber& op) {
  514. Anumber result(0);
  515. int dividend_len = len();
  516. int divisor_len = Alen(op);
  517. if(dividend_len < divisor_len) *this = result;
  518. char factor = 10 / (op.buffer[BUFLEN - divisor_len] + 1);
  519. Anumber reminder(*this * factor);
  520. Anumber optemp(op);
  521. Anumber divisor(optemp * factor);
  522. divisor_len = divisor.len();
  523. Anumber part_product;
  524. Anumber quotient(0);
  525. int k;
  526. char quotient_digit;
  527. for(k = 0; k <= dividend_len - divisor_len; k++) {
  528. int rem3 = reminder.buffer[k + (BUFLEN - dividend_len) - 1] * 100 + reminder.buffer[k + (BUFLEN - dividend_len) + 1 - 1] * 10 + reminder.buffer[k + (BUFLEN - dividend_len) + 2 - 1];
  529. int div2 = divisor.buffer[(BUFLEN - divisor_len)] * 10 + divisor.buffer[(BUFLEN - divisor_len) + 1];
  530. quotient_digit = ((rem3 / div2) < 9) ? (rem3 / div2) : 9;
  531. part_product = divisor * quotient_digit;
  532. if(smaller(reminder, part_product, (dividend_len - divisor_len) - k, divisor_len)) {
  533. quotient_digit = quotient_digit - 1;
  534. part_product = divisor * quotient_digit;
  535. }
  536. quotient.buffer[k] = quotient_digit;
  537. int i, borrow = 0, diff;
  538. for(i=0; i!=divisor_len; i++) {
  539. diff = reminder.buffer[BUFLEN - i - (dividend_len - divisor_len - k) - 1] - part_product.buffer[BUFLEN - i - 1] - borrow + 10;
  540. reminder.buffer[BUFLEN - i - (dividend_len - divisor_len - k) - 1] = diff % 10;
  541. borrow = 1 - (diff / 10);
  542. }
  543. }
  544. int i;
  545. for(i=0; i!=k; i++) {
  546. quotient.buffer[BUFLEN - k + i] = quotient.buffer[i];
  547. quotient.buffer[i] = 0;
  548. }
  549. *this = quotient;
  550. }
  551. void Anumber::operator /= (char op) {
  552. Anumber returning(0);
  553. char carry = 0;
  554. int j=0, i, temp;
  555. for(i=BUFLEN-len(); i!=BUFLEN; i++) {
  556. temp = carry*10 + buffer[i];
  557. returning.buffer[j] = temp / op;
  558. carry = temp % op;
  559. j++;
  560. }
  561. for(i=BUFLEN-1; i>=0; i--) {
  562. returning.buffer[i] = returning.buffer[i - (BUFLEN - j)];
  563. if(i < BUFLEN - j)
  564. returning.buffer[i] = 0;
  565. }
  566. *this = returning;
  567. }
  568. Anumber Anumber::operator % (const Anumber& op) {
  569. Anumber result(0);
  570. Anumber optemp(op);
  571. if(optemp.is10pow()) {
  572. int i;
  573. int lung = BUFLEN - optemp.Alog10();
  574. for(i = BUFLEN - 1; i>=lung; i--)
  575. result.buffer[i] = buffer[i];
  576. return result;
  577. }
  578. int oplen = Alen(op);
  579. if(len() < oplen) {
  580. result = *this;
  581. return result;
  582. }
  583. Anumber b(10);
  584. Anumber k(oplen);
  585. Anumber u(b.pow(k*2) / op);
  586. Anumber q1(*this / (b.pow(k-1)));
  587. Anumber q2(q1 * u);
  588. Anumber q3(q2 / (b.pow(++k)));
  589. Anumber r1(*this % b.pow(k));
  590. Anumber r2((q3 * op) % b.pow(k));
  591. Anumber r(r1 - r2);
  592. if(r.sign) r = b.pow(k) - (r2 - r1);
  593. while((r > op) || (r == op)) r -= op;
  594. return r;
  595. }
  596. char Anumber::operator % (char op) {
  597. char carry = 0;
  598. int j=0, i, temp;
  599. for(i=BUFLEN-len(); i!=BUFLEN; i++) {
  600. temp = carry*10 + buffer[i];
  601. carry = temp % op;
  602. j++;
  603. }
  604. return carry;
  605. }
  606. Anumber karatsuba(const Anumber& op1, const Anumber& op2) {
  607. if(Aiszero(op1) || Aiszero(op2)) {
  608. Anumber zero(0);
  609. return zero;
  610. }
  611. int len1 = Alen(op1);
  612. int len2 = Alen(op2);
  613. if(len1 < 3 || len2 < 3)
  614. return schoolbook(op1, op2);
  615. int lung = 2;
  616. do {
  617. lung *= 2;
  618. } while(lung < len1 || lung < len2);
  619. Anumber a;
  620. Anumber b;
  621. Anumber c;
  622. Anumber half11(0), half12(0);
  623. Anumber half21(0), half22(0);
  624. Anumber op1temp(op1);
  625. Anumber op2temp(op2);
  626. op1temp.split(&half11, &half12, lung);
  627. op2temp.split(&half21, &half22, lung);
  628. a = half11 * half21;
  629. b = half12 * half22;
  630. c = (((half11 + half12) * (half21 + half22)) - a) - b;
  631. Anumber returning;
  632. a.exp10(lung);
  633. c.exp10(lung / 2);
  634. returning = a + c + b;
  635. return returning;
  636. }
  637. Anumber schoolbook(Anumber op1, Anumber op2) {
  638. Anumber result(0);
  639. int len1 = op1.len();
  640. int len2 = op2.len();
  641. int lung = (len1 > len2) ? len1 : len2;
  642. int i, j;
  643. char temp;
  644. op1.invert();
  645. op2.invert();
  646. for(i=0; i!=lung; i++)
  647. for(j=0; j!=lung; j++) {
  648. temp = op1.buffer[i] * op2.buffer[j];
  649. if(temp > 10) {
  650. result.buffer[i+j] += temp % 10;
  651. result.buffer[i+j+1] += temp / 10;
  652. }
  653. else
  654. result.buffer[i+j] += temp;
  655. }
  656. for(i=0; i!=BUFLEN; i++)
  657. if(result.buffer[i] > 9) {
  658. result.buffer[i+1] += result.buffer[i] / 10;
  659. result.buffer[i] = result.buffer[i] % 10;
  660. }
  661. result.invert();
  662. return result;
  663. }
  664. void Anumber::invert() {
  665. int i;
  666. char temp;
  667. int med = BUFLEN/2;
  668. for(i=0; i!=med; i++) {
  669. temp = buffer[i];
  670. buffer[i] = buffer[BUFLEN - 1 - i];
  671. buffer[BUFLEN - 1 - i] = temp;
  672. }
  673. }
  674. Anumber Aabs(Anumber op) {
  675. op.sign = false;
  676. return op;
  677. }
  678. Anumber MCD(Anumber a, Anumber b) {
  679. if(b == 0) return a;
  680. else return MCD(b, a % b);
  681. }
  682. Anumber newPrime(int len) {
  683. Anumber p(0);
  684. bool found = false;
  685. int tentativi = 0;;
  686. srand(time(NULL));
  687. int i;
  688. while(!found) {
  689. printf("generating random number\n");
  690. i=BUFLEN - 1;
  691. p.buffer[i] = ((rand()%5) * 2) + 1;
  692. i--;
  693. for(; i>BUFLEN - len; i--)
  694. p.buffer[i] = rand()%10;
  695. p.buffer[i] = (rand()%9) + 1;
  696. printf("number generated = "); p.show();
  697. printf("doing modular exponentation\n");
  698. Anumber a(2);
  699. Anumber resto(a.modExp(p - 1, p));
  700. printf("done, resto = "); resto.show();
  701. if(resto == 1) found = true;
  702. tentativi++;
  703. printf("%d\n", tentativi);
  704. }
  705. printf("tentativi = %d\n", tentativi);
  706. return p;
  707. }
  708. bool coprime(Anumber &a, Anumber &b) {
  709. if(MCD(a, b) == 1) return true;
  710. return false;
  711. }
  712. int Alen(const Anumber& input) {
  713. int i=0;
  714. bool found = false;
  715. while(!found && i != BUFLEN) {
  716. if(input.buffer[i] != 0) found = true;
  717. else i++;
  718. }
  719. if(BUFLEN - i > 400) printf("%d\n", BUFLEN - i);
  720. return BUFLEN - i;
  721. }
  722. bool Aiszero(const Anumber& input) {
  723. return !(Alen(input));
  724. }