Created
April 20, 2020 12:44
-
-
Save madmongo1/53c303c6fe8de64f93adc014c7671d51 to your computer and use it in GitHub Desktop.
Minecraft hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* HEADER FILE | |
*/ | |
// | |
// Copyright (c) 2020 Richard Hodges (hodges.r@gmail.com) | |
// | |
// Official repository: https://github.com/AlexAndDad/gateway | |
// | |
#pragma once | |
#include "minecraft/net.hpp" | |
#include <openssl/sha.h> | |
#include <string> | |
namespace minecraft::protocol | |
{ | |
struct daft_hash_impl | |
{ | |
daft_hash_impl() | |
: ctx_ {} | |
{ | |
SHA1_Init(&ctx_); | |
} | |
daft_hash_impl(daft_hash_impl const &) = delete; | |
daft_hash_impl(daft_hash_impl &&) = delete; | |
daft_hash_impl &operator=(daft_hash_impl const &) = delete; | |
daft_hash_impl &operator=(daft_hash_impl &&) = delete; | |
~daft_hash_impl() {} | |
void update(net::const_buffer in) { SHA1_Update(&ctx_, in.data(), in.size()); } | |
std::string finalise(); | |
private: | |
SHA_CTX ctx_; | |
}; | |
} // namespace minecraft::protocol | |
/* | |
* CPP FILE | |
*/ | |
// | |
// Copyright (c) 2020 Richard Hodges (hodges.r@gmail.com) | |
// | |
// Official repository: https://github.com/AlexAndDad/gateway | |
// | |
#include "minecraft/protocol/daft_hash.hpp" | |
#include <algorithm> | |
#include <array> | |
#include <string_view> | |
#include <boost/algorithm/string/case_conv.hpp> | |
#include <openssl/bn.h> | |
namespace minecraft::protocol | |
{ | |
std::string daft_hash_impl::finalise() | |
{ | |
auto result = std::string(); | |
auto buf = std::array< std::uint8_t, 20 >(); | |
SHA1_Final(buf.data(), &ctx_); | |
// convert has to bignum | |
BIGNUM *bn = BN_bin2bn(buf.data(), buf.size(), nullptr); | |
// reset the hasher for next use | |
SHA1_Init(&ctx_); | |
// check for "negative" value | |
if (BN_is_bit_set(bn, 159)) | |
{ | |
result += '-'; | |
// perform 1's compliment on the bignum's bits | |
auto tmp = std::vector< unsigned char >(BN_num_bytes(bn)); | |
BN_bn2bin(bn, tmp.data()); | |
std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char b) { return ~b; }); | |
BN_bin2bn(tmp.data(), tmp.size(), bn); | |
// add 1 "as-if" 2's compliment | |
BN_add_word(bn, 1); | |
} | |
// convert to hex | |
auto hex = BN_bn2hex(bn); | |
// remove any leading zeroes except the last | |
auto view = std::string_view(hex); | |
while (view.size() && view[0] == '0') | |
view = view.substr(1); | |
// append the hex to the result | |
result.append(view.begin(), view.end()); | |
OPENSSL_free(hex); | |
BN_free(bn); | |
// convert the hex to lower case | |
boost::to_lower(result); | |
return result; | |
} | |
} // namespace minecraft::protocol | |
/* | |
* TEST FILE | |
*/ | |
// | |
// Copyright (c) 2020 Richard Hodges (hodges.r@gmail.com) | |
// | |
// Official repository: https://github.com/AlexAndDad/gateway | |
// | |
#include <catch2/catch.hpp> | |
#include "minecraft/protocol/daft_hash.hpp" | |
using namespace minecraft; | |
TEST_CASE("minecraft::protocol::daft_hash") | |
{ | |
protocol::daft_hash_impl hasher; | |
// | |
// Check class Notch | |
// | |
hasher.update(net::buffer(std::string("Notch"))); | |
auto result = hasher.finalise(); | |
CHECK(result == "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48"); | |
// | |
// Check repeatable | |
// | |
hasher.update(net::buffer(std::string("Notch"))); | |
result = hasher.finalise(); | |
CHECK(result == "4ed1f46bbe04bc756bcb17c0c7ce3e4632f06a48"); | |
// | |
// Negative hash | |
// | |
hasher.update(net::buffer(std::string("jeb_"))); | |
result = hasher.finalise(); | |
CHECK(result == "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1"); | |
hasher.update(net::buffer(std::string("j"))); | |
hasher.update(net::buffer(std::string("e"))); | |
hasher.update(net::buffer(std::string("b"))); | |
hasher.update(net::buffer(std::string("_"))); | |
result = hasher.finalise(); | |
CHECK(result == "-7c9d5b0044c130109a5d7b5fb5c317c02b4e28c1"); | |
// | |
// simon | |
// | |
hasher.update(net::buffer(std::string("simon"))); | |
result = hasher.finalise(); | |
CHECK(result == "88e16a1019277b15d58faf0541e11910eb756f6"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment