Add OpenSSL's libcrypto as a dependency

This also removes the included SHA1 and MD5 implementations
in favour of those from OpenSSL.

Thanks to @jyrkive for helping to get the CMake build working and
ensuring the game still compiles with OpenSSL 1.1.0.
(The SHA_xxx() aliases were removed in OpenSSL 1.1.0.)
This commit is contained in:
Celtic Minstrel 2017-04-30 14:36:08 -04:00
parent 9365538b3b
commit c9191c9812
22 changed files with 135 additions and 780 deletions

View file

@ -50,6 +50,9 @@ before_install:
install:
- travis_wait ./utils/travis/install_deps.sh
- if [ "$TRAVIS_OS_NAME" = osx ]; then
export CXXFLAGS="-I/usr/local/opt/openssl/include $CFLAGS" LDFLAGS="-L/usr/local/opt/openssl/lib $LDFLAGS";
fi
script:
- ./utils/travis/check_utf8.sh

View file

@ -74,6 +74,7 @@ else()
find_package(SDL2 2.0.4 REQUIRED)
endif()
find_package(Crypto 1.0 REQUIRED)
find_package(Boost 1.36 REQUIRED COMPONENTS iostreams program_options regex system thread)
find_package(Boost 1.40 REQUIRED COMPONENTS random)
@ -643,7 +644,7 @@ if(ENABLE_GAME OR ENABLE_TESTS)
pkg_check_modules( CAIRO REQUIRED cairo>=1.10 )
pkg_check_modules( PANGOCAIRO REQUIRED pangocairo>=1.21.3 )
pkg_check_modules( FONTCONFIG REQUIRED fontconfig>=2.4.1 )
pkg_check_modules( SYSTEMD systemd )
pkg_check_modules( SYSTEMD systemd )
endif(NOT MSVC)
endif(ENABLE_GAME OR ENABLE_TESTS)

View file

@ -37,6 +37,7 @@ order to build Wesnoth:
* Vorbisfile
* libbz2
* libz
* libcrypto (from OpenSSL)
The following libraries are optional dependencies that enable additional
features:

View file

