rsatest.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  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. * rsatest.c - Test driver for RSA key generation.
  6. */
  7. #include "first.h"
  8. #include <stdio.h>
  9. #include <stdlib.h> /* For strtoul() */
  10. #include <string.h> /* For strerror */
  11. #include "bnprint.h"
  12. #include "cputime.h"
  13. #include "keygen.h"
  14. #include "keys.h"
  15. #include "random.h"
  16. #include "rsaglue.h"
  17. #include "userio.h"
  18. #include "kludge.h"
  19. #define bnPut(prompt, bn) bnPrint(stdout, prompt, bn, "\n")
  20. static int
  21. rsaTest(struct PubKey const *pub, struct SecKey const *sec)
  22. {
  23. struct BigNum bn;
  24. char const buf1[25] = "abcdefghijklmnopqrstuvwxy";
  25. char buf2[64];
  26. int i, j;
  27. #if CLOCK_AVAIL
  28. timetype start, stop;
  29. unsigned long cursec, encsec = 0, decsec = 0, sigsec = 0, versec = 0;
  30. unsigned curms, encms = 0, decms = 0, sigms = 0, verms = 0;
  31. #endif
  32. if (rsaKeyTooBig(pub, sec)) {
  33. printf("Key too large for RSA library - not testing.\n");
  34. return 0;
  35. }
  36. puts("\tEncrypt\t\tDecrypt\t\tSign\t\tVerify\tStatus");
  37. bnBegin(&bn);
  38. for (j = 0; j < (int)sizeof(buf1); j++) {
  39. #if CLOCK_AVAIL
  40. gettime(&start);
  41. #endif
  42. i = rsaPublicEncrypt(&bn, (byte const *)buf1, (size_t)j+1, pub);
  43. if (i < 0) {
  44. printf("RSA encryption failed, i = %dn", i);
  45. return i;
  46. }
  47. #if CLOCK_AVAIL
  48. gettime(&stop);
  49. subtime(stop, start);
  50. encsec += cursec = sec(stop);
  51. encms += curms = msec(stop);
  52. printf("\t%lu.%03u\t", cursec, curms);
  53. #else
  54. printf("\t*\t");
  55. #endif
  56. fflush(stdout);
  57. #if CLOCK_AVAIL
  58. gettime(&start);
  59. #endif
  60. i = rsaPrivateDecrypt((byte *)buf2, sizeof(buf2), &bn,
  61. pub, sec);
  62. #if CLOCK_AVAIL
  63. gettime(&stop);
  64. subtime(stop, start);
  65. decsec += cursec = sec(stop);
  66. decms += curms = msec(stop);
  67. printf("\t%lu.%03u\t", cursec, curms);
  68. #else
  69. printf("\t*\t");
  70. #endif
  71. fflush(stdout);
  72. if (i != j+1 || memcmp(buf1, buf2, (size_t)j+1) != 0) {
  73. printf("RSA Decryption failed, i = %d\n", i);
  74. return i;
  75. }
  76. #if CLOCK_AVAIL
  77. gettime(&start);
  78. #endif
  79. i = rsaPrivateEncrypt(&bn, (byte const *)buf1, (size_t)j+1,
  80. pub, sec);
  81. #if CLOCK_AVAIL
  82. gettime(&stop);
  83. subtime(stop, start);
  84. sigsec += cursec = sec(stop);
  85. sigms += curms = msec(stop);
  86. printf("\t%lu.%03u\t", cursec, curms);
  87. #else
  88. printf("\t*\t");
  89. #endif
  90. fflush(stdout);
  91. if (i < 0) {
  92. printf("RSA signing failed, i = %d\n", i);
  93. return i;
  94. }
  95. #if CLOCK_AVAIL
  96. gettime(&start);
  97. #endif
  98. i = rsaPublicDecrypt((byte *)buf2, sizeof(buf2), &bn, pub);
  99. #if CLOCK_AVAIL
  100. gettime(&stop);
  101. subtime(stop, start);
  102. versec += cursec = sec(stop);
  103. verms += curms = msec(stop);
  104. printf("\t%lu.%03u\t", cursec, curms);
  105. #else
  106. printf("\t*\t");
  107. #endif
  108. fflush(stdout);
  109. if (i != j+1 || memcmp(buf1, buf2, (size_t)j+1) != 0) {
  110. printf("RSA verify failed i = %d != %d\n", i, j+1);
  111. return i;
  112. }
  113. printf("Succeeded\n");
  114. fflush(stdout);
  115. }
  116. #if CLOCK_AVAIL
  117. encms += 1000 * (encsec % j);
  118. encsec /= j;
  119. encms /= j;
  120. encsec += encms / 1000;
  121. encms %= 1000;
  122. decms += 1000 * (decsec % j);
  123. decsec /= j;
  124. decms /= j;
  125. decsec += decms / 1000;
  126. decms %= 1000;
  127. sigms += 1000 * (sigsec % j);
  128. sigsec /= j;
  129. sigms /= j;
  130. sigsec += sigms / 1000;
  131. sigms %= 1000;
  132. verms += 1000 * (versec % j);
  133. versec /= j;
  134. verms /= j;
  135. versec += verms / 1000;
  136. verms %= 1000;
  137. printf("\t%lu.%03u\t\t%lu.%03u\t\t%lu.%03u\t\t%lu.%03u\tAVERAGE %u\n",
  138. encsec, encms, decsec, decms,
  139. sigsec, sigms, versec, verms, bnBits(&pub->n));
  140. #endif
  141. return 0;
  142. }
  143. static int
  144. rsaGen(unsigned keybits)
  145. {
  146. struct PubKey pub;
  147. struct SecKey sec;
  148. int i;
  149. #if CLOCK_AVAIL
  150. timetype start, stop;
  151. unsigned long s;
  152. #endif
  153. if (keybits < 384)
  154. keybits = 384;
  155. userPrintf("Generating an RSA key with a %u-bit modulus.\n", keybits);
  156. randAccum(1);
  157. /* randAccum(keybits); */
  158. /*
  159. * One dot is printed per pseudoprimality test that fails.
  160. * the density of primes of length "keybits/2" is about
  161. * ln(2^(keybits/2)), or keybits/2*ln(2), so if we were to
  162. * naively test numbers at random, we'd expect to print
  163. * keybits/2*ln(2) dots per number, or keybits*ln(2) for
  164. * both. This is keybits/1.44.
  165. * However, the sieve removes all multiples of 2, 3, 5, 7, 11, 13,
  166. * etc (up to 65521, the largest prime < 65536) from the candidates.
  167. * (1-1/2)*(1-1/3)*(1-1/5)*(1-1/7)*(1-1/11)*...*(1-1/65521) is
  168. * about 0.05061325. So we only actually print keybits*ln(2)*0.0506
  169. * from the numbers we test, 0.035 of them, or about 1/28.5.
  170. * We round this up to 0.04, or 1/25, because it produces nice
  171. * round numbers and people don't get as impatient if we're a
  172. * little pessimistic. (The Poisson distribution has a long
  173. * tail.) If you really want to know, it's a 14% overestimate.
  174. */
  175. userPrintf("\n\
  176. Key generation takes a little while. This program prints dots as it\n\
  177. searches for each of the two primes it needs for a key. How long it will\n\
  178. have to search is unpredictable, but expect an average of %u dots total.\n",
  179. keybits/25);
  180. pubKeyBegin(&pub);
  181. secKeyBegin(&sec);
  182. #if CLOCK_AVAIL
  183. gettime(&start);
  184. #endif
  185. i = genRsaKey(&pub, &sec, keybits, 17, stdout);
  186. #if CLOCK_AVAIL
  187. gettime(&stop);
  188. subtime(stop, start);
  189. s = sec(stop);
  190. printf("%u-bit time = %lu.%03u sec.", keybits, s, msec(stop));
  191. if (s > 60) {
  192. putchar(' ');
  193. putchar('(');
  194. if (s > 3600)
  195. printf("%u:%02u", (unsigned)(s/3600),
  196. (unsigned)(s/60%60));
  197. else
  198. printf("%u", (unsigned)(s/60));
  199. printf(":%02u)", (unsigned)(s%60));
  200. }
  201. putchar('\n');
  202. #endif
  203. if (i < 0) {
  204. userPuts("\a\nKeygen failed!\n");
  205. } else {
  206. userPrintf("%d modular exponentiations performed.\n", i);
  207. bnPut("n = ", &pub.n);
  208. bnPut("e = ", &pub.e);
  209. bnPut("d = ", &sec.d);
  210. bnPut("p = ", &sec.p);
  211. bnPut("q = ", &sec.q);
  212. bnPut("u = ", &sec.u);
  213. i = rsaTest(&pub, &sec);
  214. }
  215. pubKeyEnd(&pub);
  216. secKeyEnd(&sec);
  217. return i;
  218. }
  219. int
  220. main(int argc, char **argv)
  221. {
  222. unsigned long t;
  223. char *p;
  224. if (argc < 2) {
  225. fprintf(stderr, "Usage: %s <bits>...\n", argv[0]);
  226. fputs("\
  227. This generates a random RSA key pair and prints its value. <bits>\n\
  228. is the size of the modulus to use.\n", stderr);
  229. return 1;
  230. }
  231. bnInit();
  232. while (--argc) {
  233. t = strtoul(*++argv, &p, 0);
  234. if (t < 384 || t > 65536 || *p) {
  235. fprintf(stderr, "Illegal modulus size: \"%s\"\n",
  236. *argv);
  237. return 1;
  238. }
  239. rsaGen((unsigned)t);
  240. }
  241. return 0;
  242. }