Move RSA class to Crypt

This commit is contained in:
Henrique Santiago 2012-08-04 10:54:35 -03:00
parent fa15c25951
commit fb7ab21e71
15 changed files with 120 additions and 159 deletions

View File

@ -1,4 +1,4 @@
local currentRsa = OTSERV_RSA local currentRsa
function g_game.getRsa() function g_game.getRsa()
return currentRsa return currentRsa
@ -6,14 +6,17 @@ end
function g_game.chooseRsa(host) function g_game.chooseRsa(host)
if host:match('.*\.tibia\.com') or host:match('.*\.cipsoft\.com') then if host:match('.*\.tibia\.com') or host:match('.*\.cipsoft\.com') then
currentRsa = CIPSOFT_RSA g_game.setRsa(CIPSOFT_RSA)
else else
currentRsa = OTSERV_RSA g_game.setRsa(OTSERV_RSA)
end end
end end
function g_game.setRsa(rsa) function g_game.setRsa(rsa)
currentRsa = rsa if currentRsa ~= rsa then
currentRsa = rsa
g_crypt.rsaSetPublicKey(currentRsa, '65537')
end
end end
function g_game.isOfficialTibia() function g_game.isOfficialTibia()
@ -45,3 +48,4 @@ function g_game.getSupportedProtocols()
} }
end end
g_game.setRsa(OTSERV_RSA)

View File

@ -65,7 +65,7 @@ function ProtocolLogin:sendLoginPacket()
end end
msg:addPaddingBytes(paddingBytes, 0) msg:addPaddingBytes(paddingBytes, 0)
msg:encryptRsa(128, g_game.getRsa()) msg:encryptRsa(128)
self:send(msg) self:send(msg)
self:enableXteaEncryption() self:enableXteaEncryption()

View File

