drawterm/libsec/dsagen.c

62 lines
1.2 KiB
C

#include "os.h"
#include <mp.h>
#include <libsec.h>
DSApriv*
dsagen(DSApub *opub)
{
DSApub *pub;
DSApriv *priv;
mpint *exp;
mpint *g;
mpint *r;
int bits;
priv = dsaprivalloc();
pub = &priv->pub;
if(opub != nil){
pub->p = mpcopy(opub->p);
pub->q = mpcopy(opub->q);
} else {
pub->p = mpnew(0);
pub->q = mpnew(0);
DSAprimes(pub->q, pub->p, nil);
}
bits = Dbits*pub->p->top;
pub->alpha = mpnew(0);
pub->key = mpnew(0);
priv->secret = mpnew(0);
// find a generator alpha of the multiplicative
// group Z*p, i.e., of order n = p-1. We use the
// fact that q divides p-1 to reduce the exponent.
//
// This isn't very efficient. If anyone has a better
// idea, mail presotto@closedmind.org
exp = mpnew(0);
g = mpnew(0);
r = mpnew(0);
mpsub(pub->p, mpone, exp);
mpdiv(exp, pub->q, exp, r);
if(mpcmp(r, mpzero) != 0)
sysfatal("dsagen foul up");
while(1){
mprand(bits, genrandom, g);
mpmod(g, pub->p, g);
mpexp(g, exp, pub->p, pub->alpha);
if(mpcmp(pub->alpha, mpone) != 0)
break;
}
mpfree(g);
mpfree(exp);
// create the secret key
mprand(bits, genrandom, priv->secret);
mpmod(priv->secret, pub->p, priv->secret);
mpexp(pub->alpha, priv->secret, pub->p, pub->key);
return priv;
}