@ -363,6 +363,7 @@ if env["prereqs"]:
have_server_prereqs = (\
CheckIEEE754(conf) & \
conf.CheckCPlusPlus(gcc_version = "4.8") & \
conf.CheckLib("libcrypto") & \
conf.CheckBoost("iostreams", require_version = boost_version) & \
conf.CheckBoostIostreamsGZip() & \
conf.CheckBoostIostreamsBZip2() & \

11
cmake/FindCrypto.cmake Normal file
View file

@ -0,0 +1,11 @@
# OpenSSL crypto library
find_path(CRYPTO_INCLUDE_DIR openssl/md5.h)
find_library(CRYPTO_LIBRARY crypto)
# handle the QUIETLY and REQUIRED arguments and set XXX_FOUND to TRUE if all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CRYPTO DEFAULT_MSG CRYPTO_LIBRARY CRYPTO_INCLUDE_DIR)
mark_as_advanced(CRYPTO_INCLUDE_DIR CRYPTO_LIBRARY)

View file

@ -52,7 +52,7 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\external\lib</AdditionalLibraryDirectories>
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Shlwapi.lib;libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -70,7 +70,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>..\..\..\external\lib</AdditionalLibraryDirectories>
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Shlwapi.lib;libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@ -85,7 +85,6 @@
<ClInclude Include="..\..\src\campaign_server\campaign_server.hpp" />
<ClInclude Include="..\..\src\campaign_server\control.hpp" />
<ClInclude Include="..\..\src\hash.hpp" />
<ClInclude Include="..\..\src\md5.hpp" />
<ClInclude Include="..\..\src\server\server_base.hpp" />
<ClInclude Include="..\..\src\server\simple_wml.hpp" />
</ItemGroup>
@ -105,9 +104,6 @@
<ClCompile Include="..\..\src\hash.cpp">
<ObjectFileName>$(IntDir)</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\md5.cpp">
<ObjectFileName>$(IntDir)</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\server\server_base.cpp">
<ObjectFileName>$(IntDir)Server\</ObjectFileName>
</ClCompile>

View file

@ -34,7 +34,6 @@
<Filter>Campaign_Server</Filter>
</ClInclude>
<ClInclude Include="..\..\src\hash.hpp" />
<ClInclude Include="..\..\src\md5.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\addon\validation.cpp">
@ -56,6 +55,5 @@
<Filter>Campaign_Server</Filter>
</ClCompile>
<ClCompile Include="..\..\src\hash.cpp" />
<ClCompile Include="..\..\src\md5.cpp" />
</ItemGroup>
</Project>

View file

@ -136,7 +136,7 @@
</ResourceCompile>
<Link>
<AdditionalOptions>/SAFESEH:NO %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;$(IntDir)liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;libeay32.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;$(IntDir)liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\external\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>MSVCR90;MSVCRT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -175,7 +175,7 @@
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Link>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;$(IntDir)liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;libeay32.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;$(IntDir)liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\external\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
@ -215,7 +215,7 @@
<PreprocessorDefinitions>_MSC_VER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;Debug\liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;libeay32.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;Debug\liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)test.exe</OutputFile>
<AdditionalLibraryDirectories>..\..\..\external\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -254,7 +254,7 @@
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Link>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;Release\liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;libeay32.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;Release\liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)test.exe</OutputFile>
<AdditionalLibraryDirectories>..\..\..\external\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
@ -300,7 +300,7 @@
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
<Link>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;$(IntDir)liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>SDL2main.lib;SDL2.lib;SDL2_image.lib;SDL2_ttf.lib;SDL2_mixer.lib;SDL2_net.lib;libeay32.lib;cairo.lib;winmm.lib;ws2_32.lib;pango-1.0.lib;pangocairo-1.0.lib;gobject-2.0.lib;glib-2.0.lib;libpng.lib;$(IntDir)liblua.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\external\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
@ -2478,7 +2478,6 @@
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)Map\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)Map\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\md5.cpp" />
<ClCompile Include="..\..\src\menu_events.cpp" />
<ClCompile Include="..\..\src\minimap.cpp" />
<ClCompile Include="..\..\src\mouse_events.cpp" />
@ -3281,13 +3280,6 @@
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)utils\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)utils\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\utils\sha1.cpp">
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)utils\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='ReleaseDEBUG|Win32'">$(IntDir)utils\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)utils\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Debug|Win32'">$(IntDir)utils\</ObjectFileName>
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Test_Release|Win32'">$(IntDir)utils\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\..\src\variable.cpp" />
<ClCompile Include="..\..\src\variable_info.cpp" />
<ClCompile Include="..\..\src\video.cpp" />
@ -3834,7 +3826,6 @@
<ClInclude Include="..\..\src\map\location.hpp" />
<ClInclude Include="..\..\src\map\map.hpp" />
<ClInclude Include="..\..\src\map_command_handler.hpp" />
<ClInclude Include="..\..\src\md5.hpp" />
<ClInclude Include="..\..\src\menu_events.hpp" />
<ClInclude Include="..\..\src\minimap.hpp" />
<ClInclude Include="..\..\src\mouse_events.hpp" />
@ -3995,7 +3986,6 @@
<ClInclude Include="..\..\src\utils\name_generator.hpp" />
<ClInclude Include="..\..\src\utils\name_generator_factory.hpp" />
<ClInclude Include="..\..\src\utils\reference_counter.hpp" />
<ClInclude Include="..\..\src\utils\sha1.hpp" />
<ClInclude Include="..\..\src\utils\smart_list.hpp" />
<ClInclude Include="..\..\src\variable.hpp" />
<ClInclude Include="..\..\src\variable_info.hpp" />

