Update hashing library (#384)

This commit is contained in:
Karol Szuster 2016-08-22 11:21:46 +02:00 committed by Vincent Herbet
parent e24b9548d4
commit ea43a61094
12 changed files with 200 additions and 154 deletions

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// crc32.cpp
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -374,7 +374,7 @@ void CRC32::add(const void* data, size_t numBytes)
}
/// return latest hash as 16 hex characters
/// return latest hash as 8 hex characters
const char* CRC32::getHash()
{
// convert hash to string
@ -390,12 +390,21 @@ const char* CRC32::getHash()
hashBuffer[5] = dec2hex[(m_hash >> 8) & 15];
hashBuffer[6] = dec2hex[(m_hash >> 4) & 15];
hashBuffer[7] = dec2hex[ m_hash & 15];
// zero-terminated string
hashBuffer[8] = 0;
// convert to std::string
return (const char *)hashBuffer;
return const_cast<const char *>(hashBuffer);
}
/// return latest hash as bytes
void CRC32::getHash(unsigned char buffer[CRC32::HashBytes])
{
buffer[0] = (m_hash >> 24) & 0xFF;
buffer[1] = (m_hash >> 16) & 0xFF;
buffer[2] = (m_hash >> 8) & 0xFF;
buffer[3] = m_hash & 0xFF;
}

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// crc32.h
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -20,10 +20,18 @@
while (more data available)
crc32.add(pointer to fresh data, number of new bytes);
std::string myHash3 = crc32.getHash();
Note:
You can find code for the faster Slicing-by-16 algorithm on my website, too:
http://create.stephan-brumme.com/crc32/
Its unrolled version is about twice as fast but its look-up table doubled in size as well.
*/
class CRC32 //: public Hash
{
public:
/// hash is 4 bytes long
enum { HashBytes = 4 };
/// same as reset()
CRC32();
@ -35,8 +43,10 @@ public:
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 16 hex characters
/// return latest hash as 8 hex characters
const char* getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// keccak.cpp
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -18,10 +18,10 @@ Keccak::Keccak(Bits bits)
/// same as reset()
void Keccak::changeBits(Bits bits)
{
m_blockSize = (200 - 2 * (bits / 8));
m_bits = bits;
m_blockSize = (200 - 2 * (bits / 8));
m_bits = bits;
reset();
reset();
}
/// restart
@ -225,11 +225,11 @@ void Keccak::processBuffer()
// add a "1" byte
m_buffer[offset++] = 1;
// fill with zeros
while (offset < blockSize - 1)
while (offset < blockSize)
m_buffer[offset++] = 0;
// and add a single set bit
m_buffer[blockSize - 1] = 0x80;
m_buffer[blockSize - 1] |= 0x80;
processBlock(m_buffer);
}
@ -257,8 +257,21 @@ const char* Keccak::getHash()
result[written++] = dec2hex[oneByte >> 4];
result[written++] = dec2hex[oneByte & 15];
}
// Keccak224's last entry in m_hash provides only 32 bits instead of 64 bits
unsigned int remainder = m_bits - hashLength * 64;
unsigned int processed = 0;
while (processed < remainder)
{
// convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[hashLength] >> processed);
result[written++] = dec2hex[oneByte >> 4];
result[written++] = dec2hex[oneByte & 15];
processed += 8;
}
result[written] = 0;
return (const char *)result;
return const_cast<const char *>(result);
}

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// keccak.h
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// md5.cpp
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -311,72 +311,49 @@ void MD5::processBuffer()
}
/// return latest hash as 16 hex characters
/// return latest hash as 32 hex characters
const char* MD5::getHash()
{
// convert hash to string
static const char dec2hex[16+1] = "0123456789abcdef";
// compute hash (as raw bytes)
unsigned char rawHash[HashBytes];
getHash(rawHash);
// convert to hex string
static char result[32+1];
size_t written = 0;
for (int i = 0; i < HashBytes; i++)
{
static const char dec2hex[16+1] = "0123456789abcdef";
result[written++] = dec2hex[(rawHash[i] >> 4) & 15];
result[written++] = dec2hex[ rawHash[i] & 15];
}
result[written] = 0;
return const_cast<const char *>(result);
}
/// return latest hash as bytes
void MD5::getHash(unsigned char buffer[MD5::HashBytes])
{
// save old hash if buffer is partially filled
uint32_t oldHash[4];
oldHash[0] = m_hash[0];
oldHash[1] = m_hash[1];
oldHash[2] = m_hash[2];
oldHash[3] = m_hash[3];
uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++)
oldHash[i] = m_hash[i];
// process remaining bytes
processBuffer();
// create hash string
static char hashBuffer[4*8+1];
unsigned char* current = buffer;
for (int i = 0; i < HashValues; i++)
{
*current++ = m_hash[i] & 0xFF;
*current++ = (m_hash[i] >> 8) & 0xFF;
*current++ = (m_hash[i] >> 16) & 0xFF;
*current++ = (m_hash[i] >> 24) & 0xFF;
hashBuffer[ 0] = dec2hex[(m_hash[0] >> 4) & 15];
hashBuffer[ 1] = dec2hex[ m_hash[0] & 15];
hashBuffer[ 2] = dec2hex[(m_hash[0] >> 12) & 15];
hashBuffer[ 3] = dec2hex[(m_hash[0] >> 8) & 15];
hashBuffer[ 4] = dec2hex[(m_hash[0] >> 20) & 15];
hashBuffer[ 5] = dec2hex[(m_hash[0] >> 16) & 15];
hashBuffer[ 6] = dec2hex[ m_hash[0] >> 28 ];
hashBuffer[ 7] = dec2hex[(m_hash[0] >> 24) & 15];
hashBuffer[ 8] = dec2hex[(m_hash[1] >> 4) & 15];
hashBuffer[ 9] = dec2hex[ m_hash[1] & 15];
hashBuffer[10] = dec2hex[(m_hash[1] >> 12) & 15];
hashBuffer[11] = dec2hex[(m_hash[1] >> 8) & 15];
hashBuffer[12] = dec2hex[(m_hash[1] >> 20) & 15];
hashBuffer[13] = dec2hex[(m_hash[1] >> 16) & 15];
hashBuffer[14] = dec2hex[ m_hash[1] >> 28 ];
hashBuffer[15] = dec2hex[(m_hash[1] >> 24) & 15];
hashBuffer[16] = dec2hex[(m_hash[2] >> 4) & 15];
hashBuffer[17] = dec2hex[ m_hash[2] & 15];
hashBuffer[18] = dec2hex[(m_hash[2] >> 12) & 15];
hashBuffer[19] = dec2hex[(m_hash[2] >> 8) & 15];
hashBuffer[20] = dec2hex[(m_hash[2] >> 20) & 15];
hashBuffer[21] = dec2hex[(m_hash[2] >> 16) & 15];
hashBuffer[22] = dec2hex[ m_hash[2] >> 28 ];
hashBuffer[23] = dec2hex[(m_hash[2] >> 24) & 15];
hashBuffer[24] = dec2hex[(m_hash[3] >> 4) & 15];
hashBuffer[25] = dec2hex[ m_hash[3] & 15];
hashBuffer[26] = dec2hex[(m_hash[3] >> 12) & 15];
hashBuffer[27] = dec2hex[(m_hash[3] >> 8) & 15];
hashBuffer[28] = dec2hex[(m_hash[3] >> 20) & 15];
hashBuffer[29] = dec2hex[(m_hash[3] >> 16) & 15];
hashBuffer[30] = dec2hex[ m_hash[3] >> 28 ];
hashBuffer[31] = dec2hex[(m_hash[3] >> 24) & 15];
// zero-terminated string
hashBuffer[32] = 0;
// restore old hash
m_hash[0] = oldHash[0];
m_hash[1] = oldHash[1];
m_hash[2] = oldHash[2];
m_hash[3] = oldHash[3];
// convert to std::string
return (const char*)hashBuffer;
// restore old hash
m_hash[i] = oldHash[i];
}
}