@ -29,8 +29,6 @@ set(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/util/matrix.h ${CMAKE_CURRENT_LIST_DIR}/util/matrix.h
${CMAKE_CURRENT_LIST_DIR}/util/point.h ${CMAKE_CURRENT_LIST_DIR}/util/point.h
${CMAKE_CURRENT_LIST_DIR}/util/rect.h ${CMAKE_CURRENT_LIST_DIR}/util/rect.h
${CMAKE_CURRENT_LIST_DIR}/util/rsa.cpp
${CMAKE_CURRENT_LIST_DIR}/util/rsa.h
${CMAKE_CURRENT_LIST_DIR}/util/size.h ${CMAKE_CURRENT_LIST_DIR}/util/size.h
# stdext # stdext

View File

@ -83,10 +83,13 @@ void Application::registerLuaFunctions()
// Crypt // Crypt
g_lua.registerSingletonClass("g_crypt"); g_lua.registerSingletonClass("g_crypt");
g_lua.bindClassStaticFunction("g_crypt", "encrypt", Crypt::encrypt); g_lua.bindSingletonFunction("g_crypt", "encrypt", &Crypt::encrypt, &g_crypt);
g_lua.bindClassStaticFunction("g_crypt", "decrypt", Crypt::decrypt); g_lua.bindSingletonFunction("g_crypt", "decrypt", &Crypt::decrypt, &g_crypt);
g_lua.bindClassStaticFunction("g_crypt", "sha1Encode", Crypt::sha1Encode); g_lua.bindSingletonFunction("g_crypt", "sha1Encode", &Crypt::sha1Encode, &g_crypt);
g_lua.bindClassStaticFunction("g_crypt", "md5Encode", Crypt::md5Encode); g_lua.bindSingletonFunction("g_crypt", "md5Encode", &Crypt::md5Encode, &g_crypt);
g_lua.bindSingletonFunction("g_crypt", "rsaSetPublicKey", &Crypt::rsaSetPublicKey, &g_crypt);
g_lua.bindSingletonFunction("g_crypt", "rsaSetPrivateKey", &Crypt::rsaSetPrivateKey, &g_crypt);
g_lua.bindSingletonFunction("g_crypt", "rsaCheckKey", &Crypt::rsaCheckKey, &g_crypt);
// Clock // Clock
g_lua.registerSingletonClass("g_clock"); g_lua.registerSingletonClass("g_clock");
@ -635,6 +638,8 @@ void Application::registerLuaFunctions()
// Server // Server
g_lua.registerClass<Server>(); g_lua.registerClass<Server>();
g_lua.bindClassStaticFunction<Server>("create", &Server::create); g_lua.bindClassStaticFunction<Server>("create", &Server::create);
g_lua.bindClassMemberFunction<Server>("close", &Server::close);
g_lua.bindClassMemberFunction<Server>("isOpen", &Server::isOpen);
g_lua.bindClassMemberFunction<Server>("acceptNext", &Server::acceptNext); g_lua.bindClassMemberFunction<Server>("acceptNext", &Server::acceptNext);
// Connection // Connection

View File

@ -21,7 +21,7 @@
*/ */
#include "inputmessage.h" #include "inputmessage.h"
#include <framework/util/rsa.h> #include <framework/util/crypt.h>
InputMessage::InputMessage() InputMessage::InputMessage()
{ {
@ -86,13 +86,10 @@ std::string InputMessage::getString()
return std::string(v, stringLength); return std::string(v, stringLength);
} }
bool InputMessage::decryptRsa(int size, const std::string& key, const std::string& p, const std::string& q, const std::string& d) bool InputMessage::decryptRsa(int size)
{ {
checkRead(size); checkRead(size);
g_rsa.setPublic(key.c_str(), "65537"); g_crypt.rsaDecrypt((unsigned char*)m_buffer + m_readPos, size);
g_rsa.setPrivate(p.c_str(), q.c_str(), d.c_str());
g_rsa.check();
g_rsa.decrypt((unsigned char*)m_buffer + m_readPos, size);
return (getU8() == 0x00); return (getU8() == 0x00);
} }

View File

@ -52,7 +52,7 @@ public:
uint32 peekU32() { uint32 v = getU32(); m_readPos-=4; return v; } uint32 peekU32() { uint32 v = getU32(); m_readPos-=4; return v; }
uint64 peekU64() { uint64 v = getU64(); m_readPos-=8; return v; } uint64 peekU64() { uint64 v = getU64(); m_readPos-=8; return v; }
bool decryptRsa(int size, const std::string& key, const std::string& p, const std::string& q, const std::string& d); bool decryptRsa(int size);
int getReadSize() { return m_readPos - m_headerPos; } int getReadSize() { return m_readPos - m_headerPos; }
int getReadPos() { return m_readPos; } int getReadPos() { return m_readPos; }

View File

@ -21,7 +21,7 @@
*/ */
#include <framework/net/outputmessage.h> #include <framework/net/outputmessage.h>
#include <framework/util/rsa.h> #include <framework/util/crypt.h>
OutputMessage::OutputMessage() OutputMessage::OutputMessage()
{ {
@ -89,13 +89,12 @@ void OutputMessage::addPaddingBytes(int bytes, uint8 byte)
m_messageSize += bytes; m_messageSize += bytes;
} }
void OutputMessage::encryptRsa(int size, const std::string& key) void OutputMessage::encryptRsa(int size)
{ {
if(m_messageSize < size) if(m_messageSize < size)
throw stdext::exception("insufficient bytes in buffer to encrypt"); throw stdext::exception("insufficient bytes in buffer to encrypt");
g_rsa.setPublic(key.c_str(), "65537"); g_crypt.rsaEncrypt((unsigned char*)m_buffer + m_writePos - size, size);
g_rsa.encrypt((unsigned char*)m_buffer + m_writePos - size, size);
} }
void OutputMessage::writeChecksum() void OutputMessage::writeChecksum()

View File

@ -49,7 +49,7 @@ public:
void addString(const std::string& buffer); void addString(const std::string& buffer);
void addPaddingBytes(int bytes, uint8 byte = 0); void addPaddingBytes(int bytes, uint8 byte = 0);
void encryptRsa(int size, const std::string& key); void encryptRsa(int size);
uint16 getMessageSize() { return m_messageSize; } uint16 getMessageSize() { return m_messageSize; }

View File

@ -35,15 +35,23 @@ ServerPtr Server::create(int port)
return ServerPtr(new Server(port)); return ServerPtr(new Server(port));
} }
void Server::close()
{
m_isOpen = false;
m_acceptor.cancel();
m_acceptor.close();
}
void Server::acceptNext() void Server::acceptNext()
{ {
ConnectionPtr connection = ConnectionPtr(new Connection); ConnectionPtr connection = ConnectionPtr(new Connection);
connection->m_connecting = true; connection->m_connecting = true;
auto self = static_self_cast<Server>();
m_acceptor.async_accept(connection->m_socket, [=](const boost::system::error_code& error) { m_acceptor.async_accept(connection->m_socket, [=](const boost::system::error_code& error) {
if(!error) { if(!error) {
connection->m_connected = true; connection->m_connected = true;
connection->m_connecting = false; connection->m_connecting = false;
} }
callLuaField("onAccept", connection, error.message(), error.value()); self->callLuaField("onAccept", connection, error.message(), error.value());
}); });
} }