View file

@ -998,9 +998,6 @@
<ClCompile Include="..\..\src\utils\name_generator_factory.cpp">
<Filter>utils</Filter>
</ClCompile>
<ClCompile Include="..\..\src\utils\sha1.cpp">
<Filter>utils</Filter>
</ClCompile>
<ClCompile Include="..\..\src\serialization\tag.cpp">
<Filter>serialization</Filter>
</ClCompile>
@ -1438,7 +1435,6 @@
<ClCompile Include="..\..\src\key.cpp" />
<ClCompile Include="..\..\src\language.cpp" />
<ClCompile Include="..\..\src\lua_jailbreak_exception.cpp" />
<ClCompile Include="..\..\src\md5.cpp" />
<ClCompile Include="..\..\src\menu_events.cpp" />
<ClCompile Include="..\..\src\minimap.cpp" />
<ClCompile Include="..\..\src\mouse_events.cpp" />
@ -2480,9 +2476,6 @@
<ClInclude Include="..\..\src\utils\reference_counter.hpp">
<Filter>utils</Filter>
</ClInclude>
<ClInclude Include="..\..\src\utils\sha1.hpp">
<Filter>utils</Filter>
</ClInclude>
<ClInclude Include="..\..\src\utils\smart_list.hpp">
<Filter>utils</Filter>
</ClInclude>
@ -2854,7 +2847,6 @@
<ClInclude Include="..\..\src\language.hpp" />
<ClInclude Include="..\..\src\lua_jailbreak_exception.hpp" />
<ClInclude Include="..\..\src\map_command_handler.hpp" />
<ClInclude Include="..\..\src\md5.hpp" />
<ClInclude Include="..\..\src\menu_events.hpp" />
<ClInclude Include="..\..\src\minimap.hpp" />
<ClInclude Include="..\..\src\mouse_events.hpp" />

View file

@ -10,7 +10,6 @@ hash.cpp
log.cpp
map/location.cpp
map/map.cpp
md5.cpp
mt_rng.cpp
seed_rng.cpp
serialization/binary_or_text.cpp

View file

@ -387,7 +387,6 @@ units/unit.cpp
utils/context_free_grammar_generator.cpp
utils/markov_generator.cpp
utils/name_generator_factory.cpp
utils/sha1.cpp
variable.cpp
variable_info.cpp
wesnothd_connection.cpp

View file

