1 #include "os.h"
2 #include <mp.h>
3 #include <libsec.h>
4
5 DSApriv*
dsagen(DSApub * opub)6 dsagen(DSApub *opub)
7 {
8 DSApub *pub;
9 DSApriv *priv;
10 mpint *exp;
11 mpint *g;
12 mpint *r;
13 int bits;
14
15 priv = dsaprivalloc();
16 pub = &priv->pub;
17
18 if(opub != nil){
19 pub->p = mpcopy(opub->p);
20 pub->q = mpcopy(opub->q);
21 } else {
22 pub->p = mpnew(0);
23 pub->q = mpnew(0);
24 DSAprimes(pub->q, pub->p, nil);
25 }
26 bits = Dbits*pub->p->top;
27
28 pub->alpha = mpnew(0);
29 pub->key = mpnew(0);
30 priv->secret = mpnew(0);
31
32 // find a generator alpha of the multiplicative
33 // group Z*p, i.e., of order n = p-1. We use the
34 // fact that q divides p-1 to reduce the exponent.
35 //
36 // This isn't very efficient. If anyone has a better
37 // idea, mail presotto@closedmind.org
38 exp = mpnew(0);
39 g = mpnew(0);
40 r = mpnew(0);
41 mpsub(pub->p, mpone, exp);
42 mpdiv(exp, pub->q, exp, r);
43 if(mpcmp(r, mpzero) != 0)
44 sysfatal("dsagen foul up");
45 while(1){
46 mprand(bits, genrandom, g);
47 mpmod(g, pub->p, g);
48 mpexp(g, exp, pub->p, pub->alpha);
49 if(mpcmp(pub->alpha, mpone) != 0)
50 break;
51 }
52 mpfree(g);
53 mpfree(exp);
54
55 // create the secret key
56 mprand(bits, genrandom, priv->secret);
57 mpmod(priv->secret, pub->p, priv->secret);
58 mpexp(pub->alpha, priv->secret, pub->p, pub->key);
59
60 return priv;
61 }
62