Core: Reworked hashes

-Removed HashDigest class (replaced by ByteArray)
-Removed Hashable/Hash classes (replaced by ComputeHash function and
Hashable template struct)
-Fixed ByteArray operator<<
-Renamed File::GetHash to File::ComputeHash


Former-commit-id: cc5eaf2d4c88a556878190b8205e66713512e2d2
This commit is contained in:
Lynix
2015-11-16 14:04:39 +01:00
parent 86da939520
commit 21f223f1c7
37 changed files with 294 additions and 621 deletions

View File

@@ -3,9 +3,57 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Hash/CRC32.hpp>
#include <Nazara/Core/Hash/Fletcher16.hpp>
#include <Nazara/Core/Hash/MD5.hpp>
#include <Nazara/Core/Hash/SHA1.hpp>
#include <Nazara/Core/Hash/SHA224.hpp>
#include <Nazara/Core/Hash/SHA256.hpp>
#include <Nazara/Core/Hash/SHA384.hpp>
#include <Nazara/Core/Hash/SHA512.hpp>
#include <Nazara/Core/Hash/Whirlpool.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
AbstractHash::~AbstractHash() = default;
std::unique_ptr<AbstractHash> AbstractHash::Get(HashType type)
{
NazaraAssert(type <= HashType_Max, "Hash type value out of enum");
switch (type)
{
case HashType_Fletcher16:
return std::unique_ptr<AbstractHash>(new HashFletcher16);
case HashType_CRC32:
return std::unique_ptr<AbstractHash>(new HashCRC32);
case HashType_MD5:
return std::unique_ptr<AbstractHash>(new HashMD5);
case HashType_SHA1:
return std::unique_ptr<AbstractHash>(new HashSHA1);
case HashType_SHA224:
return std::unique_ptr<AbstractHash>(new HashSHA224);
case HashType_SHA256:
return std::unique_ptr<AbstractHash>(new HashSHA256);
case HashType_SHA384:
return std::unique_ptr<AbstractHash>(new HashSHA384);
case HashType_SHA512:
return std::unique_ptr<AbstractHash>(new HashSHA512);
case HashType_Whirlpool:
return std::unique_ptr<AbstractHash>(new HashWhirlpool);
}
NazaraInternalError("Hash type not handled (0x" + String::Number(type, 16) + ')');
return std::unique_ptr<AbstractHash>();
}
}

View File

@@ -9,16 +9,9 @@
namespace Nz
{
std::ostream& operator<<(std::ostream& out, const ByteArray& byteArray)
std::ostream& operator<<(std::ostream& out, const Nz::ByteArray& byteArray)
{
out << byteArray.ToString();
out << byteArray.ToHex();
return out;
}
bool ByteArray::FillHash(AbstractHash* hash) const
{
hash->Append(GetConstBuffer(), GetSize());
return true;
}
}

View File

@@ -7,7 +7,6 @@
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/Hash.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <cstring>
#include <memory>
@@ -631,22 +630,6 @@ namespace Nz
return FileImpl::GetLastWriteTime(NormalizePath(filePath));
}
HashDigest File::GetHash(const String& filePath, HashType hash)
{
File file(filePath);
Hash h(hash);
return h.Process(file);
}
HashDigest File::GetHash(const String& filePath, AbstractHash* hash)
{
File file(filePath);
Hash h(hash);
return h.Process(file);
}
UInt64 File::GetSize(const String& filePath)
{
if (filePath.IsEmpty())
@@ -714,32 +697,4 @@ namespace Nz
return FileImpl::Rename(NormalizePath(sourcePath), NormalizePath(targetPath));
}
bool File::FillHash(AbstractHash* hash) const
{
File file(m_filePath);
if (!file.Open(OpenMode_ReadOnly))
{
NazaraError("Unable to open file");
return false;
}
UInt64 remainingSize = file.GetSize();
char buffer[NAZARA_CORE_FILE_BUFFERSIZE];
while (remainingSize > 0)
{
unsigned int size = static_cast<unsigned int>(std::min(remainingSize, static_cast<UInt64>(NAZARA_CORE_FILE_BUFFERSIZE)));
if (file.Read(&buffer[0], sizeof(char), size) != sizeof(char)*size)
{
NazaraError("Unable to read file");
return false;
}
remainingSize -= size;
hash->Append(reinterpret_cast<UInt8*>(&buffer[0]), size);
}
return true;
} // Fermeture automatique du fichier
}

View File

