[+] 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:
parent
8844e8fe64
commit
8a2947ffc5
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -31,4 +31,7 @@ namespace Aurora::Crypto
|
||||
#include "CA/CA.hpp"
|
||||
#include "ECC/ECC.hpp"
|
||||
#include "PEM/PEM.hpp"
|
||||
#include "RSA/RSA.hpp"
|
||||
#include "RSA/RSA.hpp"
|
||||
#include "BCrypt/BCrypt.hpp"
|
||||
#include "HMAC/HMAC.hpp"
|
||||
#include "HashCash/HashCash.hpp"
|
@ -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
|
||||
));
|
||||
}
|
35
Include/Aurora/Crypto/HMAC/HMAC.hpp
Normal file
35
Include/Aurora/Crypto/HMAC/HMAC.hpp
Normal 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);
|
||||
}
|
19
Include/Aurora/Crypto/HashCash/HashCash.hpp
Normal file
19
Include/Aurora/Crypto/HashCash/HashCash.hpp
Normal 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);
|
||||
}
|
@ -18,9 +18,19 @@ namespace Aurora::Hashing
|
||||
AUKN_SYM void Tiger(const Memory::MemoryViewRead &toHash, AuArray<AuUInt8, 24> &tiger);
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
@ -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();
|
@ -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"
|
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
88
Source/Crypto/HMAC/HMAC.cpp
Normal file
88
Source/Crypto/HMAC/HMAC.cpp
Normal 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);
|
||||
}
|
||||
}
|
30
Source/Crypto/HMAC/HMAC.hpp
Normal file
30
Source/Crypto/HMAC/HMAC.hpp
Normal 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_ {};
|
||||
};
|
||||
}
|
61
Source/Crypto/HashCash/HashCash.cpp
Normal file
61
Source/Crypto/HashCash/HashCash.cpp
Normal 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;
|
||||
}
|
||||
}
|
10
Source/Crypto/HashCash/HashCash.hpp
Normal file
10
Source/Crypto/HashCash/HashCash.hpp
Normal 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>
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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_ {};
|
||||
};
|
||||
}
|
@ -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)
|
||||
|
@ -7,185 +7,19 @@
|
||||
***/
|
||||
#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)
|
||||
{
|
||||
AuUInt32 offset;
|
||||
AuUInt8 *headPtr;
|
||||
|
||||
|
||||
headPtr = reinterpret_cast<AuUInt8 *>(in);
|
||||
offset = 0;
|
||||
|
||||
@ -197,90 +31,30 @@ namespace Aurora::RNG
|
||||
offset += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AUKN_SYM void ReadFastRNG(void *in, AuUInt32 length)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
|
||||
namespace Aurora::RNG
|
||||
{
|
||||
extern RandomUnique_t gFastDevice;
|
||||
void Init();
|
||||
void Release();
|
||||
}
|
191
Source/RNG/RNGEntropy.cpp
Normal file
191
Source/RNG/RNGEntropy.cpp
Normal 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
16
Source/RNG/RNGEntropy.hpp
Normal 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);
|
||||
}
|
70
Source/RNG/RNGStaticUtilities.cpp
Normal file
70
Source/RNG/RNGStaticUtilities.cpp
Normal 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);
|
||||
}
|
||||
}
|
13
Source/RNG/RNGStaticUtilities.hpp
Normal file
13
Source/RNG/RNGStaticUtilities.hpp
Normal 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
|
||||
{
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user