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 // 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 // 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() const char* CRC32::getHash()
{ {
// convert hash to string // convert hash to string
@ -390,12 +390,21 @@ const char* CRC32::getHash()
hashBuffer[5] = dec2hex[(m_hash >> 8) & 15]; hashBuffer[5] = dec2hex[(m_hash >> 8) & 15];
hashBuffer[6] = dec2hex[(m_hash >> 4) & 15]; hashBuffer[6] = dec2hex[(m_hash >> 4) & 15];
hashBuffer[7] = dec2hex[ m_hash & 15]; hashBuffer[7] = dec2hex[ m_hash & 15];
// zero-terminated string // zero-terminated string
hashBuffer[8] = 0; hashBuffer[8] = 0;
// convert to std::string // 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 // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //
@ -20,10 +20,18 @@
while (more data available) while (more data available)
crc32.add(pointer to fresh data, number of new bytes); crc32.add(pointer to fresh data, number of new bytes);
std::string myHash3 = crc32.getHash(); 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 class CRC32 //: public Hash
{ {
public: public:
/// hash is 4 bytes long
enum { HashBytes = 4 };
/// same as reset() /// same as reset()
CRC32(); CRC32();
@ -35,8 +43,10 @@ public:
/// add arbitrary number of bytes /// add arbitrary number of bytes
void add(const void* data, size_t numBytes); 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(); const char* getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart /// restart
void reset(); void reset();

View File

@ -1,6 +1,6 @@
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// keccak.cpp // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //
@ -18,10 +18,10 @@ Keccak::Keccak(Bits bits)
/// same as reset() /// same as reset()
void Keccak::changeBits(Bits bits) void Keccak::changeBits(Bits bits)
{ {
m_blockSize = (200 - 2 * (bits / 8)); m_blockSize = (200 - 2 * (bits / 8));
m_bits = bits; m_bits = bits;
reset(); reset();
} }
/// restart /// restart
@ -225,11 +225,11 @@ void Keccak::processBuffer()
// add a "1" byte // add a "1" byte
m_buffer[offset++] = 1; m_buffer[offset++] = 1;
// fill with zeros // fill with zeros
while (offset < blockSize - 1) while (offset < blockSize)
m_buffer[offset++] = 0; m_buffer[offset++] = 0;
// and add a single set bit // and add a single set bit
m_buffer[blockSize - 1] = 0x80; m_buffer[blockSize - 1] |= 0x80;
processBlock(m_buffer); processBlock(m_buffer);
} }
@ -257,8 +257,21 @@ const char* Keccak::getHash()
result[written++] = dec2hex[oneByte >> 4]; result[written++] = dec2hex[oneByte >> 4];
result[written++] = dec2hex[oneByte & 15]; 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; result[written] = 0;
return (const char *)result; return const_cast<const char *>(result);
} }

View File

@ -1,6 +1,6 @@
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// keccak.h // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //

View File

@ -1,6 +1,6 @@
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// md5.cpp // 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 // 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() const char* MD5::getHash()
{ {
// convert hash to string // compute hash (as raw bytes)
static const char dec2hex[16+1] = "0123456789abcdef"; 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 // save old hash if buffer is partially filled
uint32_t oldHash[4]; uint32_t oldHash[HashValues];
oldHash[0] = m_hash[0]; for (int i = 0; i < HashValues; i++)
oldHash[1] = m_hash[1]; oldHash[i] = m_hash[i];
oldHash[2] = m_hash[2];
oldHash[3] = m_hash[3];
// process remaining bytes // process remaining bytes
processBuffer(); processBuffer();
// create hash string unsigned char* current = buffer;
static char hashBuffer[4*8+1]; 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]; // restore old hash
hashBuffer[ 1] = dec2hex[ m_hash[0] & 15]; m_hash[i] = oldHash[i];
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;
} }

View File

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

View File