@ -93,6 +93,7 @@ set(common-external-libs
set(game-external-libs
${common-external-libs}
${CRYPTO_LIBRARY}
${Boost_SYSTEM_LIBRARIES}
${Boost_RANDOM_LIBRARY}
${Boost_THREAD_LIBRARY}

View file

@ -70,7 +70,7 @@ namespace {
/* Secure password storage functions */
bool authenticate(config& campaign, const config::attribute_value& passphrase)
{
return utils::create_hash(passphrase, campaign["passsalt"]) == campaign["passhash"];
return utils::md5(passphrase, campaign["passsalt"]).hex_digest() == campaign["passhash"];
}
std::string generate_salt(size_t len)
@ -92,7 +92,7 @@ void set_passphrase(config& campaign, std::string passphrase)
{
std::string salt = generate_salt(16);
campaign["passsalt"] = salt;
campaign["passhash"] = utils::create_hash(passphrase, salt);
campaign["passhash"] = utils::md5(passphrase, salt).hex_digest();
}
} // end anonymous namespace

View file

@ -19,7 +19,7 @@
#include "gettext.hpp"
#include "game_config.hpp"
#include "log.hpp"
#include "utils/sha1.hpp"
#include "hash.hpp"
#include "serialization/binary_or_text.hpp"
#include "serialization/parser.hpp"
#include "serialization/string_utils.hpp"
@ -166,7 +166,7 @@ void config_cache::read_cache(const std::string& file_path, config& cfg)
// Use a hash for a shorter display of the defines.
const std::string fname = cache_path + "/" +
cache_file_prefix_ +
sha1_hash(defines_string.str()).display();
utils::sha1(defines_string.str()).hex_digest();
const std::string fname_checksum = fname + ".checksum" + extension;
filesystem::file_tree_checksum dir_checksum;

View file

@ -226,8 +226,8 @@ static std::unique_ptr<wesnothd_connection> open_connection(CVideo& video, const
throw wesnothd_error(_("Bad data received from server"));
}
sp["password"] = utils::create_hash(utils::create_hash(password, utils::get_salt(salt),
utils::get_iteration_count(salt)), salt.substr(12, 8));
sp["password"] = utils::md5(utils::md5(password, utils::md5::get_salt(salt),
utils::md5::get_iteration_count(salt)).hex_digest(), salt.substr(12, 8)).hex_digest();
} else {
sp["password"] = password;

View file

@ -12,33 +12,66 @@
See the COPYING file for more details.
*/
#include "hash.hpp"
#include <iostream>
#include <string>
#include "md5.hpp"
#include "hash.hpp"
#include <openssl/sha.h>
#include <openssl/md5.h>
namespace utils {
static_assert(utils::md5::DIGEST_SIZE == MD5_DIGEST_LENGTH, "Constants mismatch");
static_assert(utils::sha1::DIGEST_SIZE == SHA_DIGEST_LENGTH, "Constants mismatch");
namespace {
const std::string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ;
const std::string hash_prefix = "$H$";
std::array<uint8_t, 16> md5(const std::string& input) {
MD5 md5_worker;
md5_worker.update(reinterpret_cast<const uint8_t*>(input.data()), input.size());
md5_worker.finalize();
return md5_worker.raw_digest();
template<size_t len>
std::string encode_hash(const std::array<uint8_t, len>& input) {
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;
}
int get_iteration_count(const std::string& hash) {
}
namespace utils {
md5::md5(const std::string& input) {
MD5_CTX md5_worker;
MD5_Init(&md5_worker);
MD5_Update(&md5_worker, input.data(), input.size());
MD5_Final(hash.data(), &md5_worker);
}
int md5::get_iteration_count(const std::string& hash) {
return itoa64.find_first_of(hash[3]);
}
std::string get_salt(const std::string& hash) {
std::string md5::get_salt(const std::string& hash) {
return hash.substr(4,8);
}
bool is_valid_hash(const std::string& hash) {
bool md5::is_valid_hash(const std::string& hash) {
if(hash.size() != 34) return false;
if(hash.substr(0,3) != hash_prefix) return false;
@ -48,38 +81,32 @@ bool is_valid_hash(const std::string& hash) {
return true;
}
std::string encode_hash(const std::array<uint8_t, 16>& input) {
std::string encoded_hash;
unsigned int i = 0;
do {
unsigned value = input[i++];
encoded_hash.append(itoa64.substr(value & 0x3f,1));
if(i < 16)
value |= static_cast<int>(input[i]) << 8;
encoded_hash.append(itoa64.substr((value >> 6) & 0x3f,1));
if(i++ >= 16)
break;
if(i < 16)
value |= static_cast<int>(input[i]) << 16;
encoded_hash.append(itoa64.substr((value >> 12) & 0x3f,1));
if(i++ >= 16)
break;
encoded_hash.append(itoa64.substr((value >> 18) & 0x3f,1));
} while (i < 16);
return encoded_hash;
}
std::string create_hash(const std::string& password, const std::string& salt, int iteration_count) {
md5::md5(const std::string& password, const std::string& salt, int iteration_count)
{
iteration_count = 1 << iteration_count;
std::array<uint8_t, 16> output = md5(salt + password);
hash = md5(salt + password).raw_digest();
do {
output = md5(std::string(output.begin(), output.end()).append(password));
hash = md5(std::string(hash.begin(), hash.end()).append(password)).raw_digest();
} while(--iteration_count);
}
return encode_hash(output);
std::string md5::hex_digest() const
{
return encode_hash<DIGEST_SIZE>(hash);
}
sha1::sha1(const std::string& str)
{
SHA_CTX hasher;
SHA1_Init(&hasher);
SHA1_Update(&hasher, str.data(), str.size());
SHA1_Final(hash.data(), &hasher);
}
std::string sha1::hex_digest() const
{
return encode_hash<DIGEST_SIZE>(hash);
}
} // namespace utils

View file

@ -18,20 +18,43 @@
#include <cstdint>
#include <string>
#include "global.hpp"
namespace utils {
/**
* Returns the MD5 digest for the specified input.
*
* @note The returned value points to a fixed-size 16 bytes array representing
* the raw MD5 value, not a null-terminated string. Use encode_hash if
* you need the text representation instead.
*/
std::array<uint8_t, 16> md5(const std::string& input);
int get_iteration_count(const std::string& hash);
std::string get_salt(const std::string& hash);
bool is_valid_hash(const std::string& hash);
std::string encode_hash(const std::array<uint8_t, 16>& input);
std::string create_hash(const std::string& password, const std::string& salt, int iteration_count =10);
class hash_base
{
public:
virtual std::string hex_digest() const = 0;
virtual ~hash_base() {}
};
template<size_t sz>
class hash_digest : public hash_base
{
protected:
std::array<uint8_t, sz> hash;
public:
static const int DIGEST_SIZE = sz;
std::array<uint8_t, sz> raw_digest() const {return hash;}
};
class md5 : public hash_digest<16>
{
public:
static int get_iteration_count(const std::string& hash);
static std::string get_salt(const std::string& hash);
static bool is_valid_hash(const std::string& hash);
explicit md5(const std::string& input);
md5(const std::string& input, const std::string& salt, int iteration_count = 10);
virtual std::string hex_digest() const override;
};
class sha1 : public hash_digest<20>
{
public:
explicit sha1(const std::string& input);
virtual std::string hex_digest() const override;
};
} // namespace utils

View file

@ -1,393 +0,0 @@
// MD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
// Translation and modification (c) 1995 by Mordechai T. Abzug
// This translation/ modification is provided "as is," without express or
// implied warranty of any kind.
// The translator/ modifier does not claim (1) that MD5 will do what you think
// it does; (2) that this translation/ modification is accurate; or (3) that
// this software is "merchantible." (Language for this disclaimer partially
// copied from the disclaimer below).
/* based on:
MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
MDDRIVER.C - test driver for MD2, MD4 and MD5
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include "md5.hpp"
#include <cassert>
#include <iostream>
#include <cstring> // Edit: needed for strlen() (strings.h should
// include it but apparently does not for me)
// C4351 is a warning about default-initializing arrays in the initializer list.
// Since it's desired behavior, suppress the warning.
#ifdef _MSC_VER
#pragma warning(disable:4351)
#endif
// MD5 simple initialization method
MD5::MD5()
: state()
, count()
, buffer()
, digest()
, finalized(0)
{
init();
}
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block, and updating the
// context.
void MD5::update (const uint1* input, uint4 input_length) {
uint4 input_index, buffer_index;
uint4 buffer_space; // how much space is left in buffer
if (finalized){ // so we can't update!
std::cerr << "MD5::update: Can't update a finalized digest!" << std::endl;
return;
}
// Compute number of bytes mod 64
buffer_index = ((count[0] >> 3) & 0x3F);
// Update number of bits
if ( (count[0] += (input_length << 3))<(input_length << 3) )
count[1]++;
count[1] += (input_length >> 29);
buffer_space = 64 - buffer_index; // how much space is left in buffer
// Transform as many times as possible.
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
// fill the rest of the buffer and transform
memcpy (buffer + buffer_index, input, buffer_space);
transform (buffer);
// now, transform each 64-byte piece of the input, bypassing the buffer
for (input_index = buffer_space; input_index + 63 < input_length;
input_index += 64)
transform (input+input_index);
buffer_index = 0; // so we can buffer remaining
}
else
input_index=0; // so we can buffer the whole input
// and here we do the buffering:
memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
}
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
void MD5::finalize (){
uint1 bits[8];
uint4 index, padLen;
static uint1 PADDING[64]={
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (finalized){
std::cerr << "MD5::finalize: Already finalized this digest!" << std::endl;
return;
}
// Save number of bits
encode (bits, count, 8);
// Pad out to 56 mod 64.
index = (count[0] >> 3) & 0x3f;
padLen = (index < 56) ? (56 - index) : (120 - index);
update (PADDING, padLen);
// Append length (before padding)
update (bits, 8);
// Store state in digest
encode (digest, state, 16);
// Zeroize sensitive information
memset (buffer, 0, sizeof(*buffer));
finalized=1;
}
std::array<uint8_t, 16> MD5::raw_digest()
{
std::array<uint8_t, 16> s;
if (!finalized){
std::cerr << "MD5::raw_digest: Can't get digest if you haven't "<<
"finalized the digest!" <<std::endl;
throw std::logic_error("MD5::raw_digest: attempted to obtain digest before finalizing it");
}
memcpy(s.data(), digest, 16);
return s;
}
// PRIVATE METHODS:
void MD5::init(){
finalized=0; // we just started!
// Nothing counted, so count=0
count[0] = 0;
count[1] = 0;
// Load magic initialization constants.
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
// Constants for MD5Transform routine.
// Although we could use C++ style constants, defines are actually better,
// since they let us easily evade scope clashes.
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
// MD5 basic transformation. Transforms state based on block.
void MD5::transform (const uint1 block[64]){
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode (x, block, 64);
assert(!finalized); // not just a user error, since the method is private
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset ( reinterpret_cast<uint1*>(x), 0, sizeof(x));
}
// Encodes input (UINT4) into output (uint1). Assumes len is
// a multiple of 4.
void MD5::encode (uint1 *output, uint4 *input, uint4 len) {
uint4 i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = static_cast<uint1> (input[i] & 0xff);
output[j+1] = static_cast<uint1>((input[i] >> 8) & 0xff);
output[j+2] = static_cast<uint1>((input[i] >> 16) & 0xff);
output[j+3] = static_cast<uint1>((input[i] >> 24) & 0xff);
}
}
// Decodes input (uint1) into output (UINT4). Assumes len is
// a multiple of 4.
void MD5::decode (uint4 *output, const uint1 *input, uint4 len){
uint4 i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = (static_cast<uint4>(input[j]))
| ((static_cast<uint4>(input[j+1])) << 8)
| ((static_cast<uint4>(input[j+2])) << 16)
| ((static_cast<uint4>(input[j+3])) << 24);
}
// ROTATE_LEFT rotates x left n bits.
inline MD5::uint4 MD5::rotate_left (uint4 x, uint4 n){
return (x << n) | (x >> (32-n)) ;
}
// F, G, H and I are basic MD5 functions.
inline MD5::uint4 MD5::F (uint4 x, uint4 y, uint4 z){
return (x & y) | (~x & z);
}
inline MD5::uint4 MD5::G (uint4 x, uint4 y, uint4 z){
return (x & z) | (y & ~z);
}
inline MD5::uint4 MD5::H (uint4 x, uint4 y, uint4 z){
return x ^ y ^ z;
}
inline MD5::uint4 MD5::I (uint4 x, uint4 y, uint4 z){
return y ^ (x | ~z);
}
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += F(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += G(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += H(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += I(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}

View file

@ -1,95 +0,0 @@
// MD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
// Translation and modification (c) 1995 by Mordechai T. Abzug
// This translation/ modification is provided "as is," without express or
// implied warranty of any kind.
// The translator/ modifier does not claim (1) that MD5 will do what you think
// it does; (2) that this translation/ modification is accurate; or (3) that
// this software is "merchantible." (Language for this disclaimer partially
// copied from the disclaimer below).
/* based on:
MD5.H - header file for MD5C.C
MDDRIVER.C - test driver for MD2, MD4 and MD5
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#pragma once
#include <array>
#include <cstdint>
class MD5 {
public:
// methods for controlled operation:
MD5 (); // simple initializer
void update (const uint8_t* input, const uint32_t input_length);
void finalize ();
// methods to acquire finalized result
std::array<uint8_t, 16> raw_digest (); // digest as a 16-byte binary array
private:
// first, some types:
typedef uint32_t uint4;
typedef uint16_t uint2;
typedef uint8_t uint1;
// next, the private data:
uint4 state[4];
uint4 count[2]; // number of *bits*, mod 2^64
uint1 buffer[64]; // input buffer
uint1 digest[16];
uint1 finalized;
// last, the private methods, mostly static:
void init (); // called by all constructors
void transform (const uint1 buffer[64]); // does the real update work. Note
// that length is implied to be 64.
static void encode (uint1 *dest, uint4 *src, uint4 length);
static void decode (uint4 *dest, const uint1 *src, uint4 length);
static inline uint4 rotate_left (uint4 x, uint4 n);
static inline uint4 F (uint4 x, uint4 y, uint4 z);
static inline uint4 G (uint4 x, uint4 y, uint4 z);
static inline uint4 H (uint4 x, uint4 y, uint4 z);
static inline uint4 I (uint4 x, uint4 y, uint4 z);
static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
};

View file

@ -1,164 +0,0 @@
/*
Copyright (C) 2007 - 2017 by Benoit Timbert <benoit.timbert@free.fr>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/**
* @file
* Secure Hash Algorithm 1 (SHA-1).
* Used to checksum the game-config / cache.
*/
/* This is supposed to be an implementation of the
Secure Hash Algorithm 1 (SHA-1)
Check RFC 3174 for details about the algorithm.
Currently this implementation might produce different results on little-
and big-endian machines, but for our current usage, we don't care :)
*/
#include "utils/sha1.hpp"
#include <iomanip>
#include <sstream>
#define sha_rotl(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
#define sha_ch(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) )
#define sha_parity(x,y,z) ( (x) ^ (y) ^ (z) )
#define sha_maj(x,y,z) ( ((x) & (y)) | ((x) & (z)) | ((y) & (z)) )
std::string sha1_hash::display() {
std::stringstream s;
s << std::hex << std::setfill('0') << std::setw(8) << H0;
s << std::hex << std::setfill('0') << std::setw(8) << H1;
s << std::hex << std::setfill('0') << std::setw(8) << H2;
s << std::hex << std::setfill('0') << std::setw(8) << H3;
s << std::hex << std::setfill('0') << std::setw(8) << H4;
return s.str();
}
sha1_hash::sha1_hash(const std::string& str)
: H0(0x67452301), H1(0xefcdab89), H2(0x98badcfe), H3(0x10325476), H4(0xc3d2e1f0)
{
uint8_t block[64];
int bytes_left = str.size();
uint32_t ssz = bytes_left * 8; // string length in bits
std::stringstream iss (str, std::stringstream::in);
// cut our string in 64 bytes blocks then process it
while (bytes_left > 0) {
iss.read(reinterpret_cast<char*>(block), 64);
if (bytes_left <= 64) { // if it's the last block, pad it
if (bytes_left < 64) {
block[bytes_left]= 0x80; // add a 1 bit right after the end of the string
}
int i;
for (i = 63; i > bytes_left; i--) {
block[i]=0; // pad our block with zeros
}
if (bytes_left < 56) { // enough space to store the length
// put the length at the end of the block
block[60] = ssz >> 24;
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4244)
#endif
block[61] = ssz >> 16;
block[62] = ssz >> 8;
block[63] = ssz;
#ifdef _MSC_VER
#pragma warning (pop)
#endif
} else { // not enough space for the zeros => we need a new block
next(block);
// new block
for (i = 0; i < 60 ; i++) {
block[i]=0; // pad our block with zeros
}
if (bytes_left == 64) {
block[0]= 0x80; // add a 1 bit right after the end of the string = beginning of our new block
}
// put the length at the end of the block
block[60] = ssz >> 24;
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4244)
#endif
block[61] = ssz >> 16;
block[62] = ssz >> 8;
block[63] = ssz;
#ifdef _MSC_VER
#pragma warning (pop)
#endif
}
}
next(block);
bytes_left -= 64;
}
}
void sha1_hash::next(uint8_t block[64]) {
uint32_t W[80];
uint32_t A, B, C, D, E, T;
int i;
A = H0;
B = H1;
C = H2;
D = H3;
E = H4;
for (i = 0; i < 16; i++) {
W[i]= (block[4 * i] << 24) | (block[4 * i + 1] << 16) | (block[4 * i + 2] << 8) | block[4 * i + 3];
}
for (; i < 80; i++) {
W[i]=sha_rotl(1, W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]);
}
for (i = 0; i < 20; i++) {
T = sha_rotl(5,A) + sha_ch(B,C,D) + E + W[i] + 0x5a827999;
E = D;
D = C;
C = sha_rotl(30,B);
B = A;
A = T;
}
for (; i < 40; i++) {
T = sha_rotl(5,A) + sha_parity(B,C,D) + E + W[i] + 0x6ed9eba1;
E = D;
D = C;
C = sha_rotl(30,B);
B = A;
A = T;
}
for (; i < 60; i++) {
T = sha_rotl(5,A) + sha_maj(B,C,D) + E + W[i] + 0x8f1bbcdc;
E = D;
D = C;
C = sha_rotl(30,B);
B = A;
A = T;
}
for (; i < 80; i++) {
T = sha_rotl(5,A) + sha_parity(B,C,D) + E + W[i] + 0xca62c1d6;
E = D;
D = C;
C = sha_rotl(30,B);
B = A;
A = T;
}
H0 += A;
H1 += B;
H2 += C;
H3 += D;
H4 += E;
}

View file

@ -1,35 +0,0 @@
/*
Copyright (C) 2007 - 2017 by Benoit Timbert <benoit.timbert@free.fr>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include <string>
#include <cstdint>
class sha1_hash
{
public:
/** Make a hash from a string */
sha1_hash(const std::string& str);
/** Display the hash */
std::string display();
private:
/** Process the next 512 bits block */
void next(uint8_t block[64]);
uint32_t H0, H1, H2, H3, H4;
};

View file

@ -5,7 +5,7 @@ set -ev
if [[ $TRAVIS_OS_NAME == 'osx' ]]; then
brew update
brew install scons cairo pango moreutils sdl2_image sdl2_ttf sdl2_mixer
brew install scons cairo pango moreutils sdl2_image sdl2_ttf sdl2_mixer openssl
else
@ -17,7 +17,7 @@ else
sudo apt-get install -qq libboost-filesystem-dev libboost-iostreams-dev libboost-random-dev libboost-program-options-dev libboost-regex-dev libboost-system-dev libboost-test-dev libboost-locale-dev libboost-thread-dev
sudo apt-get install -qq libcairo2-dev libfribidi-dev libpango1.0-dev
sudo apt-get install -qq libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev libvorbis-dev
sudo apt-get install gdb moreutils xvfb
sudo apt-get install gdb moreutils xvfb libssl-dev
if [ "$USE_CMAKE" = true ]; then
sudo apt-get install -qq cmake;