View File

@ -24,6 +24,9 @@
class MD5 //: public Hash
{
public:
/// split into 64 byte blocks (=> 512 bits), hash is 16 bytes long
enum { BlockSize = 512 / 8, HashBytes = 16 };
/// same as reset()
MD5();
@ -35,8 +38,10 @@ public:
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 16 hex characters
/// return latest hash as 32 hex characters
const char* getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();
@ -47,15 +52,14 @@ private:
/// process everything left in the internal buffer
void processBuffer();
/// split into 64 byte blocks (=> 512 bits)
enum { BlockSize = 512 / 8 };
/// size of processed data in bytes
uint64_t m_numBytes;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers
uint32_t m_hash[4];
uint32_t m_hash[HashValues];
};

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// sha1.cpp
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -239,14 +239,14 @@ void SHA1::processBuffer()
addLength = extra + paddedLength - BlockSize;
// must be big endian
*addLength++ = (msgBits >> 56) & 0xFF;
*addLength++ = (msgBits >> 48) & 0xFF;
*addLength++ = (msgBits >> 40) & 0xFF;
*addLength++ = (msgBits >> 32) & 0xFF;
*addLength++ = (msgBits >> 24) & 0xFF;
*addLength++ = (msgBits >> 16) & 0xFF;
*addLength++ = (msgBits >> 8) & 0xFF;
*addLength = msgBits & 0xFF;
*addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
*addLength = (unsigned char)( msgBits & 0xFF);
// process blocks
processBlock(m_buffer);
@ -256,12 +256,30 @@ void SHA1::processBuffer()
}
/// return latest hash as 16 hex characters
/// return latest hash as 40 hex characters
const char* SHA1::getHash()
{
// convert hash to string
static const char dec2hex[16+1] = "0123456789abcdef";
// compute hash (as raw bytes)
unsigned char rawHash[HashBytes];
getHash(rawHash);
// convert to hex string
static char result[40+1];
size_t written = 0;
for (int i = 0; i < HashBytes; i++)
{
static const char dec2hex[16+1] = "0123456789abcdef";
result[written++] = dec2hex[(rawHash[i] >> 4) & 15];
result[written++] = dec2hex[ rawHash[i] & 15];
}
result[written] = 0;
return const_cast<const char *>(result);
}
/// return latest hash as bytes
void SHA1::getHash(unsigned char buffer[SHA1::HashBytes])
{
// save old hash if buffer is partially filled
uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++)
@ -270,28 +288,17 @@ const char* SHA1::getHash()
// process remaining bytes
processBuffer();
// create hash string
static char hashBuffer[HashValues*8+1];
size_t offset = 0;
unsigned char* current = buffer;
for (int i = 0; i < HashValues; i++)
{
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 28) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 24) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 20) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 16) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 12) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 8) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 4) & 15];
hashBuffer[offset++] = dec2hex[ m_hash[i] & 15];
*current++ = (m_hash[i] >> 24) & 0xFF;
*current++ = (m_hash[i] >> 16) & 0xFF;
*current++ = (m_hash[i] >> 8) & 0xFF;
*current++ = m_hash[i] & 0xFF;
// restore old hash
m_hash[i] = oldHash[i];
}
// zero-terminated string
hashBuffer[offset] = 0;
// convert to std::string
return (const char *)hashBuffer;
}

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// sha1.h
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -24,6 +24,9 @@
class SHA1 //: public Hash
{
public:
/// split into 64 byte blocks (=> 512 bits), hash is 20 bytes long
enum { BlockSize = 512 / 8, HashBytes = 20 };
/// same as reset()
SHA1();
@ -35,8 +38,10 @@ public:
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 16 hex characters
/// return latest hash as 40 hex characters
const char* getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();
@ -47,15 +52,14 @@ private:
/// process everything left in the internal buffer
void processBuffer();
/// split into 64 byte blocks (=> 512 bits)
enum { BlockSize = 512 / 8, HashValues = 5 };
/// size of processed data in bytes
uint64_t m_numBytes;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers
uint32_t m_hash[HashValues];
};

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// sha256.cpp
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -325,14 +325,14 @@ void SHA256::processBuffer()
addLength = extra + paddedLength - BlockSize;
// must be big endian
*addLength++ = (msgBits >> 56) & 0xFF;
*addLength++ = (msgBits >> 48) & 0xFF;
*addLength++ = (msgBits >> 40) & 0xFF;
*addLength++ = (msgBits >> 32) & 0xFF;
*addLength++ = (msgBits >> 24) & 0xFF;
*addLength++ = (msgBits >> 16) & 0xFF;
*addLength++ = (msgBits >> 8) & 0xFF;
*addLength = msgBits & 0xFF;
*addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
*addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
*addLength = (unsigned char)( msgBits & 0xFF);
// process blocks
processBlock(m_buffer);
@ -342,12 +342,30 @@ void SHA256::processBuffer()
}
/// return latest hash as 16 hex characters
/// return latest hash as 64 hex characters
const char* SHA256::getHash()
{
// convert hash to string
static const char dec2hex[16+1] = "0123456789abcdef";
// compute hash (as raw bytes)
unsigned char rawHash[HashBytes];
getHash(rawHash);
// convert to hex string
static char result[64+1];
size_t written = 0;
for (int i = 0; i < HashBytes; i++)
{
static const char dec2hex[16+1] = "0123456789abcdef";
result[written++] = dec2hex[(rawHash[i] >> 4) & 15];
result[written++] = dec2hex[ rawHash[i] & 15];
}
result[written] = 0;
return const_cast<const char *>(result);
}
/// return latest hash as bytes
void SHA256::getHash(unsigned char buffer[SHA256::HashBytes])
{
// save old hash if buffer is partially filled
uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++)
@ -356,28 +374,17 @@ const char* SHA256::getHash()
// process remaining bytes
processBuffer();
// create hash string
static char hashBuffer[HashValues*8+1];
size_t offset = 0;
unsigned char* current = buffer;
for (int i = 0; i < HashValues; i++)
{
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 28) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 24) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 20) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 16) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 12) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 8) & 15];
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 4) & 15];
hashBuffer[offset++] = dec2hex[ m_hash[i] & 15];
*current++ = (m_hash[i] >> 24) & 0xFF;
*current++ = (m_hash[i] >> 16) & 0xFF;
*current++ = (m_hash[i] >> 8) & 0xFF;
*current++ = m_hash[i] & 0xFF;
// restore old hash
m_hash[i] = oldHash[i];
}
// zero-terminated string
hashBuffer[offset] = 0;
// convert to std::string
return (const char *)hashBuffer;
}

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// sha256.h
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -24,6 +24,9 @@
class SHA256 //: public Hash
{
public:
/// split into 64 byte blocks (=> 512 bits), hash is 32 bytes long
enum { BlockSize = 512 / 8, HashBytes = 32 };
/// same as reset()
SHA256();
@ -35,8 +38,10 @@ public:
/// add arbitrary number of bytes
void add(const void* data, size_t numBytes);
/// return latest hash as 16 hex characters
/// return latest hash as 64 hex characters
const char* getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart
void reset();
@ -47,15 +52,14 @@ private:
/// process everything left in the internal buffer
void processBuffer();
/// split into 64 byte blocks (=> 512 bits)
enum { BlockSize = 512 / 8, HashValues = 8 };
/// size of processed data in bytes
uint64_t m_numBytes;
/// valid bytes in m_buffer
size_t m_bufferSize;
/// bytes not processed yet
uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers
uint32_t m_hash[8];
uint32_t m_hash[HashValues];
};

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// sha3.cpp
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//
@ -24,7 +24,6 @@ void SHA3::changeBits(Bits bits)
reset();
}
/// restart
void SHA3::reset()
{
@ -177,6 +176,7 @@ void SHA3::add(const void* data, size_t numBytes)
{
const uint8_t* current = (const uint8_t*) data;
// copy data to buffer
if (m_bufferSize > 0)
{
while (numBytes > 0 && m_bufferSize < m_blockSize)
@ -219,18 +219,16 @@ void SHA3::add(const void* data, size_t numBytes)
/// process everything left in the internal buffer
void SHA3::processBuffer()
{
unsigned int blockSize = 200 - 2 * (m_bits / 8);
// add padding
size_t offset = m_bufferSize;
// add a "1" byte
m_buffer[offset++] = 0x06;
// fill with zeros
while (offset < blockSize - 1)
while (offset < m_blockSize)
m_buffer[offset++] = 0;
// and add a single set bit
m_buffer[blockSize - 1] = 0x80;
m_buffer[offset - 1] |= 0x80;
processBlock(m_buffer);
}
@ -255,11 +253,24 @@ const char* SHA3::getHash()
{
// convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[i] >> (8 * j));
result[written++]= dec2hex[oneByte >> 4];
result[written++]= dec2hex[oneByte & 15];
result[written++] = dec2hex[oneByte >> 4];
result[written++] = dec2hex[oneByte & 15];
}
// SHA3-224's last entry in m_hash provides only 32 bits instead of 64 bits
unsigned int remainder = m_bits - hashLength * 64;
unsigned int processed = 0;
while (processed < remainder)
{
// convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[hashLength] >> processed);
result[written++] = dec2hex[oneByte >> 4];
result[written++] = dec2hex[oneByte & 15];
processed += 8;
}
result[written] = 0;
return (const char*)result;
return const_cast<const char *>(result);
}

View File

@ -1,6 +1,6 @@
// //////////////////////////////////////////////////////////
// sha3.h
// Copyright (c) 2014 Stephan Brumme. All rights reserved.
// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
// see http://create.stephan-brumme.com/disclaimer.html
//