mirror of
https://github.com/rehlds/reunion.git
synced 2025-03-10 20:50:14 +03:00
191 lines
7.8 KiB
C++
191 lines
7.8 KiB
C++
/*************************************************************
|
|
|
|
This program is a C++ implementation of the Secure Hash Algorithm (SHA)
|
|
that handles the variations from the original 160 bit to 224, 256, 384
|
|
and 512 bit. The program is intended to be platform independant and
|
|
has been tested on little-endian (Intel) and big-endian (Sun) machines.
|
|
|
|
This program is based on a C version written by Aaron D. Gifford
|
|
(as of 11/22/2004 his code could be found at http://www.adg.us/computers/sha.html).
|
|
Attempts to contact him were unsuccessful. I greatly condensed his version
|
|
and shared as much code and data as I could think of. I also inlined
|
|
a lot of code that were macros in his version. My version detects
|
|
endian-ness automatically and adjusts itself accordingly. This program
|
|
has been tested with Visual C++ versions 6/7 and Dev-C++ on Windows,
|
|
g++ on Linux and CC on Solaris (g++ on Solaris gave a bus error).
|
|
|
|
While I did make half-hearted attempts to optimize as I went along
|
|
(testing on Wintel), any serious attempt at fast implementation is
|
|
probably going to need to make use of in-lined assembly which is not
|
|
very portable.
|
|
|
|
The goal of this implementation is ease of use. As much as possible
|
|
I tried to hide implementation details while making it trivial to change
|
|
the size of the hash and get the results. The string and charactar
|
|
array value of the hash is supplied as human-readable hex; the raw value
|
|
can also be obtained.
|
|
|
|
If you use this implementation somewhere I would like to be credited
|
|
with my work (a link to my page below is fine). I add no license
|
|
restriction beyond any that is made by the original author. This
|
|
code comes with no warrenty expressed or implied, use at your own
|
|
risk!
|
|
|
|
Keith Oxenrider
|
|
koxenrider[at]sol[dash]biotech[dot]com
|
|
The latest version of this code should be available via the page
|
|
sol-biotech.com/code.
|
|
|
|
*************************************************************/
|
|
|
|
#ifndef __SHA2C_H__
|
|
#define __SHA2C_H__
|
|
|
|
#include "reunion_shared.h"
|
|
#include <string>
|
|
#include <iostream>
|
|
|
|
// NOTE: You may need to define things by hand for your system:
|
|
typedef unsigned char sha_byte; // Exactly 1 byte
|
|
typedef unsigned int sha_word32; // Exactly 4 bytes
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
typedef ULONG64 sha_word64; // 8-bytes (64-bits)
|
|
#else
|
|
typedef unsigned long long sha_word64; // 8-bytes (64-bits)
|
|
#endif
|
|
|
|
// Digest lengths for SHA-1/224/256/384/512
|
|
const sha_word32 SHA1_DIGESTC_LENGTH = 20;
|
|
const sha_word32 SHA1_DIGESTC_STRING_LENGTH = (SHA1_DIGESTC_LENGTH * 2 + 1);
|
|
const sha_word32 SHA224_DIGESTC_LENGTH = 28;
|
|
const sha_word32 SHA224_DIGESTC_STRING_LENGTH = (SHA224_DIGESTC_LENGTH * 2 + 1);
|
|
const sha_word32 SHA256_DIGESTC_LENGTH = 32;
|
|
const sha_word32 SHA256_DIGESTC_STRING_LENGTH = (SHA256_DIGESTC_LENGTH * 2 + 1);
|
|
const sha_word32 SHA384_DIGESTC_LENGTH = 48;
|
|
const sha_word32 SHA384_DIGESTC_STRING_LENGTH = (SHA384_DIGESTC_LENGTH * 2 + 1);
|
|
const sha_word32 SHA512_DIGESTC_LENGTH = 64;
|
|
const sha_word32 SHA512_DIGESTC_STRING_LENGTH = (SHA512_DIGESTC_LENGTH * 2 + 1);
|
|
|
|
class sha2{
|
|
public:
|
|
enum SHA_TYPE {
|
|
enuSHA_NONE,
|
|
enuSHA1,
|
|
enuSHA160 = enuSHA1,
|
|
enuSHA224,
|
|
enuSHA256,
|
|
enuSHA384,
|
|
enuSHA512,
|
|
enuSHA_LAST // for easier looping during testing
|
|
};
|
|
|
|
sha2(){
|
|
m_Type = enuSHA_NONE;
|
|
m_boolIsBigEndian = true;
|
|
m_boolEnded = false;
|
|
|
|
//run-time check for endian-ness
|
|
unsigned int test = 1;
|
|
unsigned char *ptr = (unsigned char *)&test;
|
|
if (ptr[0])
|
|
m_boolIsBigEndian = false;
|
|
|
|
memset(m_chrRawHash, 0, SHA512_DIGESTC_LENGTH);
|
|
memset(m_chrHexHash, 0, SHA512_DIGESTC_STRING_LENGTH);
|
|
memset(m_digest, 0, SHA512_DIGESTC_LENGTH);
|
|
};
|
|
|
|
SHA_TYPE GetEnumType() { return m_Type; };
|
|
bool IsBigEndian() { return m_boolIsBigEndian; };
|
|
const char * GetTypeString() {
|
|
switch (m_Type) {
|
|
case sha2::enuSHA1 : return "SHA160";
|
|
case sha2::enuSHA224 : return "SHA224";
|
|
case sha2::enuSHA256 : return "SHA256";
|
|
case sha2::enuSHA384 : return "SHA384";
|
|
case sha2::enuSHA512 : return "SHA512";
|
|
default : return "Unknown!";
|
|
}
|
|
};
|
|
|
|
//call these three in order if you want to load chunk-by-chunk...
|
|
void Init(SHA_TYPE type);
|
|
|
|
void Update(const sha_byte *data, size_t len);//call as many times as needed
|
|
void End();
|
|
|
|
const char* RawHash(int &length);//NO NULL termination! size stored in 'length'
|
|
|
|
private:
|
|
SHA_TYPE m_Type;
|
|
bool m_boolEnded, m_boolIsBigEndian;
|
|
char m_chrRawHash[SHA512_DIGESTC_LENGTH], m_chrHexHash[SHA512_DIGESTC_STRING_LENGTH];
|
|
sha_byte m_digest[SHA512_DIGESTC_LENGTH];
|
|
|
|
//these are common buffers for maintaining the hash
|
|
struct SHA_CTX{
|
|
sha_byte state[sizeof(sha_word64) * 8];//maximum size
|
|
sha_word64 bitcount[2];//sha1, 224 and 256 only use the first entry
|
|
sha_byte buffer[128];
|
|
} ctx;
|
|
|
|
//** INTERNAL FUNCTION PROTOTYPES ************************************
|
|
void SHA256_Internal_Last(bool isSha1 = false);
|
|
void SHA512_Internal_Last();
|
|
|
|
void SHA1_Internal_Transform(const sha_word32 *data);
|
|
void SHA256_Internal_Transform(const sha_word32* data);
|
|
void SHA512_Internal_Transform(const sha_word64*);
|
|
|
|
void SHA32bit_Update(const sha_byte *data, size_t len, bool isSha1=false);
|
|
void SHA64bit_Update(const sha_byte *data, size_t len);
|
|
|
|
//macro replacements
|
|
inline void MEMSET_BZERO(void *p, size_t l){memset(p, 0, l);};
|
|
inline void MEMCPY_BCOPY(void *d,const void *s, size_t l) {memcpy(d, s, l);};
|
|
|
|
//For incrementally adding the unsigned 64-bit integer n to the
|
|
//unsigned 128-bit integer (represented using a two-element array of
|
|
//64-bit words):
|
|
inline void ADDINC128(sha_word64 *w, sha_word32 n) {
|
|
w[0] += (sha_word64)(n);
|
|
if (w[0] < (n)) w[1]++;
|
|
}
|
|
|
|
// Shift-right (used in SHA-256, SHA-384, and SHA-512):
|
|
inline sha_word32 SHR(sha_word32 b,sha_word32 x){return (x >> b);};
|
|
inline sha_word64 SHR(sha_word64 b,sha_word64 x){return (x >> b);};
|
|
// 32-bit Rotate-right (used in SHA-256):
|
|
inline sha_word32 ROTR32(sha_word32 b,sha_word32 x){return rotr(x, b);};
|
|
// 64-bit Rotate-right (used in SHA-384 and SHA-512):
|
|
inline sha_word64 ROTR64(sha_word64 b,sha_word64 x){return rotr64(x, b);};
|
|
// 32-bit Rotate-left (used in SHA-1):
|
|
inline sha_word32 ROTL32(sha_word32 b,sha_word32 x){return rotl(x, b);};
|
|
|
|
// Two logical functions used in SHA-1, SHA-254, SHA-256, SHA-384, and SHA-512:
|
|
inline sha_word32 Ch(sha_word32 x,sha_word32 y,sha_word32 z){return ((x & y) ^ ((~x) & z));};
|
|
inline sha_word64 Ch(sha_word64 x,sha_word64 y,sha_word64 z){return ((x & y) ^ ((~x) & z));};
|
|
inline sha_word32 Maj(sha_word32 x,sha_word32 y,sha_word32 z){return ((x & y) ^ (x & z) ^ (y & z));};
|
|
inline sha_word64 Maj(sha_word64 x,sha_word64 y,sha_word64 z){return ((x & y) ^ (x & z) ^ (y & z));};
|
|
|
|
// Function used in SHA-1:
|
|
inline sha_word32 Parity(sha_word32 x,sha_word32 y,sha_word32 z){return (x ^ y ^ z);};
|
|
|
|
// Four logical functions used in SHA-256:
|
|
inline sha_word32 Sigma0_256(sha_word32 x){return (ROTR32(2, x) ^ ROTR32(13, x) ^ ROTR32(22, x));};
|
|
inline sha_word32 Sigma1_256(sha_word32 x){return (ROTR32(6, x) ^ ROTR32(11, x) ^ ROTR32(25, x));};
|
|
inline sha_word32 sigma0_256(sha_word32 x){return (ROTR32(7, x) ^ ROTR32(18, x) ^ SHR( 3 , x));};
|
|
inline sha_word32 sigma1_256(sha_word32 x){return (ROTR32(17,x) ^ ROTR32(19, x) ^ SHR( 10, x));};
|
|
|
|
// Four of six logical functions used in SHA-384 and SHA-512:
|
|
inline sha_word64 Sigma0_512(sha_word64 x){return (ROTR64(28, x) ^ ROTR64(34, x) ^ ROTR64(39, x));};
|
|
inline sha_word64 Sigma1_512(sha_word64 x){return (ROTR64(14, x) ^ ROTR64(18, x) ^ ROTR64(41, x));};
|
|
inline sha_word64 sigma0_512(sha_word64 x){return (ROTR64( 1, x) ^ ROTR64( 8, x) ^ SHR( 7, x));};
|
|
inline sha_word64 sigma1_512(sha_word64 x){return (ROTR64(19, x) ^ ROTR64(61, x) ^ SHR( 6, x));};
|
|
|
|
inline void REVERSE32(sha_word32 w, sha_word32 &x){x = bswap(w);};
|
|
inline void REVERSE64(sha_word64 w, sha_word64 &x){x = bswap(w);};
|
|
};//end class sha2
|
|
#endif // __SHA2C_H__
|