Difference between revisions of "EVP Signing and Verifying"

From OpenSSLWiki
Jump to: navigation, search
(Added additional code comments around why EVP_DigestSignFinal is called twice)
m (Expanded introduction; moved example under subheading of Hashing since its a hashing example. MAC'ing and signatures are currently missing.)
Line 1: Line 1:
There are two APIs available for performing sign and verify operations. The older EVP_Sign* functions, and the newer and more flexible EVP_DigestSign* functions. They are very similar, but for new applications the EVP_DigestSign* versions should be preferred.
+
There are two APIs available for performing sign and verify operations. The older <tt>EVP_Sign*</tt> and <tt>EVP_Verify*</tt> functions, and the newer and more flexible <tt>EVP_DigestSign*</tt> and <tt>EVP_DigestVerify*</tt> functions. Though the APIs are similar, new applications should use the <tt>EVP_DigestSign*</tt> and <tt>EVP_DigestVerify*</tt> functions.
  
==Signing a Message==
+
The examples below use the new <tt>EVP_DigestSign*</tt> and <tt>EVP_DigestVerify*</tt> functions.
 +
 
 +
==Public Key Signing==
 +
 
 +
The first example shows how to create a signature over a message using <tt>EVP_DigestSignInit</tt>, <tt>EVP_DigestSignUpdate</tt> and <tt>EVP_DigestSignFinal</tt>. The second example shows how to verify a signature over the message using <tt>EVP_DigestVerifyInit</tt>, <tt>EVP_DigestVerifyUpdate</tt> and <tt>EVP_DigestVerifyFinal</tt>.
 +
 
 +
===Signing a Message===
  
 
Signing a message is a three stage process:
 
Signing a message is a three stage process:
* Initialise the operation and identify the message digest/hash function that will be used during the sign operation.  
+
* Initialize the context and identify the message digest/hash function that will be used during the sign operation.  
* Add message data (this step can be repeated as many times as necessary to add more message data)
+
* Add message data (this step can be repeated as many times as necessary)
* Create the signature
+
* Finalize to create the signature
 
 
In order to initialise the operation, you need to have first set up a EVP_PKEY object containing a public key for an algorithm that supports signing (this includes MAC codes). Refer to [[EVP#Working with EVP_PKEYs|Working with EVP_PKEYs]] for further information. You also need to provide a message digest algorithm (refer to [[EVP#Working with Algorithms and Modes|Working with Algorithms and Modes]]).
 
  
See the following for an example of signing a message:
+
In order to initialize the operation, you need to first have first set up a <tt>EVP_PKEY</tt> object containing a public key for an algorithm that supports signing (this includes MAC codes). Refer to [[EVP#Working with EVP_PKEYs|Working with EVP_PKEYs]] for further information. You also need to provide a message digest algorithm (refer to [[EVP#Working with Algorithms and Modes|Working with Algorithms and Modes]]).
  
EVP_MD_CTX *mdctx = NULL;
+
<pre>EVP_MD_CTX *mdctx = NULL;
int ret = 0;
+
int ret = 0;
 
   
 
   
*sig = NULL;
+
*sig = NULL;
 
   
 
   
/* Create the Message Digest Context */
+
/* Create the Message Digest Context */
if(!(mdctx = EVP_MD_CTX_create())) goto err;
+
if(!(mdctx = EVP_MD_CTX_create())) goto err;
 
   
 
   
/* Initialise the DigestSign operation - SHA-256 has been selected as the message digest function in this example */
+
/* Initialise the DigestSign operation - SHA-256 has been selected as the message digest function in this example */
 
  if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err;
 
  if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err;
 
   
 
   
Line 46: Line 50:
 
  /* Clean up */
 
  /* Clean up */
 
  if(*sig && !ret) OPENSSL_free(*sig);
 
  if(*sig && !ret) OPENSSL_free(*sig);
  if(mdctx) EVP_MD_CTX_destroy(mdctx);
+
  if(mdctx) EVP_MD_CTX_destroy(mdctx);</pre>
  
 
Note: There is no difference in the API between signing using an asymmetric algorithm, and generating a MAC code. In the case of CMAC no message digest function is required (NULL can be passed). Signing using the EVP_Sign* functions is very similar to the above example, except there is no support for MAC codes. Note that CMAC is only supported in the (as yet unreleased) version 1.1.0 of OpenSSL.
 
Note: There is no difference in the API between signing using an asymmetric algorithm, and generating a MAC code. In the case of CMAC no message digest function is required (NULL can be passed). Signing using the EVP_Sign* functions is very similar to the above example, except there is no support for MAC codes. Note that CMAC is only supported in the (as yet unreleased) version 1.1.0 of OpenSSL.
Line 52: Line 56:
 
Refer to [[Manual:EVP_DigestSignInit(3)]] for further details on the EVP_DigestSign* functions, and [[Manual:EVP_SignInit(3)]] for the EVP_Sign* functions.
 
Refer to [[Manual:EVP_DigestSignInit(3)]] for further details on the EVP_DigestSign* functions, and [[Manual:EVP_SignInit(3)]] for the EVP_Sign* functions.
  
==Verifying a Message==
+
===Verifying a Signature===
  
 
Verifying a message is very similar to signing except the EVP_DigestVerify* functions (or EVP_Verify* functions) are used instead. Clearly only a public key is required for a verify operation:
 
Verifying a message is very similar to signing except the EVP_DigestVerify* functions (or EVP_Verify* functions) are used instead. Clearly only a public key is required for a verify operation:
  
<pre>
+
<pre>/* Initialize `key` with a public key */
if(1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err;
+
if(1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err;
if(1 != EVP_DigestVerifyUpdate(mdctx, msg, strlen(msg))) goto err;
+
 
if(1 == EVP_DigestVerifyFinal(mdctx, sig, slen))
+
/* Initialize `key` with a public key */
{
+
if(1 != EVP_DigestVerifyUpdate(mdctx, msg, strlen(msg))) goto err;
/* Success */
+
 
}
+
if(1 == EVP_DigestVerifyFinal(mdctx, sig, slen))
else
+
{
{
+
    /* Success */
/* Failure */
+
}
}
+
else
 +
{
 +
    /* Failure */
 +
}
 
</pre>
 
</pre>
  

Revision as of 02:05, 15 January 2015

There are two APIs available for performing sign and verify operations. The older EVP_Sign* and EVP_Verify* functions, and the newer and more flexible EVP_DigestSign* and EVP_DigestVerify* functions. Though the APIs are similar, new applications should use the EVP_DigestSign* and EVP_DigestVerify* functions.

The examples below use the new EVP_DigestSign* and EVP_DigestVerify* functions.

Public Key Signing

The first example shows how to create a signature over a message using EVP_DigestSignInit, EVP_DigestSignUpdate and EVP_DigestSignFinal. The second example shows how to verify a signature over the message using EVP_DigestVerifyInit, EVP_DigestVerifyUpdate and EVP_DigestVerifyFinal.

Signing a Message

Signing a message is a three stage process:

  • Initialize the context and identify the message digest/hash function that will be used during the sign operation.
  • Add message data (this step can be repeated as many times as necessary)
  • Finalize to create the signature

In order to initialize the operation, you need to first have first set up a EVP_PKEY object containing a public key for an algorithm that supports signing (this includes MAC codes). Refer to Working with EVP_PKEYs for further information. You also need to provide a message digest algorithm (refer to Working with Algorithms and Modes).

EVP_MD_CTX *mdctx = NULL;
int ret = 0;
 
*sig = NULL;
 
/* Create the Message Digest Context */
if(!(mdctx = EVP_MD_CTX_create())) goto err;
 
/* Initialise the DigestSign operation - SHA-256 has been selected as the message digest function in this example */
 if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err;
 
 /* Call update with the message */
 if(1 != EVP_DigestSignUpdate(mdctx, msg, strlen(msg))) goto err;
 
 /* Finalise the DigestSign operation */
 /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the
  * signature. Length is returned in slen */
 if(1 != EVP_DigestSignFinal(mdctx, NULL, slen)) goto err;
 /* Allocate memory for the signature based on size in slen */
 if(!(*sig = OPENSSL_malloc(sizeof(unsigned char) * (*slen)))) goto err;
 /* Obtain the signature */
 if(1 != EVP_DigestSignFinal(mdctx, *sig, slen)) goto err;
 
 /* Success */
 ret = 1;
 
 err:
 if(ret != 1)
 {
   /* Do some error handling */
 }
 
 /* Clean up */
 if(*sig && !ret) OPENSSL_free(*sig);
 if(mdctx) EVP_MD_CTX_destroy(mdctx);

Note: There is no difference in the API between signing using an asymmetric algorithm, and generating a MAC code. In the case of CMAC no message digest function is required (NULL can be passed). Signing using the EVP_Sign* functions is very similar to the above example, except there is no support for MAC codes. Note that CMAC is only supported in the (as yet unreleased) version 1.1.0 of OpenSSL.

Refer to Manual:EVP_DigestSignInit(3) for further details on the EVP_DigestSign* functions, and Manual:EVP_SignInit(3) for the EVP_Sign* functions.

Verifying a Signature

Verifying a message is very similar to signing except the EVP_DigestVerify* functions (or EVP_Verify* functions) are used instead. Clearly only a public key is required for a verify operation:

/* Initialize `key` with a public key */
if(1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err;

/* Initialize `key` with a public key */
if(1 != EVP_DigestVerifyUpdate(mdctx, msg, strlen(msg))) goto err;

if(1 == EVP_DigestVerifyFinal(mdctx, sig, slen))
{
    /* Success */
}
else
{
    /* Failure */
}

Note that MAC operations do not support the verify operation. Verifying a MAC code is done by calling the sign operations and confirming that the generated code is identical to the one provided. It is important that when comparing a supplied MAC with an expected MAC that the comparison takes a constant time whether the comparison returns a match or not. Failure to do this can expose your code to timing attacks, which could (for example) enable an attacker to forge MAC codes. To do this use the CRYPTO_memcmp function as shown in the code example below. Never use memcmp for this test:

	if(!(mdctx = EVP_MD_CTX_create())) goto err;

	/* Create a buffer to store the MAC for the received message */
	if(!(sigtmp = OPENSSL_malloc(sizeof(unsigned char) * EVP_PKEY_size(key)))) goto err;
	sigtmplen = EVP_PKEY_size(key);

	/* Calculate the MAC for the received message */
	if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err;
	if(1 != EVP_DigestSignUpdate(mdctx, msg, strlen(msg))) goto err;
	if(1 != EVP_DigestSignFinal(mdctx, sigtmp, &sigtmplen)) goto err;

	/* Check the lengths of the calculated and supplied MACs are the same */ 
	if(sigtmplen != slen) goto err;

	/* Calculated MAC is in sigtmp. Supplied MAC is in sig. Compare the two */
	if(CRYPTO_memcmp(sig, sigtmp, slen))	
		/* Verify failure */ goto failure;
	else
		/* Verify success */;

Refer to Manual:EVP_DigestVerifyInit(3) and Manual:EVP_VerifyInit(3) for further information on the verify functions.

See also