DSA *DSA_new();
void DSA_free (r)
DSA *r;
int DSA_size(r)
DSA *r;
DSA *DSA_generate_parameters(bits, seed, seed_len, counter_ret, h_ret, callback, cb_arg)
int bits, seed_len, *counter_ret;
unsigned char *seed;
unsigned long *h_ret;
void (*callback)());
char *cb_arg;
int DSA_generate_key(a)
DSA *a;
int DSA_sign_setup(dsa, ctx_in, kinvp, rp)
DSA *dsa;
BN_CTX *ctx_in;
BIGNUM **kinvp, **rp;
int DSA_sign(type, dgst, dlen, sig, siglen, dsa)
int type, dlen;
unsigned char *dgst, *sig;
unsigned int *siglen;
DSA *dsa;
int DSA_verify(type, dgst, dgst_len, sigbuf, siglen, dsa)
int type, dgst_len, siglen;
unsigned char *dgst, *sigbuf;
DSA *dsa;
void ERR_load_DSA_strings();
DSA *d2i_DSAPublicKey(a, pp, length)
DSA **a;
unsigned char **pp;
long length;
DSA *d2i_DSAPrivateKey(a, pp, length)
DSA **a;
unsigned char **pp;
long length;
DSA *d2i_DSAparams(a, pp, long length)
DSA **a;
unsigned char **pp;
long length;
int i2d_DSAPublicKey(a, pp)
DSA *a;
unsigned char **pp;
int i2d_DSAPrivateKey(a, pp)
DSA *a;
unsigned char **pp;
int i2d_DSAparams(a, pp)
DSA *a;
unsigned char **pp;
int DSAparams_print(bp, x)
BIO *bp;
DSA *x;
int DSA_print(bp, x, off)
BIO *bp;
DSA *x;
int off;
int DSAparams_print_fp(fp, x)
FILE *fp;
DSA *x;
int DSA_print_fp(bp, x, off)
FILE *bp;
DSA *x;
int off;
int DSA_is_prime(q, callback)
BIGNUM *q;
void (*callback)();
All of these routines take a DSA structure which contains the following:
typedef struct dsa_st { /* This first variable is used to pick up errors where * a DSA is passed instead of of a EVP_PKEY */ int pad; int version; int write_params; BIGNUM *p; BIGNUM *q; /* == 20 */ BIGNUM *g; BIGNUM *pub_key; BIGNUM *priv_key; BIGNUM *kinv; /* Signing pre-calc */ BIGNUM *r; /* Signing pre-calc */ int references; } DSA;
DSA_new returns a new DSA stucture with fields initialized or set to NULL. It returns NULL on error.
DSA_free frees the DSA structure passed to it and any subfields that are not NULL.
DSA_size returns the length of the ASN1 der-encoding of the DSA parameters. This is used by EVP_PKEY_size when DSA is the signature algorithm used in the creation of the 'envelope'. EVP_KEY_size in turn is used to determine the length of an ASN1 der-encoded public key so that it can be written out in for example an ASN1-style signature (think of an X509 certificate, for example).a
DSA_generate_parameters expects the caller to pass it the bit length of the desired p in bits; if bits is less than 512 it will be set to 512 for you :) You may use a value as large as 1024, according to the standard. (Has this changed yet?)
If seed_in is not NULL and seed_len is 20, the seed will be used as input to the various hashes that are done during the calculation. Otherwise a random seed will be generated.
counter_ret and h_ret are both filled in by the function; these, together with the seed, can be used to generate the same p and q, in case you are suspicious of these values for some reason.
callback is called at a number of points during the calculation so that the application programmer can display a message to the user that describes how the computations are progressing. It is called at the beginning of each main loop as callback(0,num1++,cb_arg); when there's a prime found, as callback(1,num2++,cb_arg); after q is generated, as callback(2,0,cb_arg); and then immediately as callback(3,0,cb_arg); after p is generated, as callback(2,1,cb_arg); after g is generated, as callback(3,1,cb_arg); and then we are done.
The actual computation is ugly. Not hard, just tedious. Here's a pointer to the NIST document (FIPS PUB 186) that spells out the method they recommend (which is implemented here).
This function returns a DSA structure with the values p, q and g filled in, or NULL on error.
DSA_generate_key expects the caller to pass a DSA structure with subfields p, q and g filled in.
It generates a random priv_key that is smaller than q, and a pub_key that is g^priv_key mod p, and stuffs these into the DSA structure.
DSA_sign_setup expects the caller to pass a DSA structure with at least p, q and g filled in. Note that priv_key need not be filled in! But you will need it for the next step, DSA_sign.
ctx_in may be a previously allocated BN_CTX or it may be NULL, in which case one will be created for the caller.
**kinvp will be set to k^-1 mod q where k is randomly generated.
**rp, if not NULL, will be freed, and re-allocated. It will be set to (g^k mod p) mod q.
These values are used in computing the signature. Do we gain anything from precomputation as it's set up here? At least the code is more readable when it's modularized this way.
DSA_sign expects thecaller to pass the DSA structure dsa with all of the relevant fields filled in. If DSA_sign_setup was not called before calling this function, it will be called for you. dgst must point to the message digest to be signed, and dlen must be the length of that digest. type is ignored. I wonder why it is a parameter?
The function returns the signature asn1 der-encoded in *sig and the length of that object in *siglen. It returns 0 on success, and 1 on error.
DSA_verify expects dgst to point to the message digest contents before signature, dgst_len to contain the length of the message digest, sigbuf to point to the asn1 der-encoded signature, and siglen to be the length of that object. The DSA structure dsa must have all of the relevant fields (r, p, q) filled in.
The routine gets the signed message digest out of the der-encoded string, encrypts it, and checks that the resulting data and length match the data and length in dgst and dgst_len.
It returns 1 on successful check, 0 if the signature does not check, and -1 on error.
ERR_load_DSA_strings initializes arrays for the error-handling library with messages specific to the DSA library.
DSAparams_print_fp is actually defined in the ASN1 library.
This function prints out the DSA parameters passed in dsa to the file specified by fp. It calls DSAparams_print to do the most of the work.
DSAparams_print is actually defined in the ASN1 library.
This function prints out the DSA parameters passed in dsa to the BIO file specified by bp. The format is fixed and looks like this:
DSA-Parameters: (xx bit) p: xxxxxxxxxxxx q: xxxxxxxxxxxxxx g: xxxxxxxx
where the xxx are hex numbers.
DSA_print_fp is actually defined in the ASN1 library.
This function prints out the DSA parameters passed in dsa to the file specified by fp. It calls DSA_print to do the most of the work.
off is as in DSA_print below.
DSA_print is actually defined in the ASN1 library.
This function prints out the DSA parameters passed in dsa to the BIO file specified by bp. The format is fixed and looks like this:
Private-Key: (xx bit) priv: xxxxxxxxxxxxxx pub: xxxxxxxxxxxxx p: xxxxxxxxxxxx q: xxxxxxxxxxxxxx g: xxxxxxxx
where the xxx are hex numbers.
off is the number of leading blanks to put before each field. If off is greater than 128, it is silently reset to 128 and the new value is used instead.
DSA_is_prime does 50 rounds of the Miller-Rabin test on w. The callback supplied is called for each round that is passed, so that the application programmer can display a message informing the user as to the progress of the computations.
It returns 1 if prime, 0 if not, and -1 on error.
The following routines are actually defined in the ASN1 library:
int i2d_DSAPublicKey(DSA *a, unsigned char **pp); int i2d_DSAPrivateKey(DSA *a, unsigned char **pp); int i2d_DSAparams(DSA *a,unsigned char **pp); DSA *d2i_DSAPublicKey(DSA **a, unsigned char **pp, long length); DSA *d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length); DSA *d2i_DSAparams(DSA **a, unsigned char **pp, long length);
See ASN.1 conversion to and from DER-encoded form for how to use these i2d and d2i functions.
The following macros have been also been provided for the programmer's convenience:
#define DSAparams_dup(x) (DSA *)ASN1_dup((int (*)())i2d_DSAparams, \ (char *(*)())d2i_DSAparams,(char *)(x)) #define d2i_DSAparams_fp(fp,x) (DSA *)ASN1_d2i_fp((char *(*)())DSA_new, \ (char *(*)())d2i_DSAparams,(fp),(unsigned char **)(x)) #define i2d_DSAparams_fp(fp,x) ASN1_i2d_fp(i2d_DSAparams,(fp), \ (unsigned char *)(x)) #define d2i_DSAparams_bio(bp,x) (DSA *)ASN1_d2i_bio((char *(*)())DSA_new, \ (char *(*)())d2i_DSAparams,(bp),(unsigned char **)(x)) #define i2d_DSAparams_bio(bp,x) ASN1_i2d_bio(i2d_DSAparams,(bp), \ (unsigned char *)(x))
See ASN1 format manipulation routines for information on the ASN1_dup() fuction.
See ASN1 io routines for information on the i2d and d2i io routines.