[+] 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
This commit is contained in:
Reece Wilson 2022-09-19 02:34:57 +01:00
parent 8844e8fe64
commit 8a2947ffc5
34 changed files with 847 additions and 278 deletions

View File

@ -670,7 +670,7 @@ namespace Aurora::Async
inline AuSPtr<ErrorValue_t> Promise<SuccessValue_t, ErrorValue_t>::WriteIntoError()
{
this->bHasError_ = true;
return AuSPtr<SuccessValue_t>(AuSharedFromThis(), &this->error);
return AuSPtr<ErrorValue_t>(AuSharedFromThis(), &this->error);
}
template<class SuccessValue_t, class ErrorValue_t>

View File

@ -16,8 +16,8 @@ namespace Aurora::Crypto::BCrypt
AUKN_SYM AuString GenSalt(int rounds);
AUKN_SYM AuString HashPW(const AuString &password, const AuString &salt);
AUKN_SYM AuString HashPWEx(const Memory::MemoryViewRead &password, const AuString &salt);
AUKN_SYM AuString HashPassword(const AuString &password, const AuString &salt);
AUKN_SYM AuString HashPasswordEx(const Memory::MemoryViewRead &password, const AuString &salt);
AUKN_SYM bool CheckPassword(const AuString &password, const AuString &hashedPassword);
AUKN_SYM bool CheckPasswordEx(const Memory::MemoryViewRead &password, const AuString &hashedPassword);

View File

@ -32,3 +32,6 @@ namespace Aurora::Crypto
#include "ECC/ECC.hpp"
#include "PEM/PEM.hpp"
#include "RSA/RSA.hpp"
#include "BCrypt/BCrypt.hpp"
#include "HMAC/HMAC.hpp"
#include "HashCash/HashCash.hpp"

View File

@ -11,9 +11,15 @@ namespace Aurora::Crypto
{
AUE_DEFINE(EHashType,
(
eMD5,
eSHA1_20_160,
eTiger_24_192,
eSHA2_32_256,
eSHA2_64_512
eSHA2_48_384,
eSHA2_64_512,
eSHA3_28_224,
eSHA3_32_256,
eSHA3_48_384,
eSHA3_64_512
));
}

View File

@ -0,0 +1,35 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: HMAC.hpp
Date: 2022-9-18
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::HMAC
{
struct IHMACContext
{
/**
* @brief Processes an arbitrary amount of bytes
* @param input
*/
virtual void Ingest(const Memory::MemoryViewRead &input) = 0;
/**
* @brief Finalizes the hash stream
* @return
*/
virtual Memory::MemoryViewRead Finalize() = 0;
/**
* @brief
*/
virtual void Reset() = 0;
};
AUKN_SHARED_API(HMAC, IHMACContext,
EHashType algorithm,
const Memory::MemoryViewRead &sharedSecret);
}

View File

@ -0,0 +1,19 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: HashCash.hpp
Date: 2022-9-18
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::HashCash
{
struct HashCashAnswer
{
AuUInt64 y;
};
AUKN_SYM bool CheckSalt(AuUInt64 token, AuUInt8 power, const HashCashAnswer &answer);
AUKN_SYM HashCashAnswer FindAnswer(AuUInt64 token, AuUInt8 power);
}

View File

@ -19,8 +19,18 @@ namespace Aurora::Hashing
AUKN_SYM void SHA2(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 32> &sha2);
AUKN_SYM void SHA2_48(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 48> &sha2);
AUKN_SYM void SHA2_64(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 64> &sha2);
AUKN_SYM void SHA3_28(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 28> &sha3);
AUKN_SYM void SHA3_32(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 32> &sha3);
AUKN_SYM void SHA3_48(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 48> &sha3);
AUKN_SYM void SHA3_64(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 64> &sha3);
/**
* @brief RipeMD-128
*/

View File

@ -15,7 +15,12 @@ namespace Aurora::Hashing
eMD5,
eSHA1,
eSHA2_32,
eSHA2_48,
eSHA2_64,
eSHA3_28,
eSHA3_32,
eSHA3_48,
eSHA3_64,
eTiger,
eRMD128,
eRMD160,

View File