@@ -1,83 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Hash.hpp>
#include <Nazara/Core/Hash/CRC32.hpp>
#include <Nazara/Core/Hash/Fletcher16.hpp>
#include <Nazara/Core/Hash/MD5.hpp>
#include <Nazara/Core/Hash/SHA1.hpp>
#include <Nazara/Core/Hash/SHA224.hpp>
#include <Nazara/Core/Hash/SHA256.hpp>
#include <Nazara/Core/Hash/SHA384.hpp>
#include <Nazara/Core/Hash/SHA512.hpp>
#include <Nazara/Core/Hash/Whirlpool.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
Hash::Hash(HashType hash)
{
switch (hash)
{
case HashType_Fletcher16:
m_impl = new HashFletcher16;
break;
case HashType_CRC32:
m_impl = new HashCRC32;
break;
case HashType_MD5:
m_impl = new HashMD5;
break;
case HashType_SHA1:
m_impl = new HashSHA1;
break;
case HashType_SHA224:
m_impl = new HashSHA224;
break;
case HashType_SHA256:
m_impl = new HashSHA256;
break;
case HashType_SHA384:
m_impl = new HashSHA384;
break;
case HashType_SHA512:
m_impl = new HashSHA512;
break;
case HashType_Whirlpool:
m_impl = new HashWhirlpool;
break;
}
}
Hash::Hash(AbstractHash* hashImpl) :
m_impl(hashImpl)
{
}
Hash::~Hash()
{
delete m_impl;
}
HashDigest Hash::Process(const Hashable& hashable)
{
m_impl->Begin();
if (hashable.FillHash(m_impl))
return m_impl->End();
else // Erreur
{
m_impl->End();
return HashDigest();
}
}
}

View File

@@ -109,7 +109,7 @@ namespace Nz
m_state->crc = 0xFFFFFFFF;
}
HashDigest HashCRC32::End()
ByteArray HashCRC32::End()
{
m_state->crc ^= 0xFFFFFFFF;
@@ -117,17 +117,16 @@ namespace Nz
SwapBytes(&m_state->crc, sizeof(UInt32));
#endif
return HashDigest(GetHashName(), reinterpret_cast<UInt8*>(&m_state->crc), 4);
return ByteArray(reinterpret_cast<UInt8*>(&m_state->crc), 4);
}
unsigned int HashCRC32::GetDigestLength()
unsigned int HashCRC32::GetDigestLength() const
{
return 4;
}
String HashCRC32::GetHashName()
const char* HashCRC32::GetHashName() const
{
static String hashName = "CRC32";
return hashName;
return "CRC32";
}
}

View File

@@ -48,7 +48,7 @@ namespace Nz
m_state->sum2 = 0xff;
}
HashDigest HashFletcher16::End()
ByteArray HashFletcher16::End()
{
m_state->sum1 = (m_state->sum1 & 0xff) + (m_state->sum1 >> 8);
m_state->sum2 = (m_state->sum2 & 0xff) + (m_state->sum2 >> 8);
@@ -59,17 +59,16 @@ namespace Nz
SwapBytes(&fletcher, sizeof(UInt32));
#endif
return HashDigest(GetHashName(), reinterpret_cast<UInt8*>(&fletcher), 2);
return ByteArray(reinterpret_cast<UInt8*>(&fletcher), 2);
}
unsigned int HashFletcher16::GetDigestLength()
unsigned int HashFletcher16::GetDigestLength() const
{
return 2;
}
String HashFletcher16::GetHashName()
const char* HashFletcher16::GetHashName() const
{
static String hashName = "Fletcher16";
return hashName;
return "Fletcher16";
}
}

View File

@@ -325,7 +325,7 @@ namespace Nz
m_state->abcd[3] = 0x10325476;
}
HashDigest HashMD5::End()
ByteArray HashMD5::End()
{
static const unsigned char pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -349,17 +349,16 @@ namespace Nz
for (i = 0; i < 16; ++i)
digest[i] = static_cast<UInt8>(m_state->abcd[i >> 2] >> ((i & 3) << 3));
return HashDigest(GetHashName(), &digest[0], 16);
return ByteArray(&digest[0], 16);
}
unsigned int HashMD5::GetDigestLength()
unsigned int HashMD5::GetDigestLength() const
{
return 16;
}
String HashMD5::GetHashName()
const char* HashMD5::GetHashName() const
{
static String hashName = "MD5";
return hashName;
return "MD5";
}
}

View File

