freeswitch/libs/libzrtp/third_party/bnlib/test/rsatest.c

266 lines
6.2 KiB
C

/*
* Copyright (c) 1994, 1995 Colin Plumb. All rights reserved.
* For licensing and other legal details, see the file legal.c.
*
* rsatest.c - Test driver for RSA key generation.
*/
#include "first.h"
#include <stdio.h>
#include <stdlib.h> /* For strtoul() */
#include <string.h> /* For strerror */
#include "bnprint.h"
#include "cputime.h"
#include "keygen.h"
#include "keys.h"
#include "random.h"
#include "rsaglue.h"
#include "userio.h"
#include "kludge.h"
#define bnPut(prompt, bn) bnPrint(stdout, prompt, bn, "\n")
static int
rsaTest(struct PubKey const *pub, struct SecKey const *sec)
{
struct BigNum bn;
char const buf1[25] = "abcdefghijklmnopqrstuvwxy";
char buf2[64];
int i, j;
#if CLOCK_AVAIL
timetype start, stop;
unsigned long cursec, encsec = 0, decsec = 0, sigsec = 0, versec = 0;
unsigned curms, encms = 0, decms = 0, sigms = 0, verms = 0;
#endif
if (rsaKeyTooBig(pub, sec)) {
printf("Key too large for RSA library - not testing.\n");
return 0;
}
puts("\tEncrypt\t\tDecrypt\t\tSign\t\tVerify\tStatus");
bnBegin(&bn);
for (j = 0; j < (int)sizeof(buf1); j++) {
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPublicEncrypt(&bn, (byte const *)buf1, (size_t)j+1, pub);
if (i < 0) {
printf("RSA encryption failed, i = %dn", i);
return i;
}
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
encsec += cursec = sec(stop);
encms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPrivateDecrypt((byte *)buf2, sizeof(buf2), &bn,
pub, sec);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
decsec += cursec = sec(stop);
decms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
if (i != j+1 || memcmp(buf1, buf2, (size_t)j+1) != 0) {
printf("RSA Decryption failed, i = %d\n", i);
return i;
}
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPrivateEncrypt(&bn, (byte const *)buf1, (size_t)j+1,
pub, sec);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
sigsec += cursec = sec(stop);
sigms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
if (i < 0) {
printf("RSA signing failed, i = %d\n", i);
return i;
}
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPublicDecrypt((byte *)buf2, sizeof(buf2), &bn, pub);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
versec += cursec = sec(stop);
verms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
if (i != j+1 || memcmp(buf1, buf2, (size_t)j+1) != 0) {
printf("RSA verify failed i = %d != %d\n", i, j+1);
return i;
}
printf("Succeeded\n");
fflush(stdout);
}
#if CLOCK_AVAIL
encms += 1000 * (encsec % j);
encsec /= j;
encms /= j;
encsec += encms / 1000;
encms %= 1000;
decms += 1000 * (decsec % j);
decsec /= j;
decms /= j;
decsec += decms / 1000;
decms %= 1000;
sigms += 1000 * (sigsec % j);
sigsec /= j;
sigms /= j;
sigsec += sigms / 1000;
sigms %= 1000;
verms += 1000 * (versec % j);
versec /= j;
verms /= j;
versec += verms / 1000;
verms %= 1000;
printf("\t%lu.%03u\t\t%lu.%03u\t\t%lu.%03u\t\t%lu.%03u\tAVERAGE %u\n",
encsec, encms, decsec, decms,
sigsec, sigms, versec, verms, bnBits(&pub->n));
#endif
return 0;
}
static int
rsaGen(unsigned keybits)
{
struct PubKey pub;
struct SecKey sec;
int i;
#if CLOCK_AVAIL
timetype start, stop;
unsigned long s;
#endif
if (keybits < 384)
keybits = 384;
userPrintf("Generating an RSA key with a %u-bit modulus.\n", keybits);
randAccum(1);
/* randAccum(keybits); */
/*
* One dot is printed per pseudoprimality test that fails.
* the density of primes of length "keybits/2" is about
* ln(2^(keybits/2)), or keybits/2*ln(2), so if we were to
* naively test numbers at random, we'd expect to print
* keybits/2*ln(2) dots per number, or keybits*ln(2) for
* both. This is keybits/1.44.
* However, the sieve removes all multiples of 2, 3, 5, 7, 11, 13,
* etc (up to 65521, the largest prime < 65536) from the candidates.
* (1-1/2)*(1-1/3)*(1-1/5)*(1-1/7)*(1-1/11)*...*(1-1/65521) is
* about 0.05061325. So we only actually print keybits*ln(2)*0.0506
* from the numbers we test, 0.035 of them, or about 1/28.5.
* We round this up to 0.04, or 1/25, because it produces nice
* round numbers and people don't get as impatient if we're a
* little pessimistic. (The Poisson distribution has a long
* tail.) If you really want to know, it's a 14% overestimate.
*/
userPrintf("\n\
Key generation takes a little while. This program prints dots as it\n\
searches for each of the two primes it needs for a key. How long it will\n\
have to search is unpredictable, but expect an average of %u dots total.\n",
keybits/25);
pubKeyBegin(&pub);
secKeyBegin(&sec);
#if CLOCK_AVAIL
gettime(&start);
#endif
i = genRsaKey(&pub, &sec, keybits, 17, stdout);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
s = sec(stop);
printf("%u-bit time = %lu.%03u sec.", keybits, s, msec(stop));
if (s > 60) {
putchar(' ');
putchar('(');
if (s > 3600)
printf("%u:%02u", (unsigned)(s/3600),
(unsigned)(s/60%60));
else
printf("%u", (unsigned)(s/60));
printf(":%02u)", (unsigned)(s%60));
}
putchar('\n');
#endif
if (i < 0) {
userPuts("\a\nKeygen failed!\n");
} else {
userPrintf("%d modular exponentiations performed.\n", i);
bnPut("n = ", &pub.n);
bnPut("e = ", &pub.e);
bnPut("d = ", &sec.d);
bnPut("p = ", &sec.p);
bnPut("q = ", &sec.q);
bnPut("u = ", &sec.u);
i = rsaTest(&pub, &sec);
}
pubKeyEnd(&pub);
secKeyEnd(&sec);
return i;
}
int
main(int argc, char **argv)
{
unsigned long t;
char *p;
if (argc < 2) {
fprintf(stderr, "Usage: %s <bits>...\n", argv[0]);
fputs("\
This generates a random RSA key pair and prints its value. <bits>\n\
is the size of the modulus to use.\n", stderr);
return 1;
}
bnInit();
while (--argc) {
t = strtoul(*++argv, &p, 0);
if (t < 384 || t > 65536 || *p) {
fprintf(stderr, "Illegal modulus size: \"%s\"\n",
*argv);
return 1;
}
rsaGen((unsigned)t);
}
return 0;
}