View File

@ -28,15 +28,16 @@
class Server : public LuaObject class Server : public LuaObject
{ {
typedef std::function<void(ConnectionPtr, const boost::system::error_code&)> AcceptCallback;
public: public:
Server(int port); Server(int port);
static ServerPtr create(int port); static ServerPtr create(int port);
bool isOpen() { return m_isOpen; }
void close();
void acceptNext(); void acceptNext();
private: private:
stdext::boolean<true> m_isOpen;
asio::ip::tcp::acceptor m_acceptor; asio::ip::tcp::acceptor m_acceptor;
}; };

View File

@ -22,16 +22,31 @@
#include "crypt.h" #include "crypt.h"
#include <framework/stdext/math.h> #include <framework/stdext/math.h>
#include <framework/core/logger.h>
#include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid.hpp>
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <openssl/md5.h> #include <openssl/md5.h>
#include <openssl/bn.h>
#include <openssl/err.h>
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); } static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); }
Crypt g_crypt;
Crypt::Crypt()
{
m_rsa = RSA_new();
}
Crypt::~Crypt()
{
RSA_free(m_rsa);
}
std::string Crypt::base64Encode(const std::string& decoded_string) std::string Crypt::base64Encode(const std::string& decoded_string)
{ {
std::string ret; std::string ret;
@ -204,3 +219,49 @@ std::string Crypt::sha1Encode(std::string decoded_string, bool upperCase)
std::transform(result.begin(), result.end(), result.begin(), tolower); std::transform(result.begin(), result.end(), result.begin(), tolower);
return result; return result;
} }
void Crypt::rsaSetPublicKey(const std::string& n, const std::string& e)
{
BN_dec2bn(&m_rsa->n, n.c_str());
BN_dec2bn(&m_rsa->e, e.c_str());
}
void Crypt::rsaSetPrivateKey(const std::string& p, const std::string& q, const std::string& d)
{
BN_dec2bn(&m_rsa->p, p.c_str());
BN_dec2bn(&m_rsa->q, q.c_str());
BN_dec2bn(&m_rsa->d, d.c_str());
}
bool Crypt::rsaCheckKey()
{
// only used by server, that sets both public and private
if(RSA_check_key(m_rsa)) {
BN_CTX *ctx = BN_CTX_new();
BN_CTX_start(ctx);
BIGNUM *r1 = BN_CTX_get(ctx), *r2 = BN_CTX_get(ctx);
BN_mod(m_rsa->dmp1, m_rsa->d, r1, ctx);
BN_mod(m_rsa->dmq1, m_rsa->d, r2, ctx);
BN_mod_inverse(m_rsa->iqmp, m_rsa->q, m_rsa->p, ctx);
return true;
}
else {
ERR_load_crypto_strings();
g_logger.error(stdext::format("RSA check failed - %s", ERR_error_string(ERR_get_error(), NULL)));
return false;
}
}
bool Crypt::rsaEncrypt(unsigned char *msg, int size)
{
assert(size <= 128);
return RSA_public_encrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
}
bool Crypt::rsaDecrypt(unsigned char *msg, int size)
{
assert(size <= 128);
return RSA_private_decrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
}

