encrypt password and account number
* the encryption uses a unique machine key, this means that if anyone steals config.otml with a saved password, he will not be able to decrypt the password without the machine UUID key * the encrypt uses a simple XOR encryption method, encoded with base64 and adler32 summing
This commit is contained in:
parent
296f2a17c4
commit
e5000fa577
|
@ -40,7 +40,7 @@ local function tryLogin(charInfo, tries)
|
|||
|
||||
CharacterList.destroyLoadBox()
|
||||
|
||||
g_game.loginWorld(EnterGame.account, EnterGame.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName)
|
||||
g_game.loginWorld(G.account, G.password, charInfo.worldName, charInfo.worldHost, charInfo.worldPort, charInfo.characterName)
|
||||
|
||||
loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to game server...'))
|
||||
connect(loadBox, { onCancel = function()
|
||||
|
@ -81,6 +81,10 @@ function CharacterList.init()
|
|||
connect(g_game, { onConnectionError = onGameConnectionError })
|
||||
connect(g_game, { onGameStart = CharacterList.destroyLoadBox })
|
||||
connect(g_game, { onGameEnd = CharacterList.showAgain })
|
||||
|
||||
if G.characters then
|
||||
CharacterList.create(G.characters, G.premDays)
|
||||
end
|
||||
end
|
||||
|
||||
function CharacterList.terminate()
|
||||
|
@ -100,7 +104,9 @@ function CharacterList.terminate()
|
|||
end
|
||||
|
||||
function CharacterList.create(characters, premDays)
|
||||
CharacterList.show()
|
||||
G.characters = characters
|
||||
G.premDays = premDays
|
||||
|
||||
characterList:destroyChildren()
|
||||
local accountStatusLabel = charactersWindow:getChildById('accountStatusLabel')
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@ EnterGame = { }
|
|||
-- private variables
|
||||
local loadBox
|
||||
local enterGame
|
||||
local motdNumber
|
||||
local motdMessage
|
||||
local motdButton
|
||||
local enterGameButton
|
||||
|
||||
|
@ -29,15 +27,15 @@ local function onError(protocol, message, connectionError)
|
|||
end
|
||||
|
||||
local function onMotd(protocol, motd)
|
||||
motdNumber = tonumber(motd:sub(0, motd:find("\n")))
|
||||
motdMessage = motd:sub(motd:find("\n") + 1, #motd)
|
||||
G.motdNumber = tonumber(motd:sub(0, motd:find("\n")))
|
||||
G.motdMessage = motd:sub(motd:find("\n") + 1, #motd)
|
||||
motdButton:show()
|
||||
end
|
||||
|
||||
local function onCharacterList(protocol, characters, premDays)
|
||||
if enterGame:getChildById('rememberPasswordBox'):isChecked() then
|
||||
Settings.set('account', EnterGame.account)
|
||||
Settings.set('password', EnterGame.password)
|
||||
Settings.set('account', g_crypt.encrypt(G.account))
|
||||
Settings.set('password', g_crypt.encrypt(G.password))
|
||||
Settings.set('autologin', enterGame:getChildById('autoLoginBox'):isChecked())
|
||||
else
|
||||
clearAccountFields()
|
||||
|
@ -47,11 +45,12 @@ local function onCharacterList(protocol, characters, premDays)
|
|||
loadBox = nil
|
||||
|
||||
CharacterList.create(characters, premDays)
|
||||
CharacterList.show()
|
||||
|
||||
local lastMotdNumber = Settings.getNumber("motd")
|
||||
if motdNumber and motdNumber ~= lastMotdNumber then
|
||||
if G.motdNumber and G.motdNumber ~= lastMotdNumber then
|
||||
Settings.set("motd", motdNumber)
|
||||
local motdBox = displayInfoBox(tr('Message of the day'), motdMessage)
|
||||
local motdBox = displayInfoBox(tr('Message of the day'), G.motdMessage)
|
||||
connect(motdBox, { onOk = CharacterList.show })
|
||||
CharacterList.hide()
|
||||
end
|
||||
|
@ -65,8 +64,12 @@ function EnterGame.init()
|
|||
motdButton:hide()
|
||||
Keyboard.bindKeyDown('Ctrl+G', EnterGame.openWindow)
|
||||
|
||||
local account = Settings.get('account')
|
||||
local password = Settings.get('password')
|
||||
if G.motdNumber then
|
||||
motdButton:show()
|
||||
end
|
||||
|
||||
local account = g_crypt.decrypt(Settings.get('account'))
|
||||
local password = g_crypt.decrypt(Settings.get('password'))
|
||||
local host = Settings.get('host')
|
||||
local port = Settings.get('port')
|
||||
local autologin = Settings.getBoolean('autologin')
|
||||
|
@ -119,14 +122,14 @@ function EnterGame.openWindow()
|
|||
end
|
||||
|
||||
function EnterGame.doLogin()
|
||||
EnterGame.account = enterGame:getChildById('accountNameTextEdit'):getText()
|
||||
EnterGame.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
||||
EnterGame.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
||||
EnterGame.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
||||
G.account = enterGame:getChildById('accountNameTextEdit'):getText()
|
||||
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
||||
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
||||
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
||||
EnterGame.hide()
|
||||
|
||||
Settings.set('host', EnterGame.host)
|
||||
Settings.set('port', EnterGame.port)
|
||||
Settings.set('host', G.host)
|
||||
Settings.set('port', G.port)
|
||||
|
||||
local protocolLogin = ProtocolLogin.create()
|
||||
protocolLogin.onError = onError
|
||||
|
@ -140,9 +143,9 @@ function EnterGame.doLogin()
|
|||
EnterGame.show()
|
||||
end })
|
||||
|
||||
protocolLogin:login(EnterGame.host, EnterGame.port, EnterGame.account, EnterGame.password)
|
||||
protocolLogin:login(G.host, G.port, G.account, G.password)
|
||||
end
|
||||
|
||||
function EnterGame.displayMotd()
|
||||
displayInfoBox(tr('Message of the day'), motdMessage)
|
||||
displayInfoBox(tr('Message of the day'), G.motdMessage)
|
||||
end
|
||||
|
|
|
@ -4,6 +4,9 @@ importStyle = g_ui.importStyle
|
|||
importFont = g_fonts.importFont
|
||||
setDefaultFont = g_fonts.setDefaultFont
|
||||
|
||||
-- G is used as a global table to save variables in memory between reloads
|
||||
G = G or {}
|
||||
|
||||
function loadUI(otui, parent)
|
||||
local otuiFilePath = resolvepath(otui, 2)
|
||||
return g_ui.loadUI(otuiFilePath, parent)
|
||||
|
|
|
@ -171,6 +171,8 @@ SET(framework_SOURCES ${framework_SOURCES}
|
|||
|
||||
# framework util
|
||||
${CMAKE_CURRENT_LIST_DIR}/util/color.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/util/crypt.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/util/rsa.cpp
|
||||
|
||||
# framework core
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/adaptativeframecounter.cpp
|
||||
|
@ -189,7 +191,6 @@ SET(framework_SOURCES ${framework_SOURCES}
|
|||
${CMAKE_CURRENT_LIST_DIR}/net/inputmessage.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/net/outputmessage.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/net/protocol.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/net/rsa.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/net/server.cpp
|
||||
|
||||
# framework platform
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <framework/core/modulemanager.h>
|
||||
#include <framework/core/module.h>
|
||||
#include <framework/sound/soundmanager.h>
|
||||
#include <framework/util/crypt.h>
|
||||
|
||||
void Application::registerLuaFunctions()
|
||||
{
|
||||
|
@ -46,6 +47,10 @@ void Application::registerLuaFunctions()
|
|||
g_lua.bindGlobalFunction("colortostring", [](const Color& v) { return stdext::to_string(v); });
|
||||
g_lua.bindGlobalFunction("sizetostring", [](const Size& v) { return stdext::to_string(v); });
|
||||
|
||||
g_lua.registerStaticClass("g_crypt");
|
||||
g_lua.bindClassStaticFunction("g_crypt", "encrypt", Crypt::encrypt);
|
||||
g_lua.bindClassStaticFunction("g_crypt", "decrypt", Crypt::decrypt);
|
||||
|
||||
// Event
|
||||
g_lua.registerClass<Event>();
|
||||
g_lua.bindClassMemberFunction<Event>("cancel", &Event::cancel);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
|
||||
#include "inputmessage.h"
|
||||
#include "rsa.h"
|
||||
#include <framework/util/rsa.h>
|
||||
|
||||
InputMessage::InputMessage()
|
||||
{
|
||||
|
@ -105,7 +105,7 @@ void InputMessage::setHeaderSize(uint16 size)
|
|||
bool InputMessage::readChecksum()
|
||||
{
|
||||
uint32_t receivedCheck = getU32();
|
||||
uint32 checksum = stdext::generate_adler_checksum(m_buffer + m_readPos, getUnreadSize());
|
||||
uint32 checksum = stdext::adler32(m_buffer + m_readPos, getUnreadSize());
|
||||
return receivedCheck == checksum;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
|
||||
#include <framework/net/outputmessage.h>
|
||||
#include "rsa.h"
|
||||
#include <framework/util/rsa.h>
|
||||
|
||||
OutputMessage::OutputMessage()
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ void OutputMessage::encryptRSA(int size, const std::string& key)
|
|||
|
||||
void OutputMessage::writeChecksum()
|
||||
{
|
||||
uint32 checksum = stdext::generate_adler_checksum(m_buffer + m_headerPos, m_messageSize);
|
||||
uint32 checksum = stdext::adler32(m_buffer + m_headerPos, m_messageSize);
|
||||
assert(m_headerPos - 4 >= 0);
|
||||
m_headerPos -= 4;
|
||||
stdext::writeLE32(m_buffer + m_headerPos, checksum);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
namespace stdext {
|
||||
|
||||
inline uint32 generate_adler_checksum(uint8 *buffer, uint16 size) {
|
||||
inline uint32 adler32(const uint8 *buffer, uint16 size) {
|
||||
register uint32 a = 1, b = 0, tlen;
|
||||
while(size > 0) {
|
||||
tlen = size > 5552 ? 5552 : size;
|
||||
|
@ -57,9 +57,9 @@ inline uint32 to_power_of_two(uint32 v) {
|
|||
return r;
|
||||
}
|
||||
|
||||
inline uint16 readLE16(uchar *addr) { return (uint16)addr[1] << 8 | addr[0]; }
|
||||
inline uint32 readLE32(uchar *addr) { return (uint32)readLE16(addr + 2) << 16 | readLE16(addr); }
|
||||
inline uint64 readLE64(uchar *addr) { return (uint64)readLE32(addr + 4) << 32 | readLE32(addr); }
|
||||
inline uint16 readLE16(const uchar *addr) { return (uint16)addr[1] << 8 | addr[0]; }
|
||||
inline uint32 readLE32(const uchar *addr) { return (uint32)readLE16(addr + 2) << 16 | readLE16(addr); }
|
||||
inline uint64 readLE64(const uchar *addr) { return (uint64)readLE32(addr + 4) << 32 | readLE32(addr); }
|
||||
|
||||
inline void writeLE16(uchar *addr, uint16 value) { addr[1] = value >> 8; addr[0] = (uint8)value; }
|
||||
inline void writeLE32(uchar *addr, uint32 value) { writeLE16(addr + 2, value >> 16); writeLE16(addr, (uint16)value); }
|
||||
|
|
|
@ -161,7 +161,7 @@ inline std::string date_time_string() {
|
|||
}
|
||||
|
||||
/// Convert decimal to hexadecimal
|
||||
inline std::string dec_to_hex(unsigned int num) {
|
||||
inline std::string dec_to_hex(uint64 num) {
|
||||
std::string str;
|
||||
std::ostringstream o;
|
||||
o << std::hex << num;
|
||||
|
@ -170,8 +170,8 @@ inline std::string dec_to_hex(unsigned int num) {
|
|||
}
|
||||
|
||||
/// Convert hexadecimal to decimal
|
||||
inline unsigned int hex_to_dec(const std::string& str) {
|
||||
unsigned int num;
|
||||
inline uint64 hex_to_dec(const std::string& str) {
|
||||
uint64 num;
|
||||
std::istringstream i(str);
|
||||
i >> std::hex >> num;
|
||||
return num;
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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 "crypt.h"
|
||||
#include <framework/stdext/math.h>
|
||||
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static inline bool is_base64(unsigned char c) { return (isalnum(c) || (c == '+') || (c == '/')); }
|
||||
|
||||
std::string Crypt::base64Encode(const std::string& decoded_string)
|
||||
{
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
uint8 char_array_3[3];
|
||||
uint8 char_array_4[4];
|
||||
int pos = 0;
|
||||
int len = decoded_string.size();
|
||||
|
||||
while(len--) {
|
||||
char_array_3[i++] = decoded_string[pos++];
|
||||
if(i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
ret += base64_chars[char_array_4[i]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(i) {
|
||||
for(j = i; j < 3; j++)
|
||||
char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(j = 0; (j < i + 1); j++)
|
||||
ret += base64_chars[char_array_4[j]];
|
||||
|
||||
while((i++ < 3))
|
||||
ret += '=';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Crypt::base64Decode(const std::string& encoded_string)
|
||||
{
|
||||
int len = encoded_string.size();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
uint8 char_array_4[4], char_array_3[3];
|
||||
std::string ret;
|
||||
|
||||
while(len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
if(i ==4) {
|
||||
for(i = 0; i <4; i++)
|
||||
char_array_4[i] = base64_chars.find(char_array_4[i]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for(i = 0; (i < 3); i++)
|
||||
ret += char_array_3[i];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(i) {
|
||||
for(j = i; j <4; j++)
|
||||
char_array_4[j] = 0;
|
||||
|
||||
for(j = 0; j <4; j++)
|
||||
char_array_4[j] = base64_chars.find(char_array_4[j]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for(j = 0; (j < i - 1); j++)
|
||||
ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Crypt::xorCrypt(const std::string& buffer, const std::string& key)
|
||||
{
|
||||
std::string out;
|
||||
out.resize(buffer.size());
|
||||
register size_t i, j=0;
|
||||
for(i=0;i<buffer.size();++i) {
|
||||
out[i] = buffer[i] ^ key[j++];
|
||||
if(j >= key.size())
|
||||
j = 0;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string Crypt::genUUIDKey()
|
||||
{
|
||||
boost::hash<boost::uuids::uuid> uuid_hasher;
|
||||
std::size_t hash = uuid_hasher(boost::uuids::uuid());
|
||||
std::string key;
|
||||
key.assign((const char *)&hash, sizeof(hash));
|
||||
return key;
|
||||
}
|
||||
|
||||
std::string Crypt::encrypt(const std::string& decrypted_string)
|
||||
{
|
||||
std::string tmp = "0000" + decrypted_string;
|
||||
uint32 sum = stdext::adler32((const uint8*)decrypted_string.c_str(), decrypted_string.size());
|
||||
stdext::writeLE32((uint8*)&tmp[0], sum);
|
||||
std::string encrypted = base64Encode(xorCrypt(tmp, genUUIDKey()));
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
std::string Crypt::decrypt(const std::string& encrypted_string)
|
||||
{
|
||||
std::string decoded = base64Decode(encrypted_string);
|
||||
std::string tmp = xorCrypt(base64Decode(encrypted_string), genUUIDKey());
|
||||
if(tmp.length() >= 4) {
|
||||
uint32 readsum = stdext::readLE32((const uint8*)tmp.c_str());
|
||||
std::string decrypted_string = tmp.substr(4);
|
||||
uint32 sum = stdext::adler32((const uint8*)decrypted_string.c_str(), decrypted_string.size());
|
||||
if(readsum == sum)
|
||||
return decrypted_string;
|
||||
}
|
||||
return std::string();
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 CRYPT_H
|
||||
#define CRYPT_H
|
||||
|
||||
#include "../stdext/types.h"
|
||||
#include <string>
|
||||
|
||||
namespace Crypt {
|
||||
std::string base64Encode(const std::string& decoded_string);
|
||||
std::string base64Decode(const std::string& encoded_string);
|
||||
std::string xorCrypt(const std::string& buffer, const std::string& key);
|
||||
std::string genUUIDKey();
|
||||
std::string encrypt(const std::string& decrypted_string);
|
||||
std::string decrypt(const std::string& encrypted_string);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue