Click here to Skip to main content
14,269,255 members

CSHA1 - A C++ Class Implementation of the SHA-1 Hash Algorithm

Rate this:
4.89 (72 votes)
Please Sign up or sign in to vote.
4.89 (72 votes)
19 Jun 2012CPOL
CSHA1 - A C++ class implementation of the SHA-1 hash algorithm

Contents


Description of the Secure Hash Algorithm SHA-1

The Secure Hash Algorithm SHA-1 is a cryptographically secure one-way hash algorithm. It was designed by the NIST (National Institute of Standards and Technology), along with the NSA (National Security Agency). SHA-1 is based on the Message Digest MD4 algorithm design principles by Ronald L. Rivest of MIT.

Well, I think I don't have to explain what you can do with cryptographic hash algorithms. For an example what you can do with such algorithms, see this CodeProject article (CMD5 class).

For more information about SHA-1, see references [1] and [2].


CSHA1 Class Description

The CSHA1 class is an easy-to-use class for the SHA-1 hash algorithm.

If you want to test if your implementation of the class is working, try the test vectors in the 'TestVectors' directory in the demo zip file. You can find the correct hash values in the header file of the CSHA1 class.

Class members of the CSHA1 class:

  • void Reset();

    This member function resets the class. You have to call this method when using CSHA1 more than one time. This method is called automatically in the constructor and the destructor of the class so if you only hash one single data stream you don't need to call Reset() manually.

  • void Update(const UINT_8* pbData, UINT_32 uLen);

    Use this method to hash in a data stream. Data in pbData, number of bytes in uLen.

  • bool HashFile(const TCHAR* tszFileName);

    This method hashes file contents into the current state. If hashing was successful, the method returns true, otherwise false. If you use this member function, you don't need to make any call to the Update(...) method. After HashFile(...) you should call the Final() method immediately. You have to call Final() before getting the message digest of the file using the methods ReportHash(...) and GetHash(...).

  • void Final();

    When you have hashed in all data to hash, call this method. This will compute the final SHA-1 message digest and it is therefore needed to call this method before ReportHash(...) and GetHash(...).

  • bool ReportHash(TCHAR* tszReport, REPORT_TYPE rtReportType = REPORT_HEX) const;

    After calling the Final method you can get the message digest using this method. The result is stored as string in tszReport. Valid format types for uReportType are REPORT_HEX, REPORT_DIGIT and REPORT_HEX_SHORT. If you use REPORT_HEX the returned string looks like 5F A9 FB 34..., using REPORT_DIGIT this method returns the message digest in the form 129 67 5 98... . REPORT_HEX_SHORT is the same as REPORT_HEX, just without separating spaces.

  • bool GetHash(UINT_8* pbDest20) const;

    If you don't want to get the hash in a pre-formatted string using ReportHash, you can use this method. This method copies the final message digest (call Final before!) to pbDest20. pbDest20 must be able to hold at least 20 bytes (SHA-1 produces a 160-bit / 20-byte hash).


Hashing Binary Data and Strings

CSHA1 sha1;
sha1.Update(string0, strlen(string0));
sha1.Update(string1, strlen(string1));
sha1.Update(binary2, uSizeOfBufferBinary2);
sha1.Update(binary3, uSizeOfBufferBinary3);
sha1.Final();

sha1.ReportHash(szReport, CSHA1::REPORT_HEX_SHORT);
// or
sha1.GetHash(binaryArray);

I will comment each line of the example above now.

First declare an instance of the CSHA1 class:

CSHA1 sha1;

Now hash in the data like this:

sha1.Update((UINT_8*)szString, strlen(szString));

You can call this method as often as you wish.

When you hashed in all data, call the Final() member function:

sha1.Final();

If you want to get the final message digest as a pre-formatted string use this:

sha1.ReportHash(szReport, CSHA1::REPORT_HEX_SHORT);

If you want to get the final message digest in "raw form":

sha1.GetHash(binaryArray); // Get the raw message digest bytes

Hashing Files

Hashing files is the same process as hashing strings and binary data but instead of using the Update method you use the HashFile member function of the class.

For more comments see the string/binary data hashing example above.

CSHA1 sha1;
sha1.HashFile("TheFile.cpp"); // Hash in the contents of the file
                              // 'TheFile.cpp'
sha1.Final();

sha1.ReportHash(szReport, CSHA1::REPORT_HEX); // Get final hash as
                                              // pre-formatted string
// or
sha1.GetHash(binaryArray); // Get the raw message digest bytes to a
                           // temporary buffer

References

[1] RFC 3174: US Secure Hash Algorithm 1 (SHA1).
[2] Bruce Schneier, Applied Cryptography, pages 442-445.


Version History

  • Version 2.1 - 2012-06-19
    • Deconstructor (resetting internal variables) is now only implemented if SHA1_WIPE_VARIABLES is defined (which is the default).
    • Renamed inclusion guard to contain a GUID.
    • Demo application is now using C++/STL objects and functions.
    • Unicode build of the demo application now outputs the hashes of both the ANSI and Unicode representations of strings.
    • Various other demo application improvements.
  • Version 2.0 - 2012-06-14
    • Added 'limits.h' include.
    • Renamed inclusion guard and macros for compliancy (names beginning with an underscore are reserved).
  • Version 1.9 - 2011-11-10
    • Added Unicode test vectors.
    • Improved support for hashing files using the HashFile method that are larger than 4 GB.
    • Improved file hashing performance (by using a larger buffer).
    • Disabled unnecessary compiler warnings.
    • Internal variables are now private.
  • Version 1.8 - 2009-03-16
    • Converted project files to Visual Studio 2008 format.
    • Added Unicode support for HashFile utility method.
    • Added support for hashing files using the HashFile method that are larger than 2 GB.
    • HashFile now returns an error code instead of copying an error message into the output buffer.
    • GetHash now returns an error code and validates the input parameter.
    • Added ReportHashStl STL utility method.
    • Added REPORT_HEX_SHORT reporting mode.
    • Improved Linux compatibility of test program.
  • Version 1.7 - 2006-12-21
    • Fixed buffer underrun warning that appeared when compiling with Borland C Builder (thanks to Rex Bloom and Tim Gallagher for the patch).
    • Breaking change: ReportHash writes the final hash to the start of the buffer, i.e. it's not appending it to the string anymore.
    • Made some function parameters const.
    • Added Visual Studio 2005 project files to demo project.
  • Version 1.6 - 2005-02-07
    • You can set the endianness in your files, no need to modify the header file of the CSHA1 class anymore.
    • Aligned data support.
    • Made support/compilation of the utility functions (ReportHash and HashFile) optional (useful when bytes count, for example in embedded environments).
    • Thanks to Howard Kapustein for patches.
  • Version 1.5 - 2005-01-01
    • 64-bit compiler compatibility added.
    • Made variable wiping optional (define SHA1_WIPE_VARIABLES).
    • Removed unnecessary variable initializations.
    • ROL32 improvement for the Microsoft compiler (using _rotl).
  • Version 1.4 - 2004-07-22
    • CSHA1 now compiles fine with GCC 3.3 under Mac OS X (thanks to Larry Hastings).
  • Version 1.3 - 2003-08-17
    • Fixed a small memory bug and made a buffer array a class member to ensure correct working when using multiple CSHA1 class instances at one time.
  • Version 1.2 - 2002-11-16
    • Borlands C++ compiler seems to have problems with string addition using sprintf. Fixed the bug which caused the digest report function not to work properly. CSHA1 is now Borland compatible.
  • Version 1.1 - 2002-10-11
    • Removed two unnecessary header file includes and changed BOOL to bool. Fixed some minor bugs in the web page contents.
  • Version 1.0 - 2002-06-20
    • First official release.

That's it! Happy hashing!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Dominik Reichl
Software Developer
Unknown
Dominik started programming in Omikron Basic, a programming language for the good old Atari ST. After this, there was some short period of QBasic programming on the PC, but soon he began learning C++, which is his favorite language up to now.

Today, his programming experience includes C / C++ / [Visual] C++ [MFC], C#/.NET, Java, JavaScript, PHP and HTML and the basics of pure assembler.

He is interested in almost everything that has to do with computing; his special interests are security, cryptography and data compression.

You can find his latest freeware, open source projects and articles on his website: https://www.dominik-reichl.de/.

Comments and Discussions

 
QuestionResults on Unix versus Windows? Pin
Rashad26-Nov-03 10:12
memberRashad26-Nov-03 10:12 
AnswerRe: Results on Unix versus Windows? Pin
Dominik Reichl27-Nov-03 1:19
memberDominik Reichl27-Nov-03 1:19 
GeneralSHA-1 implementation, bit oriented ot byte oriented Pin
Rashad26-Nov-03 10:08
memberRashad26-Nov-03 10:08 
GeneralRe: SHA-1 implementation, bit oriented ot byte oriented Pin
Dominik Reichl27-Nov-03 1:12
memberDominik Reichl27-Nov-03 1:12 
GeneralDLL Package Pin
Anonymous8-Nov-03 3:31
memberAnonymous8-Nov-03 3:31 
GeneralRe: DLL Package Pin
Dominik Reichl8-Nov-03 4:41
memberDominik Reichl8-Nov-03 4:41 
QuestionWhat to do with a hash? Pin
Matt Newman23-Aug-03 4:28
memberMatt Newman23-Aug-03 4:28 
AnswerRe: What to do with a hash? Pin
Dominik Reichl23-Aug-03 6:54
memberDominik Reichl23-Aug-03 6:54 
First example: the Password Safe
Assume you have to develop an application that uses passwords for something. These passwords have to be saved to disk. For example consider a "Password Safe" that allows you to store other passwords. This password safe has a master key which allows a user to open his database.
Now, how is the master password stored on disk? If it is stored as plain text, everyone can read it. If you encrypt it with a fixed key (for example a hard-coded key or a key which is stored somewhere else on the computer), an attacker can search the key with which the master key has been encrypted (for example analyzing the executable file).
There comes the use of one-way functions: you hash the master password and store its hash on disk. The normal user enters his master password, this password gets hashed and is compared with the one stored on disk. If they are the same, the user is authenticated.
If an attacker now wants to break this system, he has to compute the master key from the hash. But SHA-1 is a one-way hash function, what means that the attacker cannot get the master password from the hash. Theoretically it is possible using brute-force, but in the real world it is impossible. He would have to calculate about 2^80 random messages to find another key that hashes to the same value (this is called "birthday attack"). He simply doesn't have the computing power to accomplish this.

For example Linux can store its login passwords hashed with MD5 (MD5 is a 128-bit one-way hash function, so a birthday attack "only" requires about 2^64 random texts to be hashed, SHA-1 would be better). This way the system is even secure if an attacker gets the file where the passwords are stored in ("shadow" normally).

Second example: Message Authentication Codes (MACs)
Another example is the usage of one-way functions as Message Authentication Codes (MACs). MACs are hash values that are additionally "encrypted" with a key. The final hash value is the hash of the message and the key.
And what's the use of it? Well, think of a program that hashes security-critical files on your disk and stores the hashes in a database. You enter the master key and compute the MACs of all files. Later, you enter the master key and calculate the hashes of the files again and compare them with the database. If all hashes are the same, none of the files has been changed/manipulated.
Now comes an attacker (for example a computer virus). What shall the virus do? Computing the hash values of the files is easy, but how can it compute the MAC? It's the same as in the example above: he would either have to break the SHA-1 function (which hasn't been broken today yet) or find another file that hashes to the same file (2^80 files, birthday attack).
If you would have used a hash function that isn't one-way, for example CRC (doesn't matter of what size, let's consider CRC-256), the attacker could compute another message very easily that hashes to the same value.

Hope you have an idea now what one-way hash functions are for Big Grin | :-D

-Dominik



_outp(0x64, 0xAD);
and
__asm mov al, 0xAD __asm out 0x64, al
do the same... but what do they do?? Wink | ;)
(doesn't work on NT)

GeneralRe: What to do with a hash? Pin
Matt Newman23-Aug-03 7:10
memberMatt Newman23-Aug-03 7:10 
GeneralBug on function "ReportHash" Pin
crowe12-Aug-03 3:35
membercrowe12-Aug-03 3:35 
GeneralRe: Bug on function "ReportHash" Pin
Dominik Reichl16-Aug-03 8:08
memberDominik Reichl16-Aug-03 8:08 
GeneralRe: Bug on function "ReportHash" [Bug fixed] Pin
Dominik Reichl21-Aug-03 20:33
memberDominik Reichl21-Aug-03 20:33 
GeneralPadding Pin
schepdawg10-Jul-03 9:00
memberschepdawg10-Jul-03 9:00 
GeneralRe: Padding Pin
Dominik Reichl10-Jul-03 9:03
memberDominik Reichl10-Jul-03 9:03 
Questionhow to output the test report and T values? Pin
myde30010-Apr-03 20:28
membermyde30010-Apr-03 20:28 
AnswerRe: how to output the test report and T values? Pin
Dominik Reichl11-Apr-03 6:49
memberDominik Reichl11-Apr-03 6:49 
GeneralRe: how to output the test report and T values? Pin
myde30011-Apr-03 16:15
membermyde30011-Apr-03 16:15 
GeneralRe: how to output the test report and T values? Pin
Dominik Reichl11-Apr-03 22:17
memberDominik Reichl11-Apr-03 22:17 
Questionwhy not code into key-value mode ? Pin
flyxia23-Mar-03 15:54
memberflyxia23-Mar-03 15:54 
GeneralCSHA1 not reentrant Pin
DrusTheAxe16-Mar-03 13:12
memberDrusTheAxe16-Mar-03 13:12 
GeneralRe: CSHA1 not reentrant Pin
17-Mar-03 0:42
suss17-Mar-03 0:42 
GeneralRe: CSHA1 not reentrant Pin
Dominik Reichl4-Jun-03 2:45
memberDominik Reichl4-Jun-03 2:45 
GeneralRe: CSHA1 not reentrant Pin
Christopher Smith9-Jun-03 15:11
memberChristopher Smith9-Jun-03 15:11 
GeneralJavascript version here Pin
dswigger3-Mar-03 9:40
memberdswigger3-Mar-03 9:40 
GeneralMultiple Use Pin
Amit Dey3-Dec-02 6:47
memberAmit Dey3-Dec-02 6:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Article
Posted 19 Jun 2002

Stats

583.9K views
15.4K downloads
179 bookmarked