primetest.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (c) 1994, 1995 Colin Plumb. All rights reserved.
  3. * For licensing and other legal details, see the file legal.c.
  4. *
  5. * primetest.c - Test driver for prime generation.
  6. */
  7. #include "first.h"
  8. #include <stdio.h>
  9. #include <stdlib.h> /* For strtoul() */
  10. #include "bn.h"
  11. #include "bnprint.h"
  12. #include "cputime.h"
  13. #include "prime.h"
  14. #include "random.h" /* Good random number generator */
  15. #include "noise.h"
  16. #include "kludge.h"
  17. #define bnPut(prompt, bn) bnPrint(stdout, prompt, bn, "\n")
  18. /*
  19. * Generate a random bignum of a specified length, with the given
  20. * high and low 8 bits. "High" is merged into the high 8 bits of the
  21. * number. For example, set it to 0x80 to ensure that the number is
  22. * exactly "bits" bits long (i.e. 2^(bits-1) <= bn < 2^bits).
  23. * "Low" is merged into the low 8 bits. For example, set it to
  24. * 1 to ensure that you generate an odd number.
  25. */
  26. static int
  27. genRandBn(struct BigNum *bn, unsigned bits, byte high, byte low)
  28. {
  29. unsigned char buf[64];
  30. unsigned bytes;
  31. unsigned l;
  32. int err;
  33. bnSetQ(bn, 0);
  34. bytes = (bits+7) / 8;
  35. l = bytes < sizeof(buf) ? bytes : sizeof(buf);
  36. randBytes(buf, l);
  37. /* Mask off excess high bits */
  38. buf[0] &= 255 >> (-bits & 7);
  39. /* Merge in specified high bits */
  40. buf[0] |= high >> (-bits & 7);
  41. if (bits & 7)
  42. buf[1] |= high << (bits & 7);
  43. for (;;) {
  44. bytes -= l;
  45. if (!bytes) /* Last word - merge in low bits */
  46. buf[l-1] |= low;
  47. err = bnInsertBigBytes(bn, buf, bytes, l);
  48. if (!bytes || err < 0)
  49. break;
  50. l = bytes < sizeof(buf) ? bytes : sizeof(buf);
  51. randBytes(buf, l);
  52. }
  53. memset(buf, 0, sizeof(buf));
  54. return err;
  55. }
  56. /*
  57. * Generate a new RSA key, with the specified number of bits and
  58. * public exponent. The high two bits of each prime are always
  59. * set to make the number more difficult to factor by forcing the
  60. * number into the high end of the range.
  61. */
  62. struct Progress {
  63. FILE *f;
  64. unsigned column;
  65. unsigned wrap;
  66. };
  67. static int
  68. primeProgress(void *arg, int c)
  69. {
  70. struct Progress *p = arg;
  71. if (++p->column > p->wrap) {
  72. putc('\n', p->f);
  73. p->column = 1;
  74. }
  75. putc(c, p->f);
  76. fflush(p->f);
  77. return 0;
  78. }
  79. static int
  80. primeTest(unsigned bits)
  81. {
  82. int modexps = 0;
  83. struct BigNum bn; /* Temporary */
  84. int i, j;
  85. struct Progress progress;
  86. #if CLOCK_AVAIL
  87. timetype start, stop;
  88. unsigned long curs, tots = 0;
  89. unsigned curms, totms = 0;
  90. #endif
  91. progress.f = stdout;
  92. progress.wrap = 78;
  93. bnBegin(&bn);
  94. /* Find p - choose a starting place */
  95. i = genRandBn(&bn, bits, 0x80, 1);
  96. if (i < 0)
  97. goto error;
  98. /* And search for primes */
  99. for (j = 0; j < 40; j++) {
  100. progress.column = 0;
  101. #if CLOCK_AVAIL
  102. gettime(&start);
  103. #endif
  104. i = primeGen(&bn, 0, primeProgress, &progress, 0);
  105. if (i < 0)
  106. goto error;
  107. #if CLOCK_AVAIL
  108. gettime(&stop);
  109. subtime(stop, start);
  110. tots += curs = sec(stop);
  111. totms += curms = msec(stop);
  112. #endif
  113. modexps += i;
  114. putchar('\n'); /* Signal done */
  115. printf("%d modular exponentiations performed", i);
  116. #if CLOCK_AVAIL
  117. printf(" in %lu.%03u s", curs, curms);
  118. #endif
  119. putchar('\n');
  120. bnPut("n = ", &bn);
  121. if (bnAddQ(&bn, 2) < 0)
  122. goto error;
  123. }
  124. bnEnd(&bn);
  125. printf("Total %d modular exponentiations performed", modexps);
  126. #if CLOCK_AVAIL
  127. tots += totms/1000;
  128. totms %= 1000;
  129. printf(" in %lu.%03u s\n", tots, totms);
  130. totms += 1000 * (tots % j);
  131. tots /= j;
  132. totms /= j;
  133. tots += totms / 1000;
  134. totms %= 1000;
  135. printf("Average time: %lu.%03u s", tots, totms);
  136. #endif
  137. putchar('\n');
  138. /* And that's it... success! */
  139. return 0;
  140. error:
  141. puts("\nError!");
  142. bnEnd(&bn);
  143. return -1;
  144. }
  145. int
  146. main(int argc, char **argv)
  147. {
  148. unsigned long t;
  149. char *p;
  150. if (argc < 2) {
  151. fprintf(stderr, "Usage: %s <bits>...\n", argv[0]);
  152. fputs("\
  153. This generates a random RSA key pair and prints its value. <bits>\n\
  154. is the size of the modulus to use.\n", stderr);
  155. return 1;
  156. }
  157. noise();
  158. bnInit();
  159. while (--argc) {
  160. t = strtoul(*++argv, &p, 0);
  161. if (t < 17 || t > 65536 || *p) {
  162. fprintf(stderr, "Illegal prime size: \"%s\"\n",
  163. *argv);
  164. return 1;
  165. }
  166. primeTest((unsigned)t);
  167. }
  168. return 0;
  169. }