197
An optional argument that will receive the number of iterations the function went through to find a value for
h
, which is the random number used to calculate
g
. This argument may be specified as
NULL
. callback
A pointer to a function that will be called during the prime generation process to report the status of the prime generation. The callback is the same as the callback used by
BN_generate_prime
, which we discussed in Chapter 4
. This argument may be specified as
NULL
if no callbacks are desired. cb_arg
A pointer to application-specific data. OpenSSL does not use this value for anything itself. It is passed as an argument to the specified callback function.
Once parameters have been generated, key pairs can be generated. The function
DSA_generate_key
is provided by OpenSSL for doing just that. It requires as its only argument a
DSA
object that has the parameters
p
,
q
, and
g
filled in. If the keys are generated successfully, the return from the function will be nonzero. If an error occurs, the return will be zero. The
generated public and private keys are stored in the supplied
DSA
objects
pub_key
and
priv_key
members, respectively. Once the keys are computed, they can be used for creating digital signatures and verifying them.
The
DSA
object containing the parameters and keys must remain in memory to perform these operations, of course, but when the
DSA
object is no longer needed, it should be destroyed by calling
DSA_free
and passing the
DSA
object as its only argument.
8.3.3 Signing and Verifying
Digital signatures must be computed over a message digest of the data that will be signed. The DSA standard dictates that the message digest algorithm used for this is SHA1, which has output
of the same size as the DSA
q
parameter. This is no coincidence. In fact, the DSA algorithm cannot be used to compute a signature for data that is larger than its
q
parameter. OpenSSL provides a low-level interface for computing signatures that does allow you to use DSA
to sign arbitrary data. By this, we mean that OpenSSL does not enforce the requirement to use SHA1 as the message digest to sign, or even to sign a message digest at all We strongly
recommend against using the low-level interface for signing and verifying in favor of using the EVP interface, which we describe later in this chapter. However, we will briefly cover the three
low-level functions for creating and verifying DSA signatures.
Computing a digital signature can be a processor-intensive operation. For this reason, OpenSSL provides a function that allows for the pre-computation of the portions of a signature that do not
actually require the data to be signed.
int DSA_sign_setupDSA dsa, BN_CTX ctx, BIGNUM kinvp, BIGNUM rp;
dsa The
DSA
object containing the parameters and private key that will be used for signing. ctx
198
An optional
BIGNUM
context that will be used in the pre-computation. If this argument is specified as
NULL
, a temporary context will be created and used internally. kinvp
Receives a dynamically allocated
BIGNUM
that will hold the pre-computed
kinv
value. This value can then be placed into the
DSA
objects
kinv
member so that it will be used when signing.
rp Receives a dynamically allocated
BIGNUM
that will hold the pre-computed
r
value. This value can then be placed into the
DSA
objects
r
member so that it will be used when signing.
Care must be taken when pre-computing the
kinv
and
r
values for signing. Both values must be placed in the
DSA
object. If only one is placed in the object, the memory used by the other will be leaked. Additionally, the values cannot be reused. They will be destroyed by the signing function.
It may seem tempting to save a copy of the pre-computed values and reuse them for signing multiple pieces of data, but you must not. An integral part of a DSA signature is a 160-bit
actually, the same size as the
q
parameter, but that should always be 160 bits random number known as
k
. If the same value for
k
is used more than once, it is possible for an attacker to discover the private key.
The function
DSA_sign
is provided for actually computing a digital signature using the DSA algorithm. If pre-computation of
kinv
and
r
has not been done, the function will perform the computation itself.
int DSA_signint type, const unsigned char dgst, int len, unsigned char sigret, unsigned int siglen, DSA dsa;
type Ignored for DSA signing. The argument is present only for consistency with the RSA
signing function. dgst
The buffer of data that will be signed, which should always be an SHA1 hash. len
The number of bytes in the data buffer for signing. It should always be the length of the message digest, but can never be larger than the size of the
q
parameter, which is fixed at 160 bits or 20 bytes.
sigret A buffer that will receive the signature. It must be large enough to hold the signature. The
minimum size for the buffer can be determined with a call to
DSA_size
, passing the
DSA
object that is being used for signing as the only argument. siglen
199
Receives the number of bytes of the
sigret
buffer that were filled with the signature. This argument cannot be
NULL
. dsa
The DSA object to use to sign the contents of the data buffer. The function
DSA_verify
is used to verify signatures and is similar to the function used to create them.
int DSA_verifyint type, const unsigned char dgst, int len, unsigned char sigbuf, int siglen, DSA dsa;
type Ignored for DSA verification. The argument is present only for consistency with the RSA
verification function. dgst
The message digest of the data. This digest should be computed on the data prior to calling this function. This is used to compare with the digest in the signature.
len The number of bytes in the digest buffer.
sigbuf The signature that will be verified.
siglen The number of bytes contained in the signature buffer.
dsa The
DSA
object to use to verify the signature.
8.3.4 Practical Applications