AuroraRuntime/Source/Hashing/HashStream.cpp
Reece Wilson 8a2947ffc5 [+] RMD128+BScFwd based HashCash (bcrypt DoS mitigation, acc creation, antibot, etc)
[*] Refactor bcrypt api: HashPW[Ex] -> HashPassword[Ex]
[+] ByteBuffer::GetOrAllocateLinearWriteable
[+] ByteBuffer::Can[Read/Write](n)
[+] ByteBuffer::GetLinear[Read/Writable]able(n)
[*] Split RNG.cpp into two files
[+] EHashType::eSHA2_48 (_32, _64 was already in place. missed 48/384 bit)
[+] AuCrypto::HMAC and IHMACContext
(AuHashing)
[+] EHashType::eSHA3_28
[+] EHashType::eSHA3_32
[+] EHashType::eSHA3_48
[+] EHashType::eSHA3_64
(AuCrypto)
[+] EHashType::eSHA2_48_384
[+] EHashType::eSHA2_64_512
[+] EHashType::eSHA3_28_224
[+] EHashType::eSHA3_32_256
[+] EHashType::eSHA3_48_384
[+] EHashType::eSHA3_64_512
[*] (IRandomDevice) class -> struct
[*] Bugfix: cast in Promise<SuccessValue_t, ErrorValue_t>::WriteIntoError
[+] Missing AuHashing namespace alias
[*] Time util: pad ms when fraction of a second to 3 digits
2022-09-19 02:34:57 +01:00

