/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: BCrypt.cpp Date: 2022-9-15 Author: Reece ***/ #include #include "BCrypt.hpp" extern "C" { #include "crypt_blowfish.h" } namespace Aurora::Crypto::BCrypt { static const int kMinBCryptRounds = 10; AUKN_SYM int GetForcedMinRounds() { return kMinBCryptRounds; } AUKN_SYM AuString GenSalt(int rounds) { char seed[16]; char cryptLength[31]; AuRng::RngFillArray(seed); rounds = AuMin(rounds, 31); rounds = AuMax(rounds, kMinBCryptRounds); auto ptr = _crypt_gensalt_blowfish_rn("$2a$", rounds, seed, 16, cryptLength, AuArraySize(cryptLength)); SysAssert(ptr, "?"); return ptr; } AUKN_SYM AuString HashPW(const AuString &password, const AuString &salt) { return HashPWEx({ password.c_str(), password.size() + 1 }, salt); } AUKN_SYM AuString HashPWEx(const Memory::MemoryViewRead &password, const AuString &salt) { if (password.length > 72) { SysPushErrorCrypt("BCrypt password cannot be greater than 72 characters"); return {}; } char cryptBuffer[62] { 0 }; char *pRet; if (!(pRet = crypt_rn(password.Begin(), password.length, salt.c_str(), cryptBuffer, AuArraySize(cryptBuffer)))) { SysPushErrorCrypto("bcrypt failed"); return {}; } return pRet; } AUKN_SYM bool CheckPassword(const AuString &password, const AuString &hashedPassword) { return CheckPasswordEx({ password.c_str(), password.size() + 1 }, hashedPassword); } AUKN_SYM bool CheckPasswordEx(const Memory::MemoryViewRead &password, const AuString &hashedPassword) { if (password.length == 0) { return false; } if (hashedPassword.empty()) { return false; } char cryptBuffer[62] { 0 }; char *pRet; if (!(pRet = crypt_rn(password.Begin(), password.length, hashedPassword.c_str(), cryptBuffer, AuArraySize(cryptBuffer)))) { SysPushErrorCrypto("bcrypt failed"); return {}; } // I don't care about safe eval... return cryptBuffer == hashedPassword; } }