@@ -28,23 +28,22 @@ namespace Nz
SHA1_Init(m_state);
}
HashDigest HashSHA1::End()
ByteArray HashSHA1::End()
{
UInt8 digest[SHA1_DIGEST_LENGTH];
SHA1_End(m_state, digest);
return HashDigest(GetHashName(), digest, SHA1_DIGEST_LENGTH);
return ByteArray(digest, SHA1_DIGEST_LENGTH);
}
unsigned int HashSHA1::GetDigestLength()
unsigned int HashSHA1::GetDigestLength() const
{
return SHA1_DIGEST_LENGTH;
}
String HashSHA1::GetHashName()
const char* HashSHA1::GetHashName() const
{
static String hashName = "SHA1";
return hashName;
return "SHA1";
}
}

View File

@@ -28,23 +28,22 @@ namespace Nz
SHA224_Init(m_state);
}
HashDigest HashSHA224::End()
ByteArray HashSHA224::End()
{
UInt8 digest[SHA224_DIGEST_LENGTH];
SHA224_End(m_state, digest);
return HashDigest(GetHashName(), digest, SHA224_DIGEST_LENGTH);
return ByteArray(digest, SHA224_DIGEST_LENGTH);
}
unsigned int HashSHA224::GetDigestLength()
unsigned int HashSHA224::GetDigestLength() const
{
return SHA224_DIGEST_LENGTH;
}
String HashSHA224::GetHashName()
const char* HashSHA224::GetHashName() const
{
static String hashName = "SHA224";
return hashName;
return "SHA224";
}
}

View File

@@ -28,23 +28,22 @@ namespace Nz
SHA256_Init(m_state);
}
HashDigest HashSHA256::End()
ByteArray HashSHA256::End()
{
UInt8 digest[SHA256_DIGEST_LENGTH];
SHA256_End(m_state, digest);
return HashDigest(GetHashName(), digest, SHA256_DIGEST_LENGTH);
return ByteArray(digest, SHA256_DIGEST_LENGTH);
}
unsigned int HashSHA256::GetDigestLength()
unsigned int HashSHA256::GetDigestLength() const
{
return SHA256_DIGEST_LENGTH;
}
String HashSHA256::GetHashName()
const char* HashSHA256::GetHashName() const
{
static String hashName = "SHA256";
return hashName;
return "SHA256";
}
}

View File

@@ -28,23 +28,22 @@ namespace Nz
SHA384_Init(m_state);
}
HashDigest HashSHA384::End()
ByteArray HashSHA384::End()
{
UInt8 digest[SHA384_DIGEST_LENGTH];
SHA384_End(m_state, digest);
return HashDigest(GetHashName(), digest, SHA384_DIGEST_LENGTH);
return ByteArray(digest, SHA384_DIGEST_LENGTH);
}
unsigned int HashSHA384::GetDigestLength()
unsigned int HashSHA384::GetDigestLength() const
{
return SHA384_DIGEST_LENGTH;
}
String HashSHA384::GetHashName()
const char* HashSHA384::GetHashName() const
{
static String hashName = "SHA384";
return hashName;
return "SHA384";
}
}

View File

@@ -28,23 +28,22 @@ namespace Nz
SHA512_Init(m_state);
}
HashDigest HashSHA512::End()
ByteArray HashSHA512::End()
{
UInt8 digest[SHA512_DIGEST_LENGTH];
SHA512_End(m_state, digest);
return HashDigest(GetHashName(), digest, SHA512_DIGEST_LENGTH);
return ByteArray(digest, SHA512_DIGEST_LENGTH);
}
unsigned int HashSHA512::GetDigestLength()
unsigned int HashSHA512::GetDigestLength() const
{
return SHA512_DIGEST_LENGTH;
}
String HashSHA512::GetHashName()
const char* HashSHA512::GetHashName() const
{
static String hashName = "SHA512";
return hashName;
return "SHA512";
}
}

View File

@@ -962,7 +962,7 @@ namespace Nz
m_state->hash[i] = 0L; // initial value
}
HashDigest HashWhirlpool::End()
ByteArray HashWhirlpool::End()
{
UInt8 result[64];
@@ -1012,17 +1012,16 @@ namespace Nz
m_state->bufferBits = bufferBits;
m_state->bufferPos = bufferPos;
return HashDigest(GetHashName(), &result[0], 64);
return ByteArray(&result[0], 64);
}
unsigned int HashWhirlpool::GetDigestLength()
unsigned int HashWhirlpool::GetDigestLength() const
{
return 64;
}
String HashWhirlpool::GetHashName()
const char* HashWhirlpool::GetHashName() const
{
static String hashName = "Whirlpool";
return hashName;
return "Whirlpool";
}
}

View File

