Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Security

Cryptography Providers and the CryptoAPI


[The is the second article in a two-part series. For Part 1, click here.]

To finish up with our look at encrypting a password with CryptoAPI, we'll look at using more advanced forms of the SHA algorithm and the concept of "salting the password data to make it more secure.

You may recall from Part 1 that I mentioned that SHA (Secure Hashing Algorithm) comes in 160, 256, 384, and 512-bit message "digests. The code outlined in that article showed how to create a hash using the default 160-bit message digest. However, if you feel the need to create a stronger hash, you can increase the number of bits used in the hash. Be aware that, in general, the more bits in the hash, the longer it takes to generate the hash-some of the longest keys are typically used in creating digital signatures, which can use keys of 1024 bits. More is not better, unless you definitely have the need.

However, to use the larger message digests, you need to switch to a different cryptographic "provider within CryptoAPI. This is the value passed to the CryptAcquireContext function. The PROV_RSA_FULL provider used in the example in Part 1 does not support the larger message digests of SHA. Instead, switch to the PROV_RSA_AES provider value.

AES stands for the Advanced Encryption Standard, which was developed by Belgian cryptographers Joan Daemen and Vincent Rijmen and was originally called the "Rijndael encryption algorithm" (taken from the letters of the last names of the authors). The NIST in the U.S. put out a request for proposal (RFP) to the cryptography community in the late 1990s for a new algorithm to replace the venerable (but dated) Digital Encryption Standard (DES), which had been in use by the U.S. government, corporations, and other bodies as an approved and safe form of encryption since the 1970s. However, as time passed and computers became ever more powerful, the DES algorithm was proving to be less safe than originally thought (since it used 56-bit key sizes). As an attempt to make it more secure 3DES or Triple DES was used in some cases (essentially applying DES three times to the same data). However, the U.S. government decided a new algorithm was needed and asked the cryptography community for help. Interestingly, the Rijndael algorithm was selected from a set of 12 finalists, which included some of the finest cryptography groups in the world. You can read more about this algorithm at http://www.nist.gov/public_affairs/releases/g00-176.htm but here is a description of AES from that site:

"The Advanced Encryption Standard (AES) will be a new Federal Information Processing Standard (FIPS) Publication that will specify a cryptographic algorithm for use by U.S. Government organizations to protect sensitive (unclassified) information. NIST also anticipates that the AES will be widely used on a voluntary basis by organizations, institutions, and individuals outside of the U.S.

The key sizes supported by Rijndael include 128, 192, and 256 bits. As a result of this new encryption standard, new providers were created to support it and larger key sizes for the SHA hash were included. Thus the use of the new PROV_RSA_AES provider when you want to create a hash larger than 160 bits.

So, here is how last issue's code would look if we wanted to create a SHA hash with a 256-bit message digest instead of a 160-bit message digest:

   #include <wincrypt.h>

   int hashedstrsize = 20;
   BYTE* hashedstr = NULL;
   LPCSTR str = "a password;

   HCRYPTPROV hCryptProv = NULL;
if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES,
 CRYPT_VERIFYCONTEXT)) 
   {
      HCRYPTHASH hHash = NULL;
      if (CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0,&hHash))
      {
         if (CryptHashData(hHash, (BYTE*)str, (DWORD)strlen(str), 0)) 
         {   
            DWORD len = sizeof(m_size);
            if (CryptGetHashParam(hHash, HP_HASHSIZE, 
                  (BYTE*)&m_size, &len, 0))
            {
               hashedstr = new BYTE[m_size];
               len = m_size;
               if (CryptGetHashParam(hHash, HP_HASHVAL,
                      (BYTE*)hashedstr, &len, 0))
               {
                  // all is well and we have a hash..
               }
            }
            clear();

         CryptDestroyHash(hHash);
      }

      CryptReleaseContext(hCryptProv, 0);
   }

Finally, we consider adding a salt value to the original data before hashing it. The concept of a salt is rather simple-it adds some random data to the original information to make creating a duplicate hash much more difficult (since the attacker would have to know the original salt value). For example, if the attacker generated random password values, hashed them with SHA, and compared the two hashes, he might eventually stumble across the correct password. Adding a salt value makes this much more difficult since the hash would obscure the original password.

Fortunately, adding a hash is simple-you append or prepend 4 to 8 bytes of random data to the password value before generating the hash. Then, the hash is stored along with the salt value (4 to 8 bytes you appended or prepended). Extracting the hash later, you would strip off the salt value and use it to append or prepend to the incoming test value before hashing and comparing to the stored value. Another approach is to hardwire the salt into the comparison code rather than store it in the data. As long as the attacker cannot gain access to the code to determine the salt value, you've added extra security to the hashed value for little to no cost. Increasing the size of the password by adding the salt does not change the size of the hash-it's still 20 bytes if you're using SHA.

Microsoft has made it really simple to use encryption in your application by providing CryptoAPI. I would strongly suggest that you use it rather than rolling your own obfuscation algorithm-it would take more time to write the code for your own than to use CryptoAPI, and it wouldn't be secure.

As a parting suggestion, pick up a copy of Simon Singh's The Code Book (which I also mentioned in Part 1) and read it if you want to learn more about encryption. I thoroughly enjoyed it as a readable and entertaining book on the subject.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.