View File

@ -26,7 +26,14 @@
#include "../stdext/types.h" #include "../stdext/types.h"
#include <string> #include <string>
namespace Crypt { #include <openssl/rsa.h>
class Crypt
{
public:
Crypt();
~Crypt();
std::string base64Encode(const std::string& decoded_string); std::string base64Encode(const std::string& decoded_string);
std::string base64Decode(const std::string& encoded_string); std::string base64Decode(const std::string& encoded_string);
std::string xorCrypt(const std::string& buffer, const std::string& key); std::string xorCrypt(const std::string& buffer, const std::string& key);
@ -35,6 +42,17 @@ namespace Crypt {
std::string decrypt(const std::string& encrypted_string); std::string decrypt(const std::string& encrypted_string);
std::string md5Encode(std::string decoded_string, bool upperCase); std::string md5Encode(std::string decoded_string, bool upperCase);
std::string sha1Encode(std::string decoded_string, bool upperCase); std::string sha1Encode(std::string decoded_string, bool upperCase);
}
void rsaSetPublicKey(const std::string& n, const std::string& e);
void rsaSetPrivateKey(const std::string &p, const std::string &q, const std::string &d);
bool rsaCheckKey();
bool rsaEncrypt(unsigned char *msg, int size);
bool rsaDecrypt(unsigned char *msg, int size);
private:
RSA *m_rsa;
};
extern Crypt g_crypt;
#endif #endif

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "rsa.h"
#include <openssl/bn.h>
#include <openssl/err.h>
Rsa g_rsa;
Rsa::Rsa()
{
m_rsa = RSA_new();
}
Rsa::~Rsa()
{
RSA_free(m_rsa);
}
void Rsa::setPublic(const char *n, const char *e)
{
BN_dec2bn(&m_rsa->n, n);
BN_dec2bn(&m_rsa->e, e);
}
void Rsa::setPrivate(const char *p, const char *q, const char *d)
{
BN_dec2bn(&m_rsa->p, p);
BN_dec2bn(&m_rsa->q, q);
BN_dec2bn(&m_rsa->d, d);
}
bool Rsa::check() // only used by server, that sets both public and private
{
if(RSA_check_key(m_rsa)) {
BN_CTX *ctx = BN_CTX_new();
BN_CTX_start(ctx);
BIGNUM *r1 = BN_CTX_get(ctx), *r2 = BN_CTX_get(ctx);
BN_mod(m_rsa->dmp1, m_rsa->d, r1, ctx);
BN_mod(m_rsa->dmq1, m_rsa->d, r2, ctx);
BN_mod_inverse(m_rsa->iqmp, m_rsa->q, m_rsa->p, ctx);
return true;
}
else {
ERR_load_crypto_strings();
g_logger.error(stdext::format("RSA check failed - %s", ERR_error_string(ERR_get_error(), NULL)));
return false;
}
}
bool Rsa::encrypt(unsigned char *msg, int size)
{
assert(size <= 128);
return RSA_public_encrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
}
bool Rsa::decrypt(unsigned char *msg, int size)
{
assert(size <= 128);
return RSA_private_decrypt(size, msg, msg, m_rsa, RSA_NO_PADDING) != -1;
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef RSA_H
#define RSA_H
#include <framework/global.h>
#include <openssl/rsa.h>
class Rsa
{
public:
Rsa();
~Rsa();
void setPublic(const char *n, const char *e);
void setPrivate(const char *p, const char *q, const char *d);
bool check();
bool encrypt(unsigned char *msg, int size);
bool decrypt(unsigned char *msg, int size);
private:
RSA *m_rsa;
};
extern Rsa g_rsa;
#endif

View File

@ -91,7 +91,7 @@ void ProtocolGame::sendLoginPacket(uint challangeTimestamp, uint8 challangeRando
msg->addPaddingBytes(paddingBytes); msg->addPaddingBytes(paddingBytes);
// encrypt with RSA // encrypt with RSA
msg->encryptRsa(128, g_lua.callGlobalField<std::string>("g_game", "getRsa")); msg->encryptRsa(128);
send(msg); send(msg);