@ -30,6 +30,15 @@ namespace Aurora::Hashing
*/
virtual Memory::MemoryViewRead Finalize() = 0;
/**
* @brief 1) Temporarily finalizes the stream
* 2) Copies the final state into the final buffer
* 3) Returns the stream its' original state
* 4) Returns a view of the final buffer
* @return
*/
virtual Memory::MemoryViewRead PeekFinalize() = 0;
/**
* @brief Exports the state of an aligned stream
* @return

View File

@ -316,8 +316,16 @@ namespace Aurora::Memory
inline auline void ResetReadPointer();
inline MemoryViewRead GetNextLinearRead();
inline MemoryViewWrite GetNextLinearWrite();
inline auline MemoryViewRead GetNextLinearRead();
inline auline MemoryViewWrite GetNextLinearWrite();
inline auline bool CanWrite(AuUInt length);
inline auline bool CanRead(AuUInt length);
inline auline MemoryViewRead GetLinearReadable(AuUInt length);
inline auline MemoryViewWrite GetLinearWriteable(AuUInt length);
inline auline MemoryViewWrite GetOrAllocateLinearWriteable(AuUInt length);
// Memory operations

View File

@ -232,6 +232,46 @@ namespace Aurora::Memory
return MemoryViewWrite(pBase, uCount);
}
bool ByteBuffer::CanWrite(AuUInt length)
{
return this->RemainingWrite(true) >= length;
}
bool ByteBuffer::CanRead(AuUInt length)
{
return this->RemainingBytes(true) >= length;
}
MemoryViewRead ByteBuffer::GetLinearReadable(AuUInt length)
{
auto view = this->GetNextLinearRead();
return view.length < length ? MemoryViewRead {} : MemoryViewRead(view.ptr, length);
}
MemoryViewWrite ByteBuffer::GetLinearWriteable(AuUInt length)
{
auto view = this->GetNextLinearWrite();
return view.length < length ? MemoryViewWrite {} : MemoryViewWrite(view.ptr, length);
}
MemoryViewWrite ByteBuffer::GetOrAllocateLinearWriteable(AuUInt length)
{
if (this->CanWrite(length))
{
return this->GetLinearWriteable(length);
}
else if (!this->flagCircular && this->length == 0 && this->flagExpandable)
{
if (!this->Resize(length))
{
SysPushErrorMemory("Couldn't resize bytebuffer for bytes: {}", length);
return {};
}
return this->GetLinearWriteable(length);
}
}
AuUInt ByteBuffer::GetReadOffset() const
{
if (flagCircular)

View File

@ -9,9 +9,8 @@
namespace Aurora::RNG
{
class IRandomDevice
struct IRandomDevice
{
public:
virtual void Read(void *in, AuUInt32 length) = 0;
virtual AuString NextString(AuUInt32 length, ERngStringCharacters type = ERngStringCharacters::eAlphaCharacters) = 0;

View File

@ -106,6 +106,7 @@ namespace AuTime = Aurora::Time;
namespace AuTypes = Aurora::Types;
namespace AuLog = Aurora::Logging;
namespace AuMemory = Aurora::Memory;
namespace AuHashing = Aurora::Hashing;
namespace AuExit = Aurora::Exit;
using AuWorkerId_t = AuAsync::WorkerId_t;

View File

@ -6,7 +6,7 @@
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "Crypto.hpp"
#include "AuCrypto.hpp"
#include <tomcrypt.h>
namespace Crypto
@ -23,7 +23,13 @@ namespace Crypto
register_hash(&md5_desc);
gHashSha1 = register_hash(&sha1_desc);
gHashSha256 = register_hash(&sha256_desc);
gHashSha384 = register_hash(&sha384_desc);
gHashSha512 = register_hash(&sha512_desc);
gHashSha3_224 = register_hash(&sha3_224_desc);
gHashSha3_256 = register_hash(&sha3_256_desc);
gHashSha3_384 = register_hash(&sha3_384_desc);
gHashSha3_512 = register_hash(&sha3_512_desc);
gHashMD5 = register_hash(&md5_desc);
register_hash(&rmd128_desc);
register_hash(&rmd160_desc);
gPrngYarrow = register_prng(&yarrow_desc);

View File

@ -12,8 +12,14 @@ namespace Crypto
inline int gAesCipher;
inline int gHashTiger;
inline int gHashSha1;
inline int gHashMD5;
inline int gHashSha256;
inline int gHashSha384;
inline int gHashSha512;
inline int gHashSha3_256;
inline int gHashSha3_384;
inline int gHashSha3_224;
inline int gHashSha3_512;
inline int gPrngYarrow;
void InitCrypto();

View File

@ -9,7 +9,7 @@
#include <AuroraCommon.hpp>
#include <AuroraRuntime.hpp>
#include "RuntimeInternal.hpp"
#include "Crypto.hpp"
#include "AuCrypto.hpp"
#include "Processes/Processes.hpp"
#include "RNG/RNG.hpp"
#include "Locale/Locale.hpp"

View File

@ -9,7 +9,7 @@
#include "../Crypto.hpp"
#include "Aes.hpp"
#include <tomcrypt.h>
#include <Source/Crypto.hpp>
#include <Source/AuCrypto.hpp>
namespace Aurora::Crypto::AES
{

View File

@ -25,7 +25,7 @@ namespace Aurora::Crypto::BCrypt
AUKN_SYM AuString GenSalt(int rounds)
{
char seed[16];
char cryptLength[31];
char saltBuffer[31];
AuRng::RngFillArray<false>(seed);
@ -35,18 +35,18 @@ namespace Aurora::Crypto::BCrypt
rounds,
seed,
16,
cryptLength,
AuArraySize(cryptLength));
saltBuffer,
AuArraySize(saltBuffer));
SysAssert(ptr, "?");
return ptr;
}
AUKN_SYM AuString HashPW(const AuString &password, const AuString &salt)
AUKN_SYM AuString HashPassword(const AuString &password, const AuString &salt)
{
return HashPWEx({ password.c_str(), password.size() + 1 }, salt);
return HashPasswordEx({ password.c_str(), password.size() + 1 }, salt);
}
AUKN_SYM AuString HashPWEx(const Memory::MemoryViewRead &password, const AuString &salt)
AUKN_SYM AuString HashPasswordEx(const Memory::MemoryViewRead &password, const AuString &salt)
{
if (password.length > 72)
{

View File

@ -9,7 +9,7 @@
#include <tomcrypt.h>
#include <Source/Extensions/LTC/LTCExtensions.hpp>
#include <Source/Crypto.hpp>
#include <Source/AuCrypto.hpp>
namespace Aurora::Crypto
{
@ -42,8 +42,20 @@ namespace Aurora::Crypto
return ::Crypto::gHashSha1;
case EHashType::eSHA2_32_256:
return ::Crypto::gHashSha256;
case EHashType::eSHA2_48_384:
return ::Crypto::gHashSha384;
case EHashType::eSHA2_64_512:
return ::Crypto::gHashSha512;
case EHashType::eSHA3_28_224:
return ::Crypto::gHashSha3_224;
case EHashType::eSHA3_32_256:
return ::Crypto::gHashSha3_256;
case EHashType::eSHA3_48_384:
return ::Crypto::gHashSha3_384;
case EHashType::eSHA3_64_512:
return ::Crypto::gHashSha3_512;
case EHashType::eMD5:
return ::Crypto::gHashMD5;
default:
return 0xFF;
}

View File

@ -0,0 +1,88 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: HMAC.cpp
Date: 2022-9-18
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include <Source/Crypto/Crypto.hpp>
#include "HMAC.hpp"
namespace Aurora::Crypto::HMAC
{
HMACContext::HMACContext(EHashType type) :
type_(type)
{
}
void HMACContext::Ingest(const Memory::MemoryViewRead &input)
{
SysAssert(::hmac_process(&this->state_, (const unsigned char *)input.ptr, input.length) != CRYPT_OK);
}
Memory::MemoryViewRead HMACContext::Finalize()
{
unsigned long outLength {};
if (::hmac_done(&this->state_, this->buffer_, &outLength) != CRYPT_OK)
{
SysPushErrorCrypt();
return {};
}
this->bFinished_ = true;
return { this->buffer_, outLength };
}
void HMACContext::Reset()
{
AuMemcpy(&this->state_, &this->referenceState_, sizeof(this->state_));
this->bFinished_ = false;
}
bool HMACContext::Init(const Memory::MemoryViewRead &input)
{
int iRet {};
int hash = HashMethodToId(this->type_);
if (hash == 0xFF)
{
SysPushErrorCrypt("invalid hash {}", this->type_);
return false;
}
iRet = ::hmac_init(&this->referenceState_, hash, (const unsigned char *)input.ptr, input.length);
if (iRet != CRYPT_OK)
{
SysPushErrorCrypt("error {}", iRet);
return false;
}
Reset();
return true;
}
AUKN_SYM IHMACContext *HMACNew(EHashType algorithm,
const Memory::MemoryViewRead &sharedSecret)
{
auto pContext = _new HMACContext(algorithm);
if (!pContext)
{
SysPushErrorMemory();
return {};
}
if (!pContext->Init(sharedSecret))
{
return {};
}
return pContext;
}
AUKN_SYM void HMACRelease(IHMACContext *pContext)
{
AuSafeDelete<HMACContext *>(pContext);
}
}

View File

@ -0,0 +1,30 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: HMAC.hpp
Date: 2022-9-18
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::HMAC
{
struct HMACContext : IHMACContext
{
HMACContext(EHashType type);
void Ingest(const Memory::MemoryViewRead &input) override;
Memory::MemoryViewRead Finalize() override;
void Reset() override;
bool Init(const Memory::MemoryViewRead &input);
private:
AuUInt8 buffer_[64] {};
hmac_state state_ {};
hmac_state referenceState_ {};
EHashType type_ {};
bool bFinished_ {};
};
}

View File

@ -0,0 +1,61 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: HashCash.cpp
Date: 2022-9-18
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "HashCash.hpp"
namespace Aurora::Crypto::HashCash
{
AUKN_SYM bool CheckSalt(AuUInt64 token, AuUInt8 power, const HashCashAnswer &answer)
{
AuUInt8 count {};
AuArray<AuUInt8, 16> hashBuffer;
struct Hash
{
AuUInt64 token;
AuUInt64 y;
} hash;
static_assert(sizeof(Hash) == 16);
hash.token = token;
hash.y = answer.y;
AuHashing::RMD128(AuMemoryViewRead(&hash, 16), hashBuffer);
AuBitScanForward(count, AuReadU64LE(hashBuffer.data(), 0));
return count == power;
}
AUKN_SYM HashCashAnswer FindAnswer(AuUInt64 token, AuUInt8 power)
{
HashCashAnswer answer;
AuArray<AuUInt8, 16> hashBuffer;
struct Hash
{
AuUInt64 token;
AuUInt64 y;
} hash;
static_assert(sizeof(Hash) == 16);
hash.token = token;
hash.y = AuRng::RngU64();
AuUInt8 count {};
do
{
hash.y++;
AuHashing::RMD128(AuMemoryViewRead(&hash, 16), hashBuffer);
}
while (AuBitScanForward(count, AuReadU64LE(hashBuffer.data(), 0)), count != power);
answer.y = hash.y;
return answer;
}
}

View File

@ -0,0 +1,10 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: HashCash.hpp
Date: 2022-9-18
Author: Reece
***/
#pragma once
#include <Aurora/Crypto/HashCash/HashCash.hpp>