433 lines
12 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: HashStream.cpp
Date: 2021-6-12
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include <tomcrypt.h>
#include "HashStream.hpp"
namespace Aurora::Hashing
{
HashStream::HashStream(EHashType type) : type_(type)
{
Init();
}
void HashStream::Ingest(const Memory::MemoryViewRead &input)
{
if (this->bFinished_)
{
return;
}
auto buffer = reinterpret_cast<const unsigned char *>(input.ptr);
auto len = input.length;
switch (this->type_)
{
case EHashType::eMD4:
md4_process(&this->state_, buffer, len);
break;
case EHashType::eMD5:
md5_process(&this->state_, buffer, len);
break;
case EHashType::eSHA1:
sha1_process(&this->state_, buffer, len);
break;
case EHashType::eSHA2_32:
sha256_process(&this->state_, buffer, len);
break;
case EHashType::eSHA2_48:
sha384_process(&this->state_, buffer, len);
break;
case EHashType::eSHA2_64:
sha512_process(&this->state_, buffer, len);
break;
case EHashType::eSHA3_28:
case EHashType::eSHA3_48:
case EHashType::eSHA3_32:
case EHashType::eSHA3_64:
sha3_process(&this->state_, buffer, len);
break;
case EHashType::eTiger:
tiger_process(&this->state_, buffer, len);
break;
case EHashType::eRMD128:
rmd128_process(&this->state_, buffer, len);
break;
case EHashType::eRMD160:
rmd160_process(&this->state_, buffer, len);
break;
case EHashType::eRMD256:
rmd256_process(&this->state_, buffer, len);
break;
case EHashType::eRMD320:
rmd320_process(&this->state_, buffer, len);
break;
}
}
AuUInt8 const* HashStream::GetBytes(AuUInt32 &length)
{
switch (this->type_)
{
case EHashType::eMD4:
length = 16;
if (!AuExchange(this->bFinished_, true))
{
md4_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eMD5:
length = 16;
if (!AuExchange(this->bFinished_, true))
{
md5_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA1:
length = 20;
if (!AuExchange(this->bFinished_, true))
{
sha1_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA2_48:
length = 48;
if (!AuExchange(this->bFinished_, true))
{
sha384_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA2_32:
length = 32;
if (!AuExchange(this->bFinished_, true))
{
sha256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA2_64:
length = 64;
if (!AuExchange(this->bFinished_, true))
{
sha512_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA3_28:
length = 28;
if (!AuExchange(this->bFinished_, true))
{
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA3_48:
length = 48;
if (!AuExchange(this->bFinished_, true))
{
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA3_32:
length = 32;
if (!AuExchange(this->bFinished_, true))
{
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eSHA3_64:
length = 64;
if (!AuExchange(this->bFinished_, true))
{
sha3_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eTiger:
length = 24;
if (!AuExchange(this->bFinished_, true))
{
tiger_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eRMD128:
length = 16;
if (!AuExchange(this->bFinished_, true))
{
rmd128_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eRMD160:
length = 20;
if (!AuExchange(this->bFinished_, true))
{
rmd160_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eRMD256:
length = 32;
if (!AuExchange(this->bFinished_, true))
{
rmd256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
case EHashType::eRMD320:
length = 40;
if (!AuExchange(this->bFinished_, true))
{
rmd256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
return this->buffer_;
}
return nullptr;
}
AuMemoryViewRead HashStream::Finalize()
{
AuUInt32 length;
auto begin = GetBytes(length);
return AuMemoryViewRead(begin, length);
}
Memory::MemoryViewRead HashStream::PeekFinalize()
{
if (this->bFinished_)
{
return this->Finalize();
}
hash_state state;
AuMemcpy(&state, &this->state_, sizeof(state));
auto view = this->Finalize();
AuMemcpy(&this->state_, &state, sizeof(state));
this->bFinished_ = false;
return view;
}
AuResult<AuMemoryViewRead> HashStream::Export()
{
// Defer to HASH_PROCESS defined in the private libtomcrypt header
//this->state_.name.length | bits processed
#define ADD_EXPORT(name) \
if (this->state_.name.curlen) \
{ \
return {}; \
} \
return AuMemoryViewRead {this->state_.name.state, sizeof(this->state_.name.state)};
switch (this->type_)
{
case EHashType::eMD4:
ADD_EXPORT(md4);
case EHashType::eMD5:
ADD_EXPORT(md5);
case EHashType::eSHA1:
ADD_EXPORT(sha1);
case EHashType::eSHA2_32:
ADD_EXPORT(sha256);
case EHashType::eSHA2_48:
case EHashType::eSHA2_64:
ADD_EXPORT(sha512);
case EHashType::eSHA3_28:
case EHashType::eSHA3_48:
case EHashType::eSHA3_32:
case EHashType::eSHA3_64:
{
if (this->state_.sha3.byte_index)
{
return {};
}
return AuMemoryViewRead(this->state_.sha3.s, this->state_.sha3.s + (8 * this->state_.sha3.word_index));
}
case EHashType::eTiger:
ADD_EXPORT(tiger);
case EHashType::eRMD128:
ADD_EXPORT(rmd128);
case EHashType::eRMD160:
ADD_EXPORT(rmd160);
case EHashType::eRMD256:
ADD_EXPORT(rmd256);
case EHashType::eRMD320:
ADD_EXPORT(rmd320);
default:
return {};
}
#undef ADD_EXPORT
}
bool HashStream::Import(const Memory::MemoryViewRead &view)
{
this->bFinished_ = false;
#define ADD_IMPORT(name) \
if (sizeof(this->state_.name.state) != view.length) \
{ \
SysPushErrorCrypt("Invalid hash state length -> mixed ciphers?"); \
return false; \
} \
AuMemset(&this->state_, 0, sizeof(this->state_)); \
AuMemcpy(this->state_.name.state, view.ptr, sizeof(this->state_.name.state)); \
return true;
switch (this->type_)
{
case EHashType::eMD4:
ADD_IMPORT(md4);
case EHashType::eMD5:
ADD_IMPORT(md5);
case EHashType::eSHA1:
ADD_IMPORT(sha1);
case EHashType::eSHA2_32:
ADD_IMPORT(sha256);
case EHashType::eSHA2_48:
case EHashType::eSHA2_64:
ADD_IMPORT(sha512);
case EHashType::eSHA3_28:
case EHashType::eSHA3_48:
case EHashType::eSHA3_32:
case EHashType::eSHA3_64:
{
if (this->state_.sha3.byte_index)
{
return {};
}
if (sizeof(this->state_.sha3.s) < view.length)
{
return {};
}
AuMemcpy(this->state_.sha3.s, view.ptr, view.length);
this->state_.sha3.word_index = view.length / 8;
return true;
}
case EHashType::eTiger:
ADD_IMPORT(tiger);
case EHashType::eRMD128:
ADD_IMPORT(rmd128);
case EHashType::eRMD160:
ADD_IMPORT(rmd160);
case EHashType::eRMD256:
ADD_IMPORT(rmd256);
case EHashType::eRMD320:
ADD_IMPORT(rmd320);
default:
return false;
}
#undef ADD_IMPORT
}
void HashStream::Reset()
{
Init();
}
void HashStream::Init()
{
this->bFinished_ = false;
AuMemset(&this->state_, 0, sizeof(this->state_));
switch (this->type_)
{
case EHashType::eMD4:
md4_init(&this->state_);
break;
case EHashType::eMD5:
md5_init(&this->state_);
break;
case EHashType::eSHA1:
sha1_init(&this->state_);
break;
case EHashType::eSHA2_32:
sha256_init(&this->state_);
break;
case EHashType::eSHA2_48:
sha384_init(&this->state_);
break;
case EHashType::eSHA2_64:
sha512_init(&this->state_);
break;
case EHashType::eSHA3_28:
sha3_224_init(&this->state_);
break;
case EHashType::eSHA3_32:
sha3_256_init(&this->state_);
break;
case EHashType::eSHA3_48:
sha3_384_init(&this->state_);
break;
case EHashType::eSHA3_64:
sha3_512_init(&this->state_);
break;
case EHashType::eTiger:
tiger_init(&this->state_);
break;
case EHashType::eRMD128:
rmd128_init(&this->state_);
break;
case EHashType::eRMD160:
rmd160_init(&this->state_);
break;
case EHashType::eRMD256:
rmd256_init(&this->state_);
break;
case EHashType::eRMD320:
rmd320_init(&this->state_);
break;
}
}
AUKN_SYM IHashStream *HashStreamNew(EHashType type)
{
return _new HashStream(type);
}
AUKN_SYM void HashStreamRelease(IHashStream *stream)
{
AuSafeDelete<HashStream*>(stream);
}
}