xref: /plan9/sys/src/cmd/unix/drawterm/libsec/dsagen.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
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