Use cryptographic-strength RNG for password nonce
rand() and srand() are crap. We can't fix the existing MD5 password hashing but it will go away when Bcrypt password hashing goes live on the Forums.
This commit is contained in:
parent
0407ee40ac
commit
4c77b5c418
4 changed files with 60 additions and 5 deletions
|
@ -278,9 +278,9 @@ std::pair<wesnothd_connection_ptr, config> open_connection(std::string host)
|
|||
try {
|
||||
auto bcrypt_salt = utils::bcrypt::from_salted_salt(salt);
|
||||
auto hash = utils::bcrypt::hash_pw(password, bcrypt_salt);
|
||||
std::string outer_salt = salt.substr(bcrypt_salt.iteration_count_delim_pos + 23, 8);
|
||||
if(outer_salt.size() != 8)
|
||||
throw utils::hash_error("salt too small");
|
||||
std::string outer_salt = salt.substr(bcrypt_salt.iteration_count_delim_pos + 23);
|
||||
if(outer_salt.size() != 32)
|
||||
throw utils::hash_error("salt wrong size");
|
||||
sp["password"] = utils::md5(hash.base64_digest(), outer_salt).base64_digest();
|
||||
} catch(utils::hash_error& err) {
|
||||
ERR_MP << "bcrypt hash failed: " << err.what() << std::endl;
|
||||
|
|
|
@ -787,8 +787,14 @@ void server::handle_login(socket_ptr socket, std::shared_ptr<simple_wml::documen
|
|||
void server::send_password_request(socket_ptr socket, const std::string& msg,
|
||||
const std::string& user, const char* error_code, bool force_confirmation)
|
||||
{
|
||||
std::string salt = user_handler_->create_salt();
|
||||
std::string pepper = user_handler_->create_pepper(user);
|
||||
// If using crypt_blowfish, use 32 random Base64 characters, cryptographic-strength, 192 bits entropy
|
||||
// else (phppass, MD5, $H$), use 8 random integer digits, not secure, do not use, this is crap, 29.8 bits entropy
|
||||
std::string salt {
|
||||
/* if */ (pepper[1] == '2')
|
||||
/* then */ ? user_handler_->create_secure_salt()
|
||||
/* else */ : user_handler_->create_salt()
|
||||
};
|
||||
std::string spices = pepper + salt;
|
||||
if(user_handler_->use_phpbb_encryption() && pepper.empty()) {
|
||||
async_send_error(socket, "Even though your nickname is registered on this server you "
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "server/user_handler.hpp"
|
||||
#include "config.hpp"
|
||||
#include "random.hpp"
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
|
@ -49,3 +50,50 @@ std::string user_handler::create_salt(int length) {
|
|||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// TODO - This really should be a common function.
|
||||
// This is duplicated in two or three other places.
|
||||
// Some are virtual member functions.
|
||||
namespace {
|
||||
const std::string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ;
|
||||
|
||||
std::string encode_hash(const unsigned char* input, unsigned int len) {
|
||||
std::string encoded_hash;
|
||||
|
||||
unsigned int i = 0;
|
||||
do {
|
||||
unsigned value = input[i++];
|
||||
encoded_hash.append(itoa64.substr(value & 0x3f,1));
|
||||
if(i < len)
|
||||
value |= static_cast<int>(input[i]) << 8;
|
||||
encoded_hash.append(itoa64.substr((value >> 6) & 0x3f,1));
|
||||
if(i++ >= len)
|
||||
break;
|
||||
if(i < len)
|
||||
value |= static_cast<int>(input[i]) << 16;
|
||||
encoded_hash.append(itoa64.substr((value >> 12) & 0x3f,1));
|
||||
if(i++ >= len)
|
||||
break;
|
||||
encoded_hash.append(itoa64.substr((value >> 18) & 0x3f,1));
|
||||
} while (i < len);
|
||||
|
||||
return encoded_hash;
|
||||
}
|
||||
|
||||
class RAND_bytes_exception: public std::exception
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
std::string user_handler::create_secure_salt()
|
||||
{
|
||||
// Must be full base64 encodings (3 bytes = 4 chars) else we skew the PRNG results
|
||||
unsigned char buf [((3 * 32) / 4)];
|
||||
|
||||
if(!RAND_bytes(buf, sizeof(buf))) {
|
||||
throw RAND_bytes_exception();
|
||||
}
|
||||
|
||||
return encode_hash(buf, sizeof(buf));
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,8 @@ class user_handler {
|
|||
void init_mailer(const config &c);
|
||||
|
||||
/** Create a random string of digits for password encryption. */
|
||||
std::string create_salt(int length =8);
|
||||
std::string create_salt(int length = 8);
|
||||
std::string create_secure_salt();
|
||||
|
||||
/**
|
||||
* Create custom salt.
|
||||
|
|
Loading…
Add table
Reference in a new issue