Signing and Verifying Digital Signature Algorithm DSA

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