@ -1,6 +1,6 @@
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// sha1.cpp // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //
@ -239,14 +239,14 @@ void SHA1::processBuffer()
addLength = extra + paddedLength - BlockSize; addLength = extra + paddedLength - BlockSize;
// must be big endian // must be big endian
*addLength++ = (msgBits >> 56) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
*addLength++ = (msgBits >> 48) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
*addLength++ = (msgBits >> 40) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
*addLength++ = (msgBits >> 32) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
*addLength++ = (msgBits >> 24) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
*addLength++ = (msgBits >> 16) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
*addLength++ = (msgBits >> 8) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
*addLength = msgBits & 0xFF; *addLength = (unsigned char)( msgBits & 0xFF);
// process blocks // process blocks
processBlock(m_buffer); 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() const char* SHA1::getHash()
{ {
// convert hash to string // compute hash (as raw bytes)
static const char dec2hex[16+1] = "0123456789abcdef"; 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 // save old hash if buffer is partially filled
uint32_t oldHash[HashValues]; uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++) for (int i = 0; i < HashValues; i++)
@ -270,28 +288,17 @@ const char* SHA1::getHash()
// process remaining bytes // process remaining bytes
processBuffer(); processBuffer();
// create hash string unsigned char* current = buffer;
static char hashBuffer[HashValues*8+1];
size_t offset = 0;
for (int i = 0; i < HashValues; i++) for (int i = 0; i < HashValues; i++)
{ {
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 28) & 15]; *current++ = (m_hash[i] >> 24) & 0xFF;
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 24) & 15]; *current++ = (m_hash[i] >> 16) & 0xFF;
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 20) & 15]; *current++ = (m_hash[i] >> 8) & 0xFF;
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 16) & 15]; *current++ = m_hash[i] & 0xFF;
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];
// restore old hash // restore old hash
m_hash[i] = oldHash[i]; 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 // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //
@ -24,6 +24,9 @@
class SHA1 //: public Hash class SHA1 //: public Hash
{ {
public: public:
/// split into 64 byte blocks (=> 512 bits), hash is 20 bytes long
enum { BlockSize = 512 / 8, HashBytes = 20 };
/// same as reset() /// same as reset()
SHA1(); SHA1();
@ -35,8 +38,10 @@ public:
/// add arbitrary number of bytes /// add arbitrary number of bytes
void add(const void* data, size_t numBytes); 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(); const char* getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart /// restart
void reset(); void reset();
@ -47,15 +52,14 @@ private:
/// process everything left in the internal buffer /// process everything left in the internal buffer
void processBuffer(); void processBuffer();
/// split into 64 byte blocks (=> 512 bits)
enum { BlockSize = 512 / 8, HashValues = 5 };
/// size of processed data in bytes /// size of processed data in bytes
uint64_t m_numBytes; uint64_t m_numBytes;
/// valid bytes in m_buffer /// valid bytes in m_buffer
size_t m_bufferSize; size_t m_bufferSize;
/// bytes not processed yet /// bytes not processed yet
uint8_t m_buffer[BlockSize]; uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers /// hash, stored as integers
uint32_t m_hash[HashValues]; uint32_t m_hash[HashValues];
}; };

View File

