mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-02-05 10:34:54 +00:00
d2edcad66e
Thanks to Phil Zimmermann for the code and for the license exception we needed to include it. There remains some build system integration work to be done before this code will build properly in the FreeSWITCH tree.
673 lines
16 KiB
C
673 lines
16 KiB
C
/*
|
|
* Copyright (c) 1995 Colin Plumb. All rights reserved.
|
|
* For licensing and other legal details, see the file legal.c.
|
|
*
|
|
* dsatest.c - DSA key generator and test driver.
|
|
*
|
|
* This generates DSA primes using a (hopefully) clearly
|
|
* defined algorithm, based on David Kravitz's "kosherizer".
|
|
* It is not, however, identical.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "bn.h"
|
|
#include "prime.h"
|
|
|
|
#include "cputime.h"
|
|
#include "sha.h"
|
|
|
|
#define BNDEBUG 1
|
|
|
|
#if BNDEBUG
|
|
#include "bnprint.h"
|
|
#define bndPut(prompt, bn) bnPrint(stdout, prompt, bn, "\n")
|
|
#define bndPrintf printf
|
|
#else
|
|
#define bndPut(prompt, bn) ((void)(prompt),(void)(bn))
|
|
#define bndPrintf (void)
|
|
#endif
|
|
|
|
/*
|
|
* Generate a bignum of a specified length, with the given
|
|
* high and low 8 bits. "High" is merged into the high 8 bits of the
|
|
* number. For example, set it to 0x80 to ensure that the number is
|
|
* exactly "bits" bits long (i.e. 2^(bits-1) <= bn < 2^bits).
|
|
* "Low" is merged into the low 8 bits. For example, set it to
|
|
* 1 to ensure that you generate an odd number.
|
|
*
|
|
* Then XOR the result into the input bignum. This is to
|
|
* accomodate the kosherizer in all its generality.
|
|
*
|
|
* The bignum is generated using the given seed string. The
|
|
* technique is from David Kravitz (of the NSA)'s "kosherizer".
|
|
* The string is hashed, and that (with the low bit forced to 1)
|
|
* is used for the low 160 bits of the number. Then the string,
|
|
* considered as a big-endian array of bytes, is incremented
|
|
* and the incremented value is hashed to produce the next most
|
|
* significant 160 bits, and so on. The increment is performed
|
|
* modulo the size of the seed string.
|
|
*
|
|
* The seed is returned incremented so that it may be used to generate
|
|
* subsequent numbers.
|
|
*
|
|
* The most and least significant 8 bits of the returned number are forced
|
|
* to the values passed in "high" and "low", respectively. Typically,
|
|
* high would be set to 0x80 to force the most significant bit to 1.
|
|
*/
|
|
static int
|
|
genRandBn(struct BigNum *bn, unsigned bits, unsigned char high,
|
|
unsigned char low, unsigned char *seed, unsigned len)
|
|
{
|
|
unsigned char buf1[SHA_DIGESTSIZE];
|
|
unsigned char buf2[SHA_DIGESTSIZE];
|
|
unsigned bytes = (bits+7)/8;
|
|
unsigned l = 0; /* Current position */
|
|
unsigned i;
|
|
struct SHAContext sha;
|
|
|
|
if (!bits)
|
|
return 0;
|
|
|
|
/* Generate the first bunch of hashed data */
|
|
shaInit(&sha);
|
|
shaUpdate(&sha, seed, len);
|
|
shaFinal(&sha, buf1);
|
|
/* Increment the seed, ignoring carry out. */
|
|
i = len;
|
|
while (i-- && (++seed[i] & 255) == 0)
|
|
;
|
|
/* XOR in the existing bytes */
|
|
bnExtractBigBytes(bn, buf2, l, SHA_DIGESTSIZE);
|
|
for (i = 0; i < SHA_DIGESTSIZE; i++)
|
|
buf1[i] ^= buf2[i];
|
|
buf1[SHA_DIGESTSIZE-1] |= low;
|
|
|
|
while (bytes > SHA_DIGESTSIZE) {
|
|
bytes -= SHA_DIGESTSIZE;
|
|
/* Merge in low half of high bits, if necessary */
|
|
if (bytes == 1 && (bits & 7))
|
|
buf1[0] |= high << (bits & 7);
|
|
if (bnInsertBigBytes(bn, buf1, l, SHA_DIGESTSIZE) < 0)
|
|
return -1;
|
|
l += SHA_DIGESTSIZE;
|
|
|
|
/* Compute the next hash we need */
|
|
shaInit(&sha);
|
|
shaUpdate(&sha, seed, len);
|
|
shaFinal(&sha, buf1);
|
|
/* Increment the seed, ignoring carry out. */
|
|
i = len;
|
|
while (i-- && (++seed[i] & 255) == 0)
|
|
;
|
|
/* XOR in the existing bytes */
|
|
bnExtractBigBytes(bn, buf2, l, SHA_DIGESTSIZE);
|
|
for (i = 0; i < SHA_DIGESTSIZE; i++)
|
|
buf1[i] ^= buf2[i];
|
|
}
|
|
|
|
/* Do the final "bytes"-long section, using the tail bytes in buf1 */
|
|
/* Mask off excess high bits */
|
|
buf1[SHA_DIGESTSIZE-bytes] &= 255 >> (-bits & 7);
|
|
/* Merge in specified high bits */
|
|
buf1[SHA_DIGESTSIZE-bytes] |= high >> (-bits & 7);
|
|
if (bytes > 1 && (bits & 7))
|
|
buf1[SHA_DIGESTSIZE-bytes+1] |= high << (bits & 7);
|
|
/* Merge in the appropriate bytes of the buffer */
|
|
if (bnInsertBigBytes(bn, buf1+SHA_DIGESTSIZE-bytes, l, bytes) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct Progress {
|
|
FILE *f;
|
|
unsigned column;
|
|
unsigned wrap;
|
|
};
|
|
|
|
static int
|
|
genProgress(void *arg, int c)
|
|
{
|
|
struct Progress *p = arg;
|
|
if (++p->column > p->wrap) {
|
|
putc('\n', p->f);
|
|
p->column = 1;
|
|
}
|
|
putc(c, p->f);
|
|
fflush(p->f);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
dsaGen(struct BigNum *p, unsigned pbits, struct BigNum *q, unsigned qbits,
|
|
struct BigNum *g, struct BigNum *x, struct BigNum *y,
|
|
unsigned char *seed, unsigned len, FILE *f)
|
|
{
|
|
struct BigNum h, e;
|
|
int i;
|
|
#if CLOCK_AVAIL
|
|
timetype start, stop;
|
|
unsigned long s;
|
|
#endif
|
|
struct Progress progress;
|
|
|
|
if (f)
|
|
fprintf(f,
|
|
"Generating a DSA key pair with %u-bit p and %u-bit q,\n"
|
|
"seed = \"%.*s\"\n", pbits, qbits, (int)len, (char *)seed);
|
|
progress.f = f;
|
|
progress.column = 0;
|
|
progress.wrap = 78;
|
|
|
|
#if CLOCK_AVAIL
|
|
gettime(&start);
|
|
#endif
|
|
|
|
/*
|
|
* Choose a random starting place for q
|
|
* Starting place is SHA(seed) XOR SHA(seed+1),
|
|
* With the high *8* bits set to 1.
|
|
*/
|
|
(void)bnSetQ(q, 0);
|
|
if (genRandBn(q, qbits, 0xFF, 0, seed, len) < 0)
|
|
return -1;
|
|
bndPut("q1 = ", q);
|
|
if (genRandBn(q, qbits, 0xFF, 1, seed, len) < 0)
|
|
return -1;
|
|
bndPut("q2 = ", q);
|
|
/* And search for a prime */
|
|
i = primeGen(q, (unsigned (*)(unsigned))0, f ? genProgress : 0,
|
|
(void *)&progress, 0);
|
|
bndPut("q = ", q);
|
|
if (i < 0)
|
|
return -1;
|
|
|
|
/* ...and for p */
|
|
(void)bnSetQ(p, 0);
|
|
if (genRandBn(p, pbits, 0xC0, 1, seed, len) < 0)
|
|
return -1;
|
|
bndPut("p1 = ", p);
|
|
|
|
/* Temporarily double q */
|
|
if (bnLShift(q, 1) < 0)
|
|
return -1;
|
|
|
|
bnBegin(&h);
|
|
bnBegin(&e);
|
|
|
|
/* Set p = p - (p mod q) + 1, i.e. congruent to 1 mod 2*q */
|
|
if (bnMod(&e, p, q) < 0)
|
|
goto failed;
|
|
if (bnSub(p, &e) < 0 || bnAddQ(p, 1) < 0)
|
|
goto failed;
|
|
bndPut("p2 = ", p);
|
|
|
|
if (f)
|
|
genProgress(&progress, ' ');
|
|
|
|
/* And search for a prime */
|
|
i = primeGenStrong(p, q, f ? genProgress : 0, (void *)&progress);
|
|
if (i < 0)
|
|
return -1;
|
|
bndPut("p = ", p);
|
|
|
|
/* Reduce q again */
|
|
bnRShift(q, 1);
|
|
|
|
/* Now hunt for a suitable g - first, find (p-1)/q */
|
|
if (bnDivMod(&e, &h, p, q) < 0)
|
|
goto failed;
|
|
/* e is now the exponent (p-1)/q, and h is the remainder (one!) */
|
|
if (bnBits(&h) != 1) {
|
|
bndPut("Huh? p % q = ", &h);
|
|
goto failed;
|
|
}
|
|
|
|
if (f)
|
|
genProgress(&progress, ' ');
|
|
|
|
/* Search for a suitable h */
|
|
if (bnSetQ(&h, 2) < 0 || bnTwoExpMod(g, &e, p) < 0)
|
|
goto failed;
|
|
i++;
|
|
while (bnBits(g) < 2) {
|
|
if (f)
|
|
genProgress(&progress, '.');
|
|
if (bnAddQ(&h, 1) < 0 || bnExpMod(g, &h, &e, p) < 0)
|
|
goto failed;
|
|
i++;
|
|
}
|
|
if (f)
|
|
genProgress(&progress, '*');
|
|
#if CLOCK_AVAIL
|
|
gettime(&stop);
|
|
#endif
|
|
|
|
/*
|
|
* Now pick the secret, x. Choose it a bit larger than q and do
|
|
* modular reduction to make it uniformly distributed.
|
|
*/
|
|
bnSetQ(x, 0);
|
|
/* XXX SECURITY ALERT Replace with a real RNG! SECURITY ALERT XXX */
|
|
if (genRandBn(x, qbits+8, 0, 0, seed, len) < 0)
|
|
goto failed;
|
|
if (bnMod(x, x, q) < 0 || bnExpMod(y, g, x, p) < 0)
|
|
goto failed;
|
|
i++;
|
|
if (f)
|
|
putc('\n', f);
|
|
|
|
printf("%d modular exponentiations performed.\n", i);
|
|
|
|
#if CLOCK_AVAIL
|
|
subtime(stop, start);
|
|
s = sec(stop);
|
|
bndPrintf("%u/%u-bit time = %lu.%03u sec.", pbits, qbits,
|
|
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
|
|
|
|
bndPut("q = ", q);
|
|
bndPut("p = ", p);
|
|
bndPut("h = ", &h);
|
|
bndPut("g = ", g);
|
|
bndPut("x = ", x);
|
|
bndPut("y = ", y);
|
|
|
|
bnEnd(&h);
|
|
bnEnd(&e);
|
|
|
|
return 0;
|
|
|
|
failed:
|
|
bnEnd(&h);
|
|
bnEnd(&e);
|
|
return -1;
|
|
}
|
|
|
|
static int
|
|
dsaSign(struct BigNum const *p, struct BigNum const *q, struct BigNum const *g,
|
|
struct BigNum const *x, struct BigNum const *y,
|
|
struct BigNum const *hash, struct BigNum const *k,
|
|
struct BigNum *r, struct BigNum *s)
|
|
{
|
|
int retval = -1;
|
|
struct BigNum t;
|
|
|
|
(void)y;
|
|
|
|
bnBegin(&t);
|
|
/* Make the signature... first the precomputation */
|
|
|
|
/* Compute r = (g^k mod p) mod q */
|
|
if (bnExpMod(r, g, k, p) < 0 || bnMod(r, r, q) < 0)
|
|
goto failed;
|
|
|
|
/* Compute s = k^-1 * (hash + x*r) mod q */
|
|
if (bnInv(&t, k, q) < 0)
|
|
goto failed;
|
|
if (bnMul(s, x, r) < 0 || bnMod(s, s, q) < 0)
|
|
goto failed;
|
|
|
|
/* End of precomputation. Steps after this require the hash. */
|
|
|
|
if (bnAdd(s, hash) < 0)
|
|
goto failed;
|
|
if (bnCmp(s, q) > 0 && bnSub(s, q) < 0)
|
|
goto failed;
|
|
if (bnMul(s, s, &t) < 0 || bnMod(s, s, q) < 0)
|
|
goto failed;
|
|
/* Okay, r and s are the signature! */
|
|
|
|
retval = 0;
|
|
|
|
failed:
|
|
bnEnd(&t);
|
|
return retval;
|
|
}
|
|
|
|
/* Faster version, using precomputed tables */
|
|
static int
|
|
dsaSignFast(struct BigNum const *p, struct BigNum const *q,
|
|
struct BnBasePrecomp const *pre,
|
|
struct BigNum const *x, struct BigNum const *y,
|
|
struct BigNum const *hash, struct BigNum const *k,
|
|
struct BigNum *r, struct BigNum *s)
|
|
{
|
|
int retval = -1;
|
|
struct BigNum t;
|
|
|
|
(void)y;
|
|
|
|
bnBegin(&t);
|
|
/* Make the signature... first the precomputation */
|
|
|
|
/* Compute r = (g^k mod p) mod q */
|
|
if (bnBasePrecompExpMod(r, pre, k, p) < 0 || bnMod(r, r, q) < 0)
|
|
goto failed;
|
|
|
|
/* Compute s = k^-1 * (hash + x*r) mod q */
|
|
if (bnInv(&t, k, q) < 0)
|
|
goto failed;
|
|
if (bnMul(s, x, r) < 0 || bnMod(s, s, q) < 0)
|
|
goto failed;
|
|
|
|
/* End of precomputation. Steps after this require the hash. */
|
|
|
|
if (bnAdd(s, hash) < 0)
|
|
goto failed;
|
|
if (bnCmp(s, q) > 0 && bnSub(s, q) < 0)
|
|
goto failed;
|
|
if (bnMul(s, s, &t) < 0 || bnMod(s, s, q) < 0)
|
|
goto failed;
|
|
/* Okay, r and s are the signature! */
|
|
|
|
retval = 0;
|
|
|
|
failed:
|
|
bnEnd(&t);
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* Returns 1 for a good signature, 0 for bad, and -1 on error.
|
|
*/
|
|
static int
|
|
dsaVerify(struct BigNum const *p, struct BigNum const *q,
|
|
struct BigNum const *g, struct BigNum const *y,
|
|
struct BigNum const *r, struct BigNum const *s,
|
|
struct BigNum const *hash)
|
|
{
|
|
struct BigNum w, u1, u2;
|
|
int retval = -1;
|
|
|
|
bnBegin(&w);
|
|
bnBegin(&u1);
|
|
bnBegin(&u2);
|
|
|
|
if (bnInv(&w, s, q) < 0)
|
|
goto failed;
|
|
|
|
if (bnMul(&u1, hash, &w) < 0 || bnMod(&u1, &u1, q) < 0)
|
|
goto failed;
|
|
if (bnMul(&u2, r, &w) < 0 || bnMod(&u2, &u2, q) < 0)
|
|
goto failed;
|
|
|
|
/* Now for the expensive part... */
|
|
|
|
if (bnDoubleExpMod(&w, g, &u1, y, &u2, p) < 0)
|
|
goto failed;
|
|
if (bnMod(&w, &w, q) < 0)
|
|
goto failed;
|
|
retval = (bnCmp(r, &w) == 0);
|
|
failed:
|
|
bnEnd(&u2);
|
|
bnEnd(&u1);
|
|
bnEnd(&w);
|
|
return retval;
|
|
}
|
|
|
|
#define divide_by_n(sec, msec, n) \
|
|
( msec += 1000 * (sec % n), \
|
|
sec /= n, msec /= n, \
|
|
sec += msec / 1000, \
|
|
msec %= 1000 )
|
|
|
|
static int
|
|
dsaTest(struct BigNum const *p, struct BigNum const *q, struct BigNum const *g,
|
|
struct BigNum const *x, struct BigNum const *y)
|
|
{
|
|
struct BigNum hash, r, s, k;
|
|
struct BigNum r1, s1;
|
|
struct BnBasePrecomp pre;
|
|
unsigned bits;
|
|
unsigned i;
|
|
int verified;
|
|
int retval = -1;
|
|
unsigned char foo[4], bar[4];
|
|
#if CLOCK_AVAIL
|
|
timetype start, stop;
|
|
unsigned long cursec, sigsec = 0, sig1sec = 0, versec = 0;
|
|
unsigned curms, sigms = 0, sig1ms = 0, verms = 0;
|
|
unsigned j, n, m = 0;
|
|
#endif
|
|
|
|
bnBegin(&hash);
|
|
bnBegin(&r); bnBegin(&r1);
|
|
bnBegin(&s); bnBegin(&s1);
|
|
bnBegin(&k);
|
|
|
|
bits = bnBits(q);
|
|
strcpy((char *)foo, "foo");
|
|
strcpy((char *)bar, "bar");
|
|
|
|
/* Precompute powers of g */
|
|
if (bnBasePrecompBegin(&pre, g, p, bits) < 0)
|
|
goto failed;
|
|
|
|
bndPrintf(" N\tSigning \tSigning1\tVerifying\tStatus\n");
|
|
for (i = 0; i < 25; i++) {
|
|
/* Pick a random hash, the right length. */
|
|
(void)bnSetQ(&k, 0);
|
|
if (genRandBn(&hash, bits, 0, 0, foo, 4) < 0)
|
|
goto failed;
|
|
|
|
/* Make the signature... */
|
|
|
|
/*
|
|
* XXX SECURITY ALERT XXX
|
|
* XXX Replace with a real RNG! XXX
|
|
* XXX SECURITY ALERT XXX
|
|
*/
|
|
(void)bnSetQ(&k, 0);
|
|
if (genRandBn(&k, bnBits(q)+8, 0, 0, bar, 4) < 0)
|
|
goto failed;
|
|
/* Reduce k to the correct range */
|
|
if (bnMod(&k, &k, q) < 0)
|
|
goto failed;
|
|
#if CLOCK_AVAIL
|
|
/* Decide on a number of iterations to perform... */
|
|
m += n = i+1; /* This goes from 1 to 325 */
|
|
bndPrintf("%3d", n);
|
|
gettime(&start);
|
|
for (j = 0; j < n; j++)
|
|
#endif
|
|
if (dsaSign(p, q, g, x, y, &hash, &k, &r, &s) < 0)
|
|
goto failed;
|
|
#if CLOCK_AVAIL
|
|
gettime(&stop);
|
|
subtime(stop, start);
|
|
sigsec += cursec = sec(stop);
|
|
sigms += curms = msec(stop);
|
|
divide_by_n(cursec, curms, n);
|
|
bndPrintf("\t%lu.%03u\t\t", cursec, curms);
|
|
#else
|
|
bndPrintf("\t*\t\t");
|
|
#endif
|
|
fflush(stdout);
|
|
|
|
#if CLOCK_AVAIL
|
|
gettime(&start);
|
|
for (j = 0; j < n; j++)
|
|
#endif
|
|
if (dsaSignFast(p, q, &pre, x, y, &hash, &k, &r1, &s1) < 0)
|
|
goto failed;
|
|
#if CLOCK_AVAIL
|
|
gettime(&stop);
|
|
subtime(stop, start);
|
|
sig1sec += cursec = sec(stop);
|
|
sig1ms += curms = msec(stop);
|
|
divide_by_n(cursec, curms, n);
|
|
bndPrintf("%lu.%03u\t\t", cursec, curms);
|
|
#else
|
|
bndPrintf("*\t\t");
|
|
#endif
|
|
fflush(stdout);
|
|
if (bnCmp(&r, &r1) != 0) {
|
|
printf("\a** Error r != r1");
|
|
bndPut("g = ", g);
|
|
bndPut("k = ", &k);
|
|
bndPut("r = ", &r);
|
|
bndPut("r1= ", &r1);
|
|
}
|
|
if (bnCmp(&s, &s1) != 0) {
|
|
printf("\a** Error r != r1");
|
|
bndPut("g = ", g);
|
|
bndPut("k = ", &k);
|
|
bndPut("s = ", &s);
|
|
bndPut("s1= ", &s1);
|
|
}
|
|
|
|
/* Okay, r and s are the signature! Now, verify it. */
|
|
|
|
#if CLOCK_AVAIL
|
|
gettime(&start);
|
|
verified = 0; /* To silence warning */
|
|
for (j = 0; j < n; j++) {
|
|
#endif
|
|
verified = dsaVerify(p, q, g, y, &r, &s, &hash);
|
|
if (verified <= 0)
|
|
break;
|
|
}
|
|
#if CLOCK_AVAIL
|
|
gettime(&stop);
|
|
subtime(stop, start);
|
|
versec += cursec = sec(stop);
|
|
verms += curms = msec(stop);
|
|
divide_by_n(cursec, curms, j);
|
|
bndPrintf("%lu.%03u\t\t", cursec, curms);
|
|
#else
|
|
bndPrintf("*\t\t");
|
|
#endif
|
|
if (verified > 0) {
|
|
printf("Test successful.\n");
|
|
} else if (verified == 0) {
|
|
printf("\aSignature did NOT check!.\n");
|
|
bndPut("hash = ", &hash);
|
|
bndPut("k = ", &k);
|
|
bndPut("r = ", &r);
|
|
bndPut("s = ", &s);
|
|
getchar();
|
|
} else {
|
|
printf("\a** Error while verifying");
|
|
bndPut("hash = ", &hash);
|
|
bndPut("k = ", &k);
|
|
bndPut("r = ", &r);
|
|
bndPut("s = ", &s);
|
|
getchar();
|
|
goto failed;
|
|
}
|
|
}
|
|
#if CLOCK_AVAIL
|
|
divide_by_n(sigsec, sigms, m);
|
|
divide_by_n(sig1sec, sig1ms, m);
|
|
divide_by_n(versec, verms, m);
|
|
|
|
bndPrintf("%3u\t%lu.%03u\t\t%lu.%03u\t\t%lu.%03u\t\tAVERAGE %u/%u\n",
|
|
m, sigsec, sigms, sig1sec, sig1ms, versec, verms,
|
|
bnBits(p), bnBits(q));
|
|
#endif
|
|
/* Success */
|
|
retval = 0;
|
|
|
|
failed:
|
|
bnBasePrecompEnd(&pre);
|
|
bnEnd(&k);
|
|
bnEnd(&s1); bnEnd(&s);
|
|
bnEnd(&r1); bnEnd(&r);
|
|
bnEnd(&hash);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/* Copy the command line to the buffer. */
|
|
static unsigned
|
|
copy(unsigned char *buf, int argc, char **argv)
|
|
{
|
|
unsigned pos, len;
|
|
|
|
pos = 0;
|
|
while (--argc) {
|
|
len = strlen(*++argv);
|
|
memcpy(buf, *argv, len);
|
|
buf += len;
|
|
pos += len;
|
|
if (argc > 1) {
|
|
*buf++ = ' ';
|
|
pos++;
|
|
}
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
unsigned len;
|
|
struct BigNum p, q, g, x, y;
|
|
unsigned char buf[1024];
|
|
|
|
if (argc < 2) {
|
|
fprintf(stderr, "Usage: %s <seed>\n", argv[0]);
|
|
fputs("\
|
|
<seed> should be a a string of bytes to be hashed to seed the prime\n\
|
|
generator. Note that unquoted whitespace between words will be counted\n\
|
|
as a single space. To include multiple spaces, quote them.\n", stderr);
|
|
return 1;
|
|
}
|
|
|
|
bnInit();
|
|
bnBegin(&p);
|
|
bnBegin(&q);
|
|
bnBegin(&g);
|
|
bnBegin(&x);
|
|
bnBegin(&y);
|
|
|
|
len = copy(buf, argc, argv);
|
|
dsaGen(&p, 512, &q, 160, &g, &x, &y, buf, len, stdout);
|
|
dsaTest(&p, &q, &g, &x, &y);
|
|
|
|
len = copy(buf, argc, argv);
|
|
dsaGen(&p, 768, &q, 160, &g, &x, &y, buf, len, stdout);
|
|
dsaTest(&p, &q, &g, &x, &y);
|
|
|
|
len = copy(buf, argc, argv);
|
|
dsaGen(&p, 1024, &q, 160, &g, &x, &y, buf, len, stdout);
|
|
dsaTest(&p, &q, &g, &x, &y);
|
|
|
|
len = copy(buf, argc, argv);
|
|
dsaGen(&p, 1536, &q, 192, &g, &x, &y, buf, len, stdout);
|
|
dsaTest(&p, &q, &g, &x, &y);
|
|
|
|
len = copy(buf, argc, argv);
|
|
dsaGen(&p, 2048, &q, 224, &g, &x, &y, buf, len, stdout);
|
|
dsaTest(&p, &q, &g, &x, &y);
|
|
|
|
len = copy(buf, argc, argv);
|
|
dsaGen(&p, 3072, &q, 256, &g, &x, &y, buf, len, stdout);
|
|
dsaTest(&p, &q, &g, &x, &y);
|
|
|
|
len = copy(buf, argc, argv);
|
|
dsaGen(&p, 4096, &q, 288, &g, &x, &y, buf, len, stdout);
|
|
dsaTest(&p, &q, &g, &x, &y);
|
|
|
|
bnEnd(&y);
|
|
bnEnd(&x);
|
|
bnEnd(&g);
|
|
bnEnd(&q);
|
|
bnEnd(&p);
|
|
|
|
return 0;
|
|
}
|