@@ -1,194 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
HashDigest::HashDigest() :
m_digest(nullptr),
m_digestLength(0)
{
}
HashDigest::HashDigest(const String& hashName, const UInt8* digest, unsigned int length) :
m_hashName(hashName),
m_digestLength(length)
{
if (m_digestLength > 0)
{
m_digest = new UInt8[length];
std::memcpy(m_digest, digest, length);
}
else
m_digest = nullptr;
}
HashDigest::HashDigest(const HashDigest& rhs) :
m_hashName(rhs.m_hashName),
m_digestLength(rhs.m_digestLength)
{
if (m_digestLength > 0)
{
m_digest = new UInt8[m_digestLength];
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
}
else
m_digest = nullptr;
}
HashDigest::HashDigest(HashDigest&& rhs) noexcept :
m_hashName(std::move(rhs.m_hashName)),
m_digest(rhs.m_digest),
m_digestLength(rhs.m_digestLength)
{
rhs.m_digest = nullptr;
rhs.m_digestLength = 0;
}
HashDigest::~HashDigest()
{
delete[] m_digest;
}
bool HashDigest::IsValid() const
{
return m_digestLength > 0;
}
const UInt8* HashDigest::GetDigest() const
{
return m_digest;
}
unsigned int HashDigest::GetDigestLength() const
{
return m_digestLength;
}
String HashDigest::GetHashName() const
{
return m_hashName;
}
String HashDigest::ToHex() const
{
if (m_digestLength == 0)
return String();
unsigned int length = m_digestLength*2;
String hexOutput(length);
for (unsigned int i = 0; i < m_digestLength; ++i)
std::sprintf(&hexOutput[i*2], "%02x", m_digest[i]);
return hexOutput;
}
UInt8 HashDigest::operator[](unsigned int pos) const
{
#if NAZARA_CORE_SAFE
if (pos >= m_digestLength)
{
NazaraError("Position out of range");
return 0;
}
#endif
return m_digest[pos];
}
HashDigest& HashDigest::operator=(const HashDigest& rhs)
{
if (this == &rhs)
return *this;
m_hashName = rhs.m_hashName;
m_digestLength = rhs.m_digestLength;
if (m_digestLength > 0)
{
m_digest = new UInt8[m_digestLength];
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
}
else
m_digest = nullptr;
return *this;
}
HashDigest& HashDigest::operator=(HashDigest&& rhs) noexcept
{
std::swap(m_hashName, rhs.m_hashName);
std::swap(m_digest, rhs.m_digest);
std::swap(m_digestLength, rhs.m_digestLength);
return *this;
}
bool HashDigest::operator==(const HashDigest& rhs) const
{
if (m_digest == nullptr || rhs.m_digest == nullptr)
return m_digest == rhs.m_digest;
if (m_digestLength != rhs.m_digestLength)
return false;
return m_hashName == rhs.m_hashName && std::memcmp(m_digest, rhs.m_digest, m_digestLength) == 0;
}
bool HashDigest::operator!=(const HashDigest& rhs) const
{
return !operator==(rhs);
}
bool HashDigest::operator<(const HashDigest& rhs) const
{
if (rhs.m_digest == nullptr)
return false;
if (m_digest == nullptr)
return true;
int cmp = String::Compare(m_hashName, rhs.m_hashName);
if (cmp == 0)
{
cmp = std::memcmp(m_digest, rhs.m_digest, std::min(m_digestLength, rhs.m_digestLength));
if (cmp == 0)
return m_digestLength < rhs.m_digestLength;
else
return cmp < 0;
}
else
return cmp < 0;
}
bool HashDigest::operator<=(const HashDigest& rhs) const
{
return !rhs.operator<(*this);
}
bool HashDigest::operator>(const HashDigest& rhs) const
{
return rhs.operator<(*this);
}
bool HashDigest::operator>=(const HashDigest& rhs) const
{
return !operator<(rhs);
}
}
std::ostream& operator<<(std::ostream& out, const Nz::HashDigest& hashstring)
{
out << hashstring.ToHex();
return out;
}

View File

@@ -1,24 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/Hash.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
Hashable::~Hashable() = default;
HashDigest Hashable::GetHash(HashType hash) const
{
Hash h(hash);
return h.Process(*this);
}
HashDigest Hashable::GetHash(AbstractHash* impl) const
{
Hash h(impl);
return h.Process(*this);
}
}

View File

@@ -5,7 +5,6 @@
///TODO: Réécrire une bonne partie des algorithmes employés (Relu jusqu'à 3538)
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Unicode.hpp>
@@ -4203,13 +4202,6 @@ namespace Nz
}
}
bool String::FillHash(AbstractHash* hash) const
{
hash->Append(reinterpret_cast<const UInt8*>(GetConstBuffer()), GetSize());
return true;
}
const std::shared_ptr<String::SharedString>& String::GetEmptyString()
{
static auto emptyString = std::make_shared<SharedString>();