@ -1,6 +1,6 @@
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// sha256.cpp // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //
@ -325,14 +325,14 @@ void SHA256::processBuffer()
addLength = extra + paddedLength - BlockSize; addLength = extra + paddedLength - BlockSize;
// must be big endian // must be big endian
*addLength++ = (msgBits >> 56) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
*addLength++ = (msgBits >> 48) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
*addLength++ = (msgBits >> 40) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
*addLength++ = (msgBits >> 32) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
*addLength++ = (msgBits >> 24) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
*addLength++ = (msgBits >> 16) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
*addLength++ = (msgBits >> 8) & 0xFF; *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
*addLength = msgBits & 0xFF; *addLength = (unsigned char)( msgBits & 0xFF);
// process blocks // process blocks
processBlock(m_buffer); 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() const char* SHA256::getHash()
{ {
// convert hash to string // compute hash (as raw bytes)
static const char dec2hex[16+1] = "0123456789abcdef"; 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 // save old hash if buffer is partially filled
uint32_t oldHash[HashValues]; uint32_t oldHash[HashValues];
for (int i = 0; i < HashValues; i++) for (int i = 0; i < HashValues; i++)
@ -356,28 +374,17 @@ const char* SHA256::getHash()
// process remaining bytes // process remaining bytes
processBuffer(); processBuffer();
// create hash string unsigned char* current = buffer;
static char hashBuffer[HashValues*8+1];
size_t offset = 0;
for (int i = 0; i < HashValues; i++) for (int i = 0; i < HashValues; i++)
{ {
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 28) & 15]; *current++ = (m_hash[i] >> 24) & 0xFF;
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 24) & 15]; *current++ = (m_hash[i] >> 16) & 0xFF;
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 20) & 15]; *current++ = (m_hash[i] >> 8) & 0xFF;
hashBuffer[offset++] = dec2hex[(m_hash[i] >> 16) & 15]; *current++ = m_hash[i] & 0xFF;
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];
// restore old hash // restore old hash
m_hash[i] = oldHash[i]; 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 // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //
@ -24,6 +24,9 @@
class SHA256 //: public Hash class SHA256 //: public Hash
{ {
public: public:
/// split into 64 byte blocks (=> 512 bits), hash is 32 bytes long
enum { BlockSize = 512 / 8, HashBytes = 32 };
/// same as reset() /// same as reset()
SHA256(); SHA256();
@ -35,8 +38,10 @@ public:
/// add arbitrary number of bytes /// add arbitrary number of bytes
void add(const void* data, size_t numBytes); 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(); const char* getHash();
/// return latest hash as bytes
void getHash(unsigned char buffer[HashBytes]);
/// restart /// restart
void reset(); void reset();
@ -47,15 +52,14 @@ private:
/// process everything left in the internal buffer /// process everything left in the internal buffer
void processBuffer(); void processBuffer();
/// split into 64 byte blocks (=> 512 bits)
enum { BlockSize = 512 / 8, HashValues = 8 };
/// size of processed data in bytes /// size of processed data in bytes
uint64_t m_numBytes; uint64_t m_numBytes;
/// valid bytes in m_buffer /// valid bytes in m_buffer
size_t m_bufferSize; size_t m_bufferSize;
/// bytes not processed yet /// bytes not processed yet
uint8_t m_buffer[BlockSize]; uint8_t m_buffer[BlockSize];
enum { HashValues = HashBytes / 4 };
/// hash, stored as integers /// hash, stored as integers
uint32_t m_hash[8]; uint32_t m_hash[HashValues];
}; };

View File

@ -1,6 +1,6 @@
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// sha3.cpp // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //
@ -24,7 +24,6 @@ void SHA3::changeBits(Bits bits)
reset(); reset();
} }
/// restart /// restart
void SHA3::reset() void SHA3::reset()
{ {
@ -177,6 +176,7 @@ void SHA3::add(const void* data, size_t numBytes)
{ {
const uint8_t* current = (const uint8_t*) data; const uint8_t* current = (const uint8_t*) data;
// copy data to buffer
if (m_bufferSize > 0) if (m_bufferSize > 0)
{ {
while (numBytes > 0 && m_bufferSize < m_blockSize) 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 /// process everything left in the internal buffer
void SHA3::processBuffer() void SHA3::processBuffer()
{ {
unsigned int blockSize = 200 - 2 * (m_bits / 8);
// add padding // add padding
size_t offset = m_bufferSize; size_t offset = m_bufferSize;
// add a "1" byte // add a "1" byte
m_buffer[offset++] = 0x06; m_buffer[offset++] = 0x06;
// fill with zeros // fill with zeros
while (offset < blockSize - 1) while (offset < m_blockSize)
m_buffer[offset++] = 0; m_buffer[offset++] = 0;
// and add a single set bit // and add a single set bit
m_buffer[blockSize - 1] = 0x80; m_buffer[offset - 1] |= 0x80;
processBlock(m_buffer); processBlock(m_buffer);
} }
@ -255,11 +253,24 @@ const char* SHA3::getHash()
{ {
// convert a byte to hex // convert a byte to hex
unsigned char oneByte = (unsigned char) (m_hash[i] >> (8 * j)); unsigned char oneByte = (unsigned char) (m_hash[i] >> (8 * j));
result[written++]= dec2hex[oneByte >> 4]; result[written++] = dec2hex[oneByte >> 4];
result[written++]= dec2hex[oneByte & 15]; 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; result[written] = 0;
return (const char*)result; return const_cast<const char *>(result);
} }

View File

@ -1,6 +1,6 @@
// ////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////
// sha3.h // 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 // see http://create.stephan-brumme.com/disclaimer.html
// //