From f7d1003bba78d8e9f8246ebf71b940da3b897913 Mon Sep 17 00:00:00 2001 From: gesior Date: Mon, 8 Mar 2021 18:54:19 +0100 Subject: [PATCH] replace OpenSSL RSA, MD5, SHA1, SHA256 and SHA512 with Crypto++ + GMP RSA and SHA1 --- Makefile.am | 2 +- config.h | 46 ++++++++++------ configmanager.cpp | 2 +- configure.ac | 12 +++-- databasemanager.cpp | 115 --------------------------------------- enums.h | 3 -- luascript.cpp | 36 ------------- luascript.h | 3 -- otserv.cpp | 56 +++---------------- protocol.cpp | 16 +++--- protocol.h | 2 + rsa.cpp | 129 ++++++++++++++++++++++++++++++++++++++++++++ rsa.h | 41 ++++++++++++++ tools.cpp | 100 +++++++++------------------------- tools.h | 3 -- 15 files changed, 253 insertions(+), 313 deletions(-) create mode 100644 rsa.cpp create mode 100644 rsa.h diff --git a/Makefile.am b/Makefile.am index e717ff4..7aa74db 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ if LOGIN_SERVER MAYBE_LOGIN = gameservers.cpp gameservers.h endif -theotxserver_SOURCES = account.h actions.cpp actions.h baseevents.cpp baseevents.h beds.cpp \ +theotxserver_SOURCES = rsa.cpp rsa.h account.h actions.cpp actions.h baseevents.cpp baseevents.h beds.cpp \ beds.h chat.cpp chat.h combat.cpp combat.h condition.cpp condition.h \ config.h configmanager.cpp configmanager.h connection.cpp connection.h \ const.h container.cpp container.h creature.cpp creature.h \ diff --git a/config.h b/config.h index 330c771..bbdb52b 100644 --- a/config.h +++ b/config.h @@ -10,6 +10,27 @@ /* Define to 1 if you have the header file. */ /* #undef HAVE_CPPCONN_CONFIG_H */ +/* Define to 1 if you have the header file. */ +#define HAVE_CRYPTOPP_ADLER32_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CRYPTOPP_BASE64_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CRYPTOPP_CRYPTLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CRYPTOPP_HEX_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CRYPTOPP_HMAC_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CRYPTOPP_MD5_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CRYPTOPP_SHA_H 1 + /* Define to 1 if you have the `floor' function. */ #define HAVE_FLOOR 1 @@ -22,6 +43,9 @@ /* Define to 1 if you have the `gethostname' function. */ #define HAVE_GETHOSTNAME 1 +/* Define to 1 if you have the header file. */ +#define HAVE_GMP_H 1 + /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 @@ -81,8 +105,11 @@ */ /* #undef HAVE_LIBBOOST_THREAD_MT */ -/* Define to 1 if you have the `crypto' library (-lcrypto). */ -#define HAVE_LIBCRYPTO 1 +/* Define to 1 if you have the `cryptopp' library (-lcryptopp). */ +#define HAVE_LIBCRYPTOPP 1 + +/* Define to 1 if you have the `gmp' library (-lgmp). */ +#define HAVE_LIBGMP 1 /* Define to 1 if you have the `lua' library (-llua). */ /* #undef HAVE_LIBLUA */ @@ -142,21 +169,6 @@ /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IN_H 1 -/* Define to 1 if you have the header file. */ -#define HAVE_OPENSSL_BN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENSSL_ERR_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENSSL_MD5_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENSSL_RSA_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_OPENSSL_SHA_H 1 - /* Define to 1 if you have the `pow' function. */ #define HAVE_POW 1 diff --git a/configmanager.cpp b/configmanager.cpp index 128baa6..09d8dc6 100644 --- a/configmanager.cpp +++ b/configmanager.cpp @@ -109,7 +109,7 @@ bool ConfigManager::load() #ifndef __LOGIN_SERVER__ m_confBool[LOGIN_ONLY_LOGINSERVER] = getGlobalBool("loginOnlyWithLoginServer", false); #endif - m_confString[ENCRYPTION_TYPE] = getGlobalString("encryptionType", "sha256"); + m_confString[ENCRYPTION_TYPE] = getGlobalString("encryptionType", "sha1"); m_confString[RSA_PRIME1] = getGlobalString("rsaPrime1", "14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); m_confString[RSA_PRIME2] = getGlobalString("rsaPrime2", "7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); m_confString[RSA_PUBLIC] = getGlobalString("rsaPublic", "65537"); diff --git a/configure.ac b/configure.ac index 5880aff..603295e 100644 --- a/configure.ac +++ b/configure.ac @@ -142,6 +142,10 @@ AC_FUNC_MEMCMP AC_FUNC_REALLOC AC_CHECK_FUNCS([ceil floor ftime gethostbyname gethostname memset pow sqrt strcasecmp strncasecmp strstr strtol]) +# check for gmp +AC_CHECK_HEADERS([gmp.h], ,[AC_MSG_ERROR("gmp header not found.")]) +AC_CHECK_LIB(gmp, __gmpz_init2, ,[AC_MSG_ERROR("Linking against gmp library failed.")]) + # check for xml2 AM_PATH_XML2(2.6.5, , AC_MSG_ERROR([You need libxml2 >= 2.6.5 to compile otxserver!])) LIBS="$LIBS $XML_LIBS" @@ -154,10 +158,6 @@ AC_CHECK_LIB(z, main, ,[AC_MSG_ERROR("Linking against zlib library failed.")]) AC_CHECK_HEADERS([pthread.h], ,[AC_MSG_ERROR("pthread header not found.")]) AC_CHECK_LIB(pthread, main, ,[AC_MSG_ERROR("Linking against pthread library failed)]) -# check for OpenSSL -AC_CHECK_HEADERS([openssl/rsa.h openssl/bn.h openssl/err.h openssl/sha.h openssl/md5.h], , [AC_MSG_ERROR("Required OpenSSL headers not found.")]) -AC_CHECK_LIB(crypto, main, , [AC_MSG_ERROR("Linking against OpenSSL library failed")]) - # check for boost AC_CHECK_LIB(boost_thread-gcc-mt, main, , [ AC_CHECK_LIB(boost_thread-mt, main, , [ @@ -202,6 +202,10 @@ AC_CHECK_LIB(boost_filesystem-gcc-mt, main, , [ # check for boost::unordered_set (should only check if gnu compiler version is below 4) # AC_CHECK_HEADERS([boost/tr1/unordered_set.hpp], , [AC_MSG_ERROR("boost::unordered_set header not found. Please update your boost to at least 1.40.")]) +# check for Crypto++ +AC_CHECK_HEADERS([cryptopp/sha.h cryptopp/md5.h cryptopp/adler32.h cryptopp/hex.h cryptopp/base64.h cryptopp/hmac.h cryptopp/cryptlib.h], , [AC_MSG_ERROR("Required Crypto++ headers not found.")]) +AC_CHECK_LIB(cryptopp, main, , [AC_MSG_ERROR("Linking against Crypto++ library failed")]) + # check for Lua if test "$luaJIT" = "yes" ; then PKG_CHECK_MODULES(LUA, luajit, , [ diff --git a/databasemanager.cpp b/databasemanager.cpp index 05664a6..115b8f7 100644 --- a/databasemanager.cpp +++ b/databasemanager.cpp @@ -357,38 +357,6 @@ void DatabaseManager::checkEncryption() { switch(newValue) { - case ENCRYPTION_MD5: - { - if((Encryption_t)value != ENCRYPTION_PLAIN) - { - std::clog << "> WARNING: You cannot change the encryption to MD5, change it back in config.lua." << std::endl; - return; - } - - Database* db = Database::getInstance(); - DBQuery query; - if(db->getDatabaseEngine() != DATABASE_ENGINE_MYSQL && db->getDatabaseEngine() != DATABASE_ENGINE_POSTGRESQL) - { - query << "SELECT `id`, `password`, `key` FROM `accounts`;"; - if(DBResult* result = db->storeQuery(query.str())) - { - do - { - query << "UPDATE `accounts` SET `password` = " << db->escapeString(transformToMD5(result->getDataString("password"), false)) << ", `key` = " << db->escapeString(transformToMD5(result->getDataString("key"), false)) << " WHERE `id` = " << result->getDataInt("id") << ";"; - db->query(query.str()); - } - while(result->next()); - result->free(); - } - } - else - db->query("UPDATE `accounts` SET `password` = MD5(`password`), `key` = MD5(`key`);"); - - registerDatabaseConfig("encryption", (int32_t)newValue); - std::clog << "> Encryption updated to MD5." << std::endl; - break; - } - case ENCRYPTION_SHA1: { if((Encryption_t)value != ENCRYPTION_PLAIN) @@ -421,62 +389,6 @@ void DatabaseManager::checkEncryption() break; } - case ENCRYPTION_SHA256: - { - if((Encryption_t)value != ENCRYPTION_PLAIN) - { - std::clog << "> WARNING: You cannot change the encryption to SHA256, change it back in config.lua." << std::endl; - return; - } - - Database* db = Database::getInstance(); - DBQuery query; - - query << "SELECT `id`, `password`, `key` FROM `accounts`;"; - if(DBResult* result = db->storeQuery(query.str())) - { - do - { - query << "UPDATE `accounts` SET `password` = " << db->escapeString(transformToSHA256(result->getDataString("password"), false)) << ", `key` = " << db->escapeString(transformToSHA256(result->getDataString("key"), false)) << " WHERE `id` = " << result->getDataInt("id") << ";"; - db->query(query.str()); - } - while(result->next()); - result->free(); - } - - registerDatabaseConfig("encryption", (int32_t)newValue); - std::clog << "> Encryption set to SHA256." << std::endl; - break; - } - - case ENCRYPTION_SHA512: - { - if((Encryption_t)value != ENCRYPTION_PLAIN) - { - std::clog << "> WARNING: You cannot change the encryption to SHA512, change it back in config.lua." << std::endl; - return; - } - - Database* db = Database::getInstance(); - DBQuery query; - - query << "SELECT `id`, `password`, `key` FROM `accounts`;"; - if(DBResult* result = db->storeQuery(query.str())) - { - do - { - query << "UPDATE `accounts` SET `password` = " << db->escapeString(transformToSHA512(result->getDataString("password"), false)) << ", `key` = " << db->escapeString(transformToSHA512(result->getDataString("key"), false)) << " WHERE `id` = " << result->getDataInt("id") << ";"; - db->query(query.str()); - } - while(result->next()); - result->free(); - } - - registerDatabaseConfig("encryption", (int32_t)newValue); - std::clog << "> Encryption set to SHA512." << std::endl; - break; - } - default: { std::clog << "> WARNING: You cannot switch from hashed passwords to plain text, change back the passwordType in config.lua to the passwordType you were previously using." << std::endl; @@ -492,15 +404,6 @@ void DatabaseManager::checkEncryption() { switch(newValue) { - case ENCRYPTION_MD5: - { - Database* db = Database::getInstance(); - DBQuery query; - query << "UPDATE `accounts` SET `password` = " << db->escapeString(transformToMD5("1", false)) << " WHERE `id` = 1 AND `password` = '1';"; - db->query(query.str()); - break; - } - case ENCRYPTION_SHA1: { Database* db = Database::getInstance(); @@ -510,24 +413,6 @@ void DatabaseManager::checkEncryption() break; } - case ENCRYPTION_SHA256: - { - Database* db = Database::getInstance(); - DBQuery query; - query << "UPDATE `accounts` SET `password` = " << db->escapeString(transformToSHA256("1", false)) << " WHERE `id` = 1 AND `password` = '1';"; - db->query(query.str()); - break; - } - - case ENCRYPTION_SHA512: - { - Database* db = Database::getInstance(); - DBQuery query; - query << "UPDATE `accounts` SET `password` = " << db->escapeString(transformToSHA512("1", false)) << " WHERE `id` = 1 AND `password` = '1';"; - db->query(query.str()); - break; - } - default: break; } diff --git a/enums.h b/enums.h index de32ed8..5b73543 100644 --- a/enums.h +++ b/enums.h @@ -84,10 +84,7 @@ enum DatabaseEngine_t enum Encryption_t { ENCRYPTION_PLAIN = 0, - ENCRYPTION_MD5, ENCRYPTION_SHA1, - ENCRYPTION_SHA256, - ENCRYPTION_SHA512 }; enum GuildLevel_t diff --git a/luascript.cpp b/luascript.cpp index 3c3b992..5057591 100644 --- a/luascript.cpp +++ b/luascript.cpp @@ -2635,10 +2635,7 @@ const luaL_Reg LuaInterface::luaStdTable[] = {"clog", LuaInterface::luaStdClog}, {"cerr", LuaInterface::luaStdCerr}, - {"md5", LuaInterface::luaStdMD5}, {"sha1", LuaInterface::luaStdSHA1}, - {"sha256", LuaInterface::luaStdSHA256}, - {"sha512", LuaInterface::luaStdSHA512}, {"checkName", LuaInterface::luaStdCheckName}, {NULL, NULL} @@ -10994,17 +10991,6 @@ EXPOSE_LOG(Cerr, std::cerr) #undef EXPOSE_LOG -int32_t LuaInterface::luaStdMD5(lua_State* L) -{ - //std.md5(string[, upperCase = false]) - bool upperCase = false; - if(lua_gettop(L) > 1) - upperCase = popBoolean(L); - - lua_pushstring(L, transformToMD5(popString(L), upperCase).c_str()); - return 1; -} - int32_t LuaInterface::luaStdSHA1(lua_State* L) { //std.sha1(string[, upperCase = false]) @@ -11016,28 +11002,6 @@ int32_t LuaInterface::luaStdSHA1(lua_State* L) return 1; } -int32_t LuaInterface::luaStdSHA256(lua_State* L) -{ - //std.sha256(string[, upperCase = false]) - bool upperCase = false; - if(lua_gettop(L) > 1) - upperCase = popBoolean(L); - - lua_pushstring(L, transformToSHA256(popString(L), upperCase).c_str()); - return 1; -} - -int32_t LuaInterface::luaStdSHA512(lua_State* L) -{ - //std.sha512(string[, upperCase = false]) - bool upperCase = false; - if(lua_gettop(L) > 1) - upperCase = popBoolean(L); - - lua_pushstring(L, transformToSHA512(popString(L), upperCase).c_str()); - return 1; -} - int32_t LuaInterface::luaStdCheckName(lua_State* L) { //std.checkName(string[, forceUppercaseOnFirstLetter = true]) diff --git a/luascript.h b/luascript.h index 6b33d56..c7f4980 100644 --- a/luascript.h +++ b/luascript.h @@ -744,10 +744,7 @@ class LuaInterface static int32_t luaStdCout(lua_State* L); static int32_t luaStdClog(lua_State* L); static int32_t luaStdCerr(lua_State* L); - static int32_t luaStdMD5(lua_State* L); static int32_t luaStdSHA1(lua_State* L); - static int32_t luaStdSHA256(lua_State* L); - static int32_t luaStdSHA512(lua_State* L); static int32_t luaStdCheckName(lua_State* L); lua_State* m_luaState; diff --git a/otserv.cpp b/otserv.cpp index 3045d7b..2dde7b2 100644 --- a/otserv.cpp +++ b/otserv.cpp @@ -41,9 +41,6 @@ #include #ifdef _MULTIPLATFORM77 -#include -#include -#include #endif #include "server.h" #ifdef __LOGIN_SERVER__ @@ -78,6 +75,7 @@ #include "exception.h" #endif #include "textlogger.h" +#include "rsa.h" #ifdef __NO_BOOST_EXCEPTIONS__ #include @@ -88,7 +86,7 @@ inline void boost::throw_exception(std::exception const & e) } #endif #ifdef _MULTIPLATFORM77 -RSA* g_RSA; +RSA g_RSA; #endif ConfigManager g_config; Game g_game; @@ -560,26 +558,11 @@ ServiceManager* services) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading Password encryption:"); #endif std::string encryptionType = asLowerCaseString(g_config.getString(ConfigManager::ENCRYPTION_TYPE)); - if(encryptionType == "md5") - { - g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_MD5); - std::clog << ">>> Using (MD5) encryption ... (done)." << std::endl; - } - else if(encryptionType == "sha1") + if(encryptionType == "sha1") { g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_SHA1); std::clog << ">>> Using (SHA1) encryption ... (done)." << std::endl; } - else if(encryptionType == "sha256") - { - g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_SHA256); - std::clog << ">>> Using (SHA256) encryption ... (done)." << std::endl; - } - else if(encryptionType == "sha512") - { - g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_SHA512); - std::clog << ">>> Using (SHA512) encryption ... (done)." << std::endl; - } else { g_config.setNumber(ConfigManager::ENCRYPTION, ENCRYPTION_PLAIN); @@ -594,35 +577,12 @@ ServiceManager* services) #if defined(WINDOWS) && !defined(_CONSOLE) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading RSA Key"); #endif - g_RSA = RSA_new(); - - BN_dec2bn(&g_RSA->p, g_config.getString(ConfigManager::RSA_PRIME1).c_str()); - BN_dec2bn(&g_RSA->q, g_config.getString(ConfigManager::RSA_PRIME2).c_str()); - BN_dec2bn(&g_RSA->d, g_config.getString(ConfigManager::RSA_PRIVATE).c_str()); - BN_dec2bn(&g_RSA->n, g_config.getString(ConfigManager::RSA_MODULUS).c_str()); - BN_dec2bn(&g_RSA->e, g_config.getString(ConfigManager::RSA_PUBLIC).c_str()); - - // This check will verify keys set in config.lua - if(RSA_check_key(g_RSA)) - { - // Ok, now we calculate a few things, dmp1, dmq1 and iqmp - BN_CTX* ctx = BN_CTX_new(); - BN_CTX_start(ctx); - - BIGNUM *r1 = BN_CTX_get(ctx), *r2 = BN_CTX_get(ctx); - BN_mod(g_RSA->dmp1, g_RSA->d, r1, ctx); - BN_mod(g_RSA->dmq1, g_RSA->d, r2, ctx); - - BN_mod_inverse(g_RSA->iqmp, g_RSA->q, g_RSA->p, ctx); - } - else - { - ERR_load_crypto_strings(); - std::stringstream s; + std::clog << ">> Loading RSA key" << std::endl; + const char* p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); + const char* q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); + const char* d("46730330223584118622160180015036832148732986808519344675210555262940258739805766860224610646919605860206328024326703361630109888417839241959507572247284807035235569619173792292786907845791904955103601652822519121908367187885509270025388641700821735345222087940578381210879116823013776808975766851829020659073"); - s << std::endl << "> OpenSSL failed - " << ERR_error_string(ERR_get_error(), NULL); - startupErrorMessage(s.str()); - } + g_RSA.initialize(p, q, d); #endif std::clog << ">> Starting SQL connection" << std::endl; diff --git a/protocol.cpp b/protocol.cpp index 651e903..7aee138 100644 --- a/protocol.cpp +++ b/protocol.cpp @@ -27,8 +27,8 @@ #include "outputmessage.h" #ifdef _MULTIPLATFORM77 -#include -extern RSA* g_RSA; +#include "rsa.h" +extern RSA g_RSA; #endif #include "definitions.h" @@ -179,6 +179,11 @@ bool Protocol::XTEA_decrypt(NetworkMessage& msg) } bool Protocol::RSA_decrypt(NetworkMessage& msg) +{ + return RSA_decrypt(&g_RSA, msg); +} + +bool Protocol::RSA_decrypt(RSA* rsa, NetworkMessage& msg) { if(msg.size() - msg.position() != 128) { @@ -191,11 +196,7 @@ bool Protocol::RSA_decrypt(NetworkMessage& msg) return false; } - uint16_t size = msg.size(); - RSA_private_decrypt(128, (uint8_t*)(msg.buffer() + msg.position()), (uint8_t*)msg.buffer(), g_RSA, RSA_NO_PADDING); - msg.setSize(size); - - msg.setPosition(0); + rsa->decrypt((char*)(msg.buffer() + msg.position())); if(!msg.get()) return true; @@ -207,6 +208,7 @@ bool Protocol::RSA_decrypt(NetworkMessage& msg) std::clog << std::endl; return false; } + #endif uint32_t Protocol::getIP() const diff --git a/protocol.h b/protocol.h index 9402c63..b3b8908 100644 --- a/protocol.h +++ b/protocol.h @@ -19,6 +19,7 @@ #define __PROTOCOL__ #include "otsystem.h" #include "connection.h" +#include "rsa.h" class OutputMessage; class Connection; @@ -70,6 +71,7 @@ class Protocol : boost::noncopyable void XTEA_encrypt(OutputMessage& msg); bool XTEA_decrypt(NetworkMessage& msg); bool RSA_decrypt(NetworkMessage& msg); + bool RSA_decrypt(RSA* rsa, NetworkMessage& msg); #endif virtual void releaseProtocol(); virtual void deleteProtocolTask(); diff --git a/rsa.cpp b/rsa.cpp new file mode 100644 index 0000000..3af9782 --- /dev/null +++ b/rsa.cpp @@ -0,0 +1,129 @@ +//////////////////////////////////////////////////////////////////////// +// OpenTibia - an opensource roleplaying game +//////////////////////////////////////////////////////////////////////// +// 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 3 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; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +//////////////////////////////////////////////////////////////////////// +#include "otpch.h" +#include "rsa.h" + +RSA::RSA() +{ + mpz_init2(m_p, 1024); + mpz_init2(m_q, 1024); + mpz_init2(m_d, 1024); + mpz_init2(m_u, 1024); + mpz_init2(m_dp, 1024); + mpz_init2(m_dq, 1024); + mpz_init2(m_mod, 1024); +} + +RSA::~RSA() +{ + mpz_clear(m_p); + mpz_clear(m_q); + mpz_clear(m_d); + mpz_clear(m_u); + mpz_clear(m_dp); + mpz_clear(m_dq); + mpz_clear(m_mod); +} + +bool RSA::initialize(const std::string& file) +{ + FILE* f = fopen(file.c_str(), "r"); + if(!f) + return false; + + char p[512], q[512], d[512]; + delete fgets(p, 512, f); + delete fgets(q, 512, f); + delete fgets(d, 512, f); + + initialize(p, q, d); + return true; +} + +void RSA::initialize(const char* p, const char* q, const char* d) +{ + boost::recursive_mutex::scoped_lock lockClass(rsaLock); + + mpz_set_str(m_p, p, 10); + mpz_set_str(m_q, q, 10); + mpz_set_str(m_d, d, 10); + + mpz_t pm1, qm1; + mpz_init2(pm1, 520); + mpz_init2(qm1, 520); + + mpz_sub_ui(pm1, m_p, 1); + mpz_sub_ui(qm1, m_q, 1); + mpz_invert(m_u, m_p, m_q); + + mpz_mod(m_dp, m_d, pm1); + mpz_mod(m_dq, m_d, qm1); + mpz_mul(m_mod, m_p, m_q); + + mpz_clear(pm1); + mpz_clear(qm1); +} + +void RSA::decrypt(char* msg) +{ + boost::recursive_mutex::scoped_lock lockClass(rsaLock); + mpz_t c, v1, v2, u2, tmp; + + mpz_init2(c, 1024); + mpz_init2(v1, 1024); + mpz_init2(v2, 1024); + mpz_init2(u2, 1024); + mpz_init2(tmp, 1024); + + mpz_import(c, 128, 1, 1, 0, 0, msg); + + mpz_mod(tmp, c, m_p); + mpz_powm(v1, tmp, m_dp, m_p); + mpz_mod(tmp, c, m_q); + mpz_powm(v2, tmp, m_dq, m_q); + + mpz_sub(u2, v2, v1); + mpz_mul(tmp, u2, m_u); + + mpz_mod(u2, tmp, m_q); + if(mpz_cmp_si(u2, 0) < 0) + { + mpz_add(tmp, u2, m_q); + mpz_set(u2, tmp); + } + + mpz_mul(tmp, u2, m_p); + mpz_set_ui(c, 0); + mpz_add(c, v1, tmp); + + size_t count = (mpz_sizeinbase(c, 2) + 7)/8; + memset(msg, 0, 128 - count); + mpz_export(&msg[128 - count], NULL, 1, 1, 0, 0, c); + + mpz_clear(c); + mpz_clear(v1); + mpz_clear(v2); + mpz_clear(u2); + mpz_clear(tmp); +} + +void RSA::getPublicKey(char* buffer) +{ + size_t count = (mpz_sizeinbase(m_mod, 2) + 7) / 8; + memset(buffer, 0, 128 - count); + mpz_export(&buffer[128 - count], NULL, 1, 1, 0, 0, m_mod); +} diff --git a/rsa.h b/rsa.h new file mode 100644 index 0000000..ed94617 --- /dev/null +++ b/rsa.h @@ -0,0 +1,41 @@ +//////////////////////////////////////////////////////////////////////// +// OpenTibia - an opensource roleplaying game +//////////////////////////////////////////////////////////////////////// +// 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 3 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; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +//////////////////////////////////////////////////////////////////////// + +#ifndef __RSA__ +#define __RSA__ + +#include "otsystem.h" +#include + +class RSA +{ + public: + RSA(); + virtual ~RSA(); + + void initialize(const char* p, const char* q, const char* d); + bool initialize(const std::string& file); + + void decrypt(char* msg); + + void getPublicKey(char* buffer); + + protected: + boost::recursive_mutex rsaLock; + mpz_t m_p, m_q, m_u, m_d, m_dp, m_dq, m_mod; +}; +#endif diff --git a/tools.cpp b/tools.cpp index a6a1cf2..53a09e0 100644 --- a/tools.cpp +++ b/tools.cpp @@ -20,106 +20,56 @@ #include #include -#include -#include +#include +#include +#include + +#include +#include +#include #include "vocation.h" #include "configmanager.h" extern ConfigManager g_config; -std::string transformToMD5(const std::string &plainText, bool upperCase) -{ - MD5_CTX c; - MD5_Init(&c); - MD5_Update(&c, plainText.c_str(), plainText.length()); - - uint8_t md[MD5_DIGEST_LENGTH]; - MD5_Final(md, &c); - - char output[(MD5_DIGEST_LENGTH << 1) + 1]; - for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) - sprintf(output + (i << 1), "%.2X", md[i]); - - if(upperCase) - return std::string(output); - - return asLowerCaseString(std::string(output)); -} - std::string transformToSHA1(const std::string &plainText, bool upperCase) { - SHA_CTX c; - SHA1_Init(&c); - SHA1_Update(&c, plainText.c_str(), plainText.length()); - - uint8_t md[SHA_DIGEST_LENGTH]; - SHA1_Final(md, &c); + // Crypto++ SHA1 object + CryptoPP::SHA1 hash; - char output[(SHA_DIGEST_LENGTH << 1) + 1]; - for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) - sprintf(output + (i << 1), "%.2X", md[i]); + // Use native byte instead of casting chars + byte digest[CryptoPP::SHA1::DIGESTSIZE]; - if(upperCase) - return std::string(output); + // Do the actual calculation, require a byte value so we need a cast + hash.CalculateDigest(digest, (const byte*)plainText.c_str(), plainText.length()); - return asLowerCaseString(std::string(output)); -} + // Crypto++ HexEncoder object + CryptoPP::HexEncoder encoder; -std::string transformToSHA256(const std::string &plainText, bool upperCase) -{ - SHA256_CTX c; - SHA256_Init(&c); - SHA256_Update(&c, plainText.c_str(), plainText.length()); + // Our output + std::string output; - uint8_t md[SHA256_DIGEST_LENGTH]; - SHA256_Final(md, &c); - - char output[(SHA256_DIGEST_LENGTH << 1) + 1]; - for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) - sprintf(output + (i << 1), "%.2X", md[i]); - - if(upperCase) - return std::string(output); - - return asLowerCaseString(std::string(output)); -} - -std::string transformToSHA512(const std::string &plainText, bool upperCase) -{ - SHA512_CTX c; - SHA512_Init(&c); - SHA512_Update(&c, plainText.c_str(), plainText.length()); - - uint8_t md[SHA512_DIGEST_LENGTH]; - SHA512_Final(md, &c); - - char output[(SHA512_DIGEST_LENGTH << 1) + 1]; - for(int32_t i = 0; i < (int32_t)sizeof(md); ++i) - sprintf(output + (i << 1), "%.2X", md[i]); + // Drop internal hex encoder and use this, returns uppercase by default + encoder.Attach(new CryptoPP::StringSink(output)); + encoder.Put(digest, sizeof(digest)); + encoder.MessageEnd(); + // Make sure we want uppercase if(upperCase) - return std::string(output); + return output; - return asLowerCaseString(std::string(output)); + // Convert to lowercase if needed + return asLowerCaseString(output); } void _encrypt(std::string& str, bool upperCase) { switch(g_config.getNumber(ConfigManager::ENCRYPTION)) { - case ENCRYPTION_MD5: - str = transformToMD5(str, upperCase); - break; case ENCRYPTION_SHA1: str = transformToSHA1(str, upperCase); break; - case ENCRYPTION_SHA256: - str = transformToSHA256(str, upperCase); - break; - case ENCRYPTION_SHA512: - str = transformToSHA512(str, upperCase); - break; default: { if(upperCase) diff --git a/tools.h b/tools.h index adf8cb2..f26035d 100644 --- a/tools.h +++ b/tools.h @@ -101,10 +101,7 @@ bool isValidAccountName(std::string text); bool isValidPassword(std::string text); bool isValidName(std::string text, bool forceUppercaseOnFirstLetter = true); -std::string transformToMD5(const std::string &plainText, bool upperCase); std::string transformToSHA1(const std::string &plainText, bool upperCase); -std::string transformToSHA256(const std::string &plainText, bool upperCase); -std::string transformToSHA512(const std::string &plainText, bool upperCase); void _encrypt(std::string& str, bool upperCase); bool encryptTest(std::string plain, std::string& hash);