View File

@ -51,6 +51,14 @@ namespace Aurora::Hashing
sha256_done(&hs, sha2.data());
}
AUKN_SYM void SHA2_48(const AuMemoryViewRead &read, AuArray<AuUInt8, 48> &sha2)
{
hash_state hs;
sha384_init(&hs);
sha384_process(&hs, reinterpret_cast<const unsigned char *>(read.ptr), read.length);
sha384_done(&hs, sha2.data());
}
AUKN_SYM void SHA2_64(const AuMemoryViewRead &read, AuArray<AuUInt8, 64> &sha2)
{
hash_state hs;
@ -59,6 +67,38 @@ namespace Aurora::Hashing
sha512_done(&hs, sha2.data());
}
AUKN_SYM void SHA3_28(const AuMemoryViewRead &read, AuArray<AuUInt8, 28> &sha3)
{
hash_state hs;
sha3_224_init(&hs);
sha3_process(&hs, reinterpret_cast<const unsigned char *>(read.ptr), read.length);
sha3_done(&hs, sha3.data());
}
AUKN_SYM void SHA3_32(const AuMemoryViewRead &read, AuArray<AuUInt8, 32> &sha3)
{
hash_state hs;
sha3_256_init(&hs);
sha3_process(&hs, reinterpret_cast<const unsigned char *>(read.ptr), read.length);
sha3_done(&hs, sha3.data());
}
AUKN_SYM void SHA3_48(const AuMemoryViewRead &read, AuArray<AuUInt8, 48> &sha3)
{
hash_state hs;
sha3_384_init(&hs);
sha3_process(&hs, reinterpret_cast<const unsigned char *>(read.ptr), read.length);
sha3_done(&hs, sha3.data());
}
AUKN_SYM void SHA3_64(const AuMemoryViewRead &read, AuArray<AuUInt8, 64> &sha3)
{
hash_state hs;
sha3_512_init(&hs);
sha3_process(&hs, reinterpret_cast<const unsigned char *>(read.ptr), read.length);
sha3_done(&hs, sha3.data());
}
AUKN_SYM void RMD128(const AuMemoryViewRead &read, AuArray<AuUInt8, 16> &rmd128)
{
hash_state hs;

View File

@ -18,7 +18,7 @@ namespace Aurora::Hashing
void HashStream::Ingest(const Memory::MemoryViewRead &input)
{
if (this->finished_)
if (this->bFinished_)
{
return;
}
@ -40,9 +40,18 @@ namespace Aurora::Hashing
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;
@ -67,7 +76,7 @@ namespace Aurora::Hashing
{
case EHashType::eMD4:
length = 16;
if (!AuExchange(this->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
md4_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -75,7 +84,7 @@ namespace Aurora::Hashing
case EHashType::eMD5:
length = 16;
if (!AuExchange(this->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
md5_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -83,15 +92,23 @@ namespace Aurora::Hashing
case EHashType::eSHA1:
length = 20;
if (!AuExchange(this->finished_, true))
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->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
sha256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -99,15 +116,47 @@ namespace Aurora::Hashing
case EHashType::eSHA2_64:
length = 64;
if (!AuExchange(this->finished_, true))
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->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
tiger_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -115,7 +164,7 @@ namespace Aurora::Hashing
case EHashType::eRMD128:
length = 16;
if (!AuExchange(this->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
rmd128_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -123,7 +172,7 @@ namespace Aurora::Hashing
case EHashType::eRMD160:
length = 20;
if (!AuExchange(this->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
rmd160_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -131,7 +180,7 @@ namespace Aurora::Hashing
case EHashType::eRMD256:
length = 32;
if (!AuExchange(this->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
rmd256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -140,7 +189,7 @@ namespace Aurora::Hashing
case EHashType::eRMD320:
length = 40;
if (!AuExchange(this->finished_, true))
if (!AuExchange(this->bFinished_, true))
{
rmd256_done(&this->state_, reinterpret_cast<unsigned char *>(this->buffer_));
}
@ -157,6 +206,22 @@ namespace Aurora::Hashing
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
@ -184,9 +249,23 @@ namespace Aurora::Hashing
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);
@ -210,7 +289,7 @@ namespace Aurora::Hashing
bool HashStream::Import(const Memory::MemoryViewRead &view)
{
this->finished_ = false;
this->bFinished_ = false;
#define ADD_IMPORT(name) \
if (sizeof(this->state_.name.state) != view.length) \
@ -236,9 +315,30 @@ namespace Aurora::Hashing
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);
@ -268,7 +368,7 @@ namespace Aurora::Hashing
void HashStream::Init()
{
this->finished_ = false;
this->bFinished_ = false;
AuMemset(&this->state_, 0, sizeof(this->state_));
switch (this->type_)
@ -285,9 +385,24 @@ namespace Aurora::Hashing
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;

View File

@ -18,6 +18,7 @@ namespace Aurora::Hashing
AuUInt8 const *GetBytes(AuUInt32 &length) override;
Memory::MemoryViewRead Finalize() override;
Memory::MemoryViewRead PeekFinalize() override;
AuResult<Memory::MemoryViewRead> Export() override;
@ -30,6 +31,6 @@ namespace Aurora::Hashing
AuUInt8 buffer_[64] {};
hash_state state_ {};
EHashType type_ {};
bool finished_ {};
bool bFinished_ {};
};
}

View File

@ -59,9 +59,8 @@ namespace Aurora::Locale
static AuString _TextPrepadZeroMS(const AuString &in)
{
AuString ret = in;
if (ret.size() == 1) ret.insert(0, "000", 3);
else if (ret.size() == 2) ret.insert(0, "000", 2);
else if (ret.size() == 3) ret.insert(0, "000", 1);
if (ret.size() == 1) ret.insert(0, "000", 2);
else if (ret.size() == 2) ret.insert(0, "000", 1);
while (ret.size() > 1 && ret[ret.size() - 1] == '0')
ret.pop_back();
return ret;
@ -100,7 +99,7 @@ namespace Aurora::Locale
//
// ! = pad
//
// S!2.MS!4s (01.5000s)
// S!2.MS!3s (01.500s)
// M!2.S!2 (02:29)
// H!2:M!2:S!2 (01:02:29)
// D!0d H!2:M!2:S!2 (9d 01:02:29)

View File

@ -7,179 +7,13 @@
***/
#include <Source/RuntimeInternal.hpp>
#include "RNG.hpp"
#if defined(AURORA_PLATFORM_WIN32)
#include <wincrypt.h>
#include <bcrypt.h>
#elif defined(AURORA_IS_MODERNNT_DERIVED)
#include <bcrypt.h>
#undef USE_OLD_NTCRYPT
#endif
#if defined(AURORA_IS_POSIX_DERIVED)
#include <cstdio>
#endif
#include "RNGEntropy.hpp"
#include "WELL.hpp"
namespace Aurora::RNG
{
static WELLRand gWellRand;
static RandomUnique_t gFastDevice;
#if defined(AURORA_IS_POSIX_DERIVED)
static FILE *gDevURand;
static void InitRandPlatform()
{
gDevURand = fopen("/dev/urandom", "rb");
if (gDevURand == NULL)
{
gDevURand = fopen("/dev/random", "rb");
}
if (!gDevURand)
{
return;
}
if (setvbuf(gDevURand, NULL, _IONBF, 0) != 0)
{
#if 0
fclose(gDevURand);
gDevURand = NULL;
#endif
}
}
static AuUInt32 RngUnix(AuUInt8 *buf, AuUInt32 len)
{
return fread(buf, 1, (size_t)len, gDevURand);
}
#elif defined(AURORA_IS_MODERNNT_DERIVED)
#if defined(USE_OLD_NTCRYPT)
static HCRYPTPROV gCryptoProv;
#endif
static void InitRandPlatform()
{
#if defined(USE_OLD_NTCRYPT)
if (!CryptAcquireContext(&gCryptoProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)))
{
if (!CryptAcquireContext(&gCryptoProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
{
gCryptoProv = 0;
}
}
#endif
}
static AuUInt32 RngWin32(AuUInt8 *buf, AuUInt32 len)
{
#if defined(USE_OLD_NTCRYPT)
if (!gCryptoProv)
{
return 0;
}
if (!CryptGenRandom(gCryptoProv, len, buf))
{
return 0;
}
return len;
#else
#if !defined(AURORA_DONT_PREFER_WIN32_USERLAND_AES_RNG)
if (BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, reinterpret_cast<PUCHAR>(buf), len, 0) == 0)
{
return len;
}
#endif
if (BCryptGenRandom(NULL, reinterpret_cast<PUCHAR>(buf), len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
{
return len;
}
return 0;
#endif
}
#else
static void InitRandPlatform()
{
}
#endif
static AuUInt32 RngStdC(AuUInt8 *buf, AuUInt32 len)
{
clock_t t1;
int l, acc, bits, a, b;
l = len;
acc = a = b = 0;
bits = 8;
while (len--)
{
while (bits--) // for each bit in byte
{
do
{
t1 = clock();
while (t1 == clock()) // spin within the resolution of 1 C clock() tick
{
a ^= 1; // flip
}
t1 = clock();
while (t1 == clock())
{
b ^= 1; // flip
}
} while (a == b); // ensure theres enough entropy for a deviation to occur
acc = (acc << 1) | a; // push the first bit state
}
*buf++ = acc;
acc = 0;
bits = 8;
}
return l;
}
static AuUInt32 RngGetBytes(AuUInt8 *out, AuUInt32 outlen)
{
AuUInt32 x;
#if defined(AURORA_IS_MODERNNT_DERIVED)
x = RngWin32(out, outlen);
if (x != 0)
{
return x;
}
#elif defined(AURORA_IS_POSIX_DERIVED)
x = RngUnix(out, outlen);
if (x != 0)
{
return x;
}
#endif
x = RngStdC(out, outlen);
if (x != 0)
{
return x;
}
return 0;
}
RandomUnique_t gFastDevice;
AUKN_SYM void ReadSecureRNG(void *in, AuUInt32 length)
{
@ -203,84 +37,24 @@ namespace Aurora::RNG
WELL_NextBytes(&gWellRand, in, length);
}
AUKN_SYM AuString ReadString(AuUInt32 length, ERngStringCharacters type)
{
return gFastDevice->NextString(length, type);
}
AUKN_SYM void RngString(char *string, AuUInt32 length, ERngStringCharacters type)
{
gFastDevice->NextString(string, length, type);
}
AUKN_SYM AuUInt8 RngByte()
{
return gFastDevice->NextByte();
}
AUKN_SYM bool RngBoolean()
{
return gFastDevice->NextBoolean();
}
AUKN_SYM AuUInt32 RngU32()
{
return gFastDevice->NextU32();
}
AUKN_SYM AuUInt32 RngU32(AuUInt32 min, AuUInt32 max)
{
return gFastDevice->NextU32(min, max);
}
AUKN_SYM AuUInt64 RngU64()
{
return gFastDevice->NextU64();
}
AUKN_SYM AuInt32 RngInt(AuInt32 min, AuInt32 max)
{
return gFastDevice->NextInt(min, max);
}
AUKN_SYM double RngDecimal()
{
return gFastDevice->NextDecimal();
}
AUKN_SYM float RngNumber(float min, float max)
{
return gFastDevice->NextNumber(min, max);
}
AUKN_SYM AuUInt32 RngIndex(AuUInt32 count /* = max + 1*/)
{
return gFastDevice->NextIndex(count);
}
static void InitFastRng()
{
AuArray<AuUInt8, 64> maxEntropy;
RngFillArray<false, AuUInt8>(maxEntropy.data(), 64);
gWellRand = WELL_SeedRandBig64(maxEntropy);
RandomDef fast; //intentionally null def
RandomDef fast;
fast.secure = false;
gFastDevice = RandomUnique(fast);
}
void Init()
{
InitRandPlatform();
EntropyInit();
InitFastRng();
}
void Release()
{
#if defined(AURORA_IS_POSIX_DERIVED)
if (gDevURand != NULL)
fclose(gDevURand);
#elif defined(AURORA_IS_MODERNNT_DERIVED) && defined(USE_OLD_NTCRYPT)
CryptReleaseContext(gCryptoProv, 0);
#endif
EntropyDeinit();
}
}

View File

@ -9,6 +9,7 @@
namespace Aurora::RNG
{
extern RandomUnique_t gFastDevice;
void Init();
void Release();
}

191
Source/RNG/RNGEntropy.cpp Normal file
View File

@ -0,0 +1,191 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RNGEntropy.cpp
Date: 2022-9-17
File: RNG.cpp
Date: 2021-6-11
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "RNG.hpp"
#include "RNGEntropy.hpp"
#if defined(AURORA_PLATFORM_WIN32)
#include <wincrypt.h>
#include <bcrypt.h>
#include <bcrypt.h>
#endif
#if defined(AURORA_IS_POSIX_DERIVED)
#include <cstdio>
#endif
#include "WELL.hpp"
namespace Aurora::RNG
{
#if defined(AURORA_IS_POSIX_DERIVED)
static int gDevURand;
void EntropyInit()
{
gDevURand = ::open("/dev/urandom", O_RDONLY);
if (gDevURand <= 0)
{
gDevURand = ::open("/dev/random", O_RDONLY);
}
if (gDevURand <= 0)
{
gDevURand = -1;
}
}
static AuUInt32 RngUnix(AuUInt8 *buf, AuUInt32 len)
{
if (gDevURand == -1)
{
return 0;
}
return ::read(gDevURand, buf, len);
}
#elif defined(AURORA_IS_MODERNNT_DERIVED)
#if defined(USE_OLD_NTCRYPT)
static HCRYPTPROV gCryptoProv;
#endif
void EntropyInit()
{
#if defined(USE_OLD_NTCRYPT)
if (!CryptAcquireContext(&gCryptoProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)))
{
if (!CryptAcquireContext(&gCryptoProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
{
gCryptoProv = 0;
}
}
#endif
}
static AuUInt32 RngWin32(AuUInt8 *buf, AuUInt32 len)
{
#if defined(USE_OLD_NTCRYPT)
if (!gCryptoProv)
{
return 0;
}
if (!::CryptGenRandom(gCryptoProv, len, buf))
{
return 0;
}
return len;
#else
#if !defined(AURORA_DONT_PREFER_WIN32_USERLAND_AES_RNG)
if (::BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, reinterpret_cast<PUCHAR>(buf), len, 0) == 0)
{
return len;
}
#endif
if (::BCryptGenRandom(NULL, reinterpret_cast<PUCHAR>(buf), len, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0)
{
return len;
}
return 0;
#endif
}
#else
void EntropyInit()
{
}
#endif
static AuUInt32 RngStdC(AuUInt8 *buf, AuUInt32 len)
{
clock_t t1;
int l, acc, bits, a, b;
l = len;
acc = a = b = 0;
bits = 8;
while (len--)
{
while (bits--) // for each bit in byte
{
do
{
t1 = clock();
while (t1 == clock()) // spin within the resolution of 1 C clock() tick
{
a ^= 1; // flip
}
t1 = clock();
while (t1 == clock())
{
b ^= 1; // flip
}
} while (a == b); // ensure theres enough entropy for a deviation to occur
acc = (acc << 1) | a; // push the first bit state
}
*buf++ = acc;
acc = 0;
bits = 8;
}
return l;
}
AuUInt32 RngGetBytes(AuUInt8 *out, AuUInt32 outlen)
{
AuUInt32 x;
#if defined(AURORA_IS_MODERNNT_DERIVED)
x = RngWin32(out, outlen);
if (x != 0)
{
return x;
}
#elif defined(AURORA_IS_POSIX_DERIVED)
x = RngUnix(out, outlen);
if (x != 0)
{
return x;
}
#endif
x = RngStdC(out, outlen);
if (x != 0)
{
return x;
}
return 0;
}
void EntropyDeinit()
{
#if defined(AURORA_IS_POSIX_DERIVED)
if (gDevURand <= 0)
{
::close(gDevURand);
}
#elif defined(AURORA_IS_MODERNNT_DERIVED) && defined(USE_OLD_NTCRYPT)
CryptReleaseContext(gCryptoProv, 0);
#endif
}
}

16
Source/RNG/RNGEntropy.hpp Normal file
View File

@ -0,0 +1,16 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RNGEntropy.hpp
Date: 2022-9-17
Author: Reece
***/
#pragma once
namespace Aurora::RNG
{
void EntropyInit();
void EntropyDeinit();
AuUInt32 RngGetBytes(AuUInt8 *out, AuUInt32 outlen);
}

View File

@ -0,0 +1,70 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RNGStaticUtilities.cpp
Date: 2022-9-17
File: RNG.cpp
Date: 2021-6-11
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "RNG.hpp"
#include "RNGStaticUtilities.hpp"
namespace Aurora::RNG
{
AUKN_SYM AuString ReadString(AuUInt32 length, ERngStringCharacters type)
{
return gFastDevice->NextString(length, type);
}
AUKN_SYM void RngString(char *string, AuUInt32 length, ERngStringCharacters type)
{
gFastDevice->NextString(string, length, type);
}
AUKN_SYM AuUInt8 RngByte()
{
return gFastDevice->NextByte();
}
AUKN_SYM bool RngBoolean()
{
return gFastDevice->NextBoolean();
}
AUKN_SYM AuUInt32 RngU32()
{
return gFastDevice->NextU32();
}
AUKN_SYM AuUInt32 RngU32(AuUInt32 min, AuUInt32 max)
{
return gFastDevice->NextU32(min, max);
}
AUKN_SYM AuUInt64 RngU64()
{
return gFastDevice->NextU64();
}
AUKN_SYM AuInt32 RngInt(AuInt32 min, AuInt32 max)
{
return gFastDevice->NextInt(min, max);
}
AUKN_SYM double RngDecimal()
{
return gFastDevice->NextDecimal();
}
AUKN_SYM float RngNumber(float min, float max)
{
return gFastDevice->NextNumber(min, max);
}
AUKN_SYM AuUInt32 RngIndex(AuUInt32 count /* = max + 1*/)
{
return gFastDevice->NextIndex(count);
}
}

View File

@ -0,0 +1,13 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RNGStaticUtilities.hpp
Date: 2022-9-17
Author: Reece
***/
#pragma once
namespace Aurora::RNG
{
}

View File

@ -11,9 +11,8 @@
namespace Aurora::RNG
{
class RandomDevice : public IRandomDevice
struct RandomDevice : IRandomDevice
{
public:
void Read(void *in, AuUInt32 length) override;
AuString NextString(AuUInt32 length, ERngStringCharacters type) override;
@ -38,6 +37,8 @@ namespace Aurora::RNG
void RandomDevice::Init(const RandomDef &def)
{
this->def_ = def;
// Gross...
if (!def.secure)
{
if (def.seed)
@ -158,19 +159,19 @@ namespace Aurora::RNG
AUKN_SYM IRandomDevice *RandomNew(const Aurora::RNG::RandomDef &def)
{
auto device = _new RandomDevice();
if (!device)
auto pDevice = _new RandomDevice();
if (!pDevice)
{
return nullptr;
}
device->Init(def);
pDevice->Init(def);
return device;
return pDevice;
}
AUKN_SYM void RandomRelease(IRandomDevice *stream)
AUKN_SYM void RandomRelease(IRandomDevice *pStream)
{
AuSafeDelete<RandomDevice*>(stream);
AuSafeDelete<RandomDevice*>(pStream);
}
}