Ok, de mon côté, j'ai enfin réussi à déterminé d'ou venait ce crash, donc, j'ai enfin réussi à exécuté un projet utilisant SFGL, je vais donc mettre à jour tout ça sur git-hub et commencer à faire quelques tutoriels.
Mais il y a surement moyen d'encore améliorer l'installation du framework et de la rendre fonctionnelle sur d'autres plateformes, mais, comme je galère beaucoup avec CMake et que c'est mon tout premier framework je pense que je vais laisser le soin à un expert de s'en charger, de plus je n'ai pas de mac et je ne connais pas xcode.
J'ai oublié de préciser que SFGL utilise boost également donc, il faut installer boost.
Plus tard quand je mettrai le module réseau sur git-hub, il faudra aussi installer openssl que j'utilise pour le module réseau.
Un aperçu du code source pour le réseau :
Classe qui se charge d'appliquer un chiffrement RSA aux octets envoyés sur le réseau
#include "rsa.h"
#include <stdlib.h>
#include <iostream>
int Rsa::size = 0;
X509* Rsa::x = X509_new();
EVP_PKEY* Rsa::evp_pkey = EVP_PKEY_new();
BIO* Rsa::pub = BIO_new(BIO_s_mem());
size_t Rsa::pub_len = 0;
char* Rsa::pub_key = NULL;
RSA* Rsa::keypair = generateKeys(2048);
int Rsa::getCertificate (unsigned char **out) {
int len= i2d_X509(x, out);
return len;
}
void Rsa::setCertificate(const unsigned char* in, int length) {
x = d2i_X509(NULL,&in,length);
evp_pkey = X509_get_pubkey(x);
keypair = EVP_PKEY_get1_RSA(evp_pkey);
PEM_write_bio_RSAPublicKey(pub, keypair);
pub_len = BIO_pending(pub);
free(pub_key);
pub_key = (char*)malloc(pub_len + 1);
BIO_read(pub, pub_key, pub_len);
pub_key[pub_len] = '\0';
}
int Rsa::encryptWithPrKey (const char *data, size_t dataSize, char **encData) {
*encData = new char[RSA_size(keypair)];
int encDataLen = RSA_private_encrypt(dataSize, (unsigned char*) data, (unsigned char*)*encData, keypair, RSA_PKCS1_PADDING);
if (encDataLen == -1) {
char* err = (char*) malloc(130);
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
free(err);
return FAILURE;
}
return encDataLen;
}
int Rsa::decryptWithPrKey (const char *encData, size_t dataSize, char **data) {
char *msg = new char[dataSize];
int dataLen = RSA_private_decrypt(dataSize, (unsigned char*) encData, (unsigned char*)msg, keypair, RSA_PKCS1_OAEP_PADDING);
if (dataLen == -1) {
char* err = (char*) malloc(130);
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
free(err);
}
*data = new char[dataLen+1];
memcpy(*data, msg, dataLen);
(*data)[dataLen] = '\0';
delete[] msg;
return dataLen;
}
int Rsa::encryptWithPbKey (const char *data, size_t dataSize, char **encData) {
*encData = new char[RSA_size(keypair)];
int encDataLen = RSA_public_encrypt(dataSize, (unsigned char*) data, (unsigned char*) *encData, keypair, RSA_PKCS1_OAEP_PADDING);
if (encDataLen == -1) {
char* err = (char*) malloc(130);
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
free(err);
return FAILURE;
}
return encDataLen;
}
int Rsa::decryptWithPbKey (const char *encData, size_t dataSize, char **data) {
char *msg = new char[dataSize];
int dataLen = RSA_public_decrypt(dataSize, (unsigned char*) encData, (unsigned char*) msg, keypair, RSA_PKCS1_PADDING);
if (dataLen == -1) {
char* err = (char*) malloc(130);
ERR_load_crypto_strings();
ERR_error_string(ERR_get_error(), err);
fprintf(stderr, "Error encrypting message: %s\n", err);
free(err);
return FAILURE;
}
*data = new char[dataLen+1];
memcpy(*data, msg, dataLen);
(*data)[dataLen] = '\0';
delete[] msg;
return dataLen;
}
Classe qui se charge de d'appliquer un chiffrement aes aux octets envoyé sur le réseau :
#include "aes.h"
using namespace std;
#include <iostream>
int AES_ENC::size = 0;
unsigned char* AES_ENC::key = new unsigned char[32];
unsigned char* AES_ENC::iv = new unsigned char[32];
unsigned char* AES_ENC::aesSalt = new unsigned char[32];
EVP_CIPHER_CTX* AES_ENC::e_ctx = new EVP_CIPHER_CTX;
EVP_CIPHER_CTX* AES_ENC::d_ctx = new EVP_CIPHER_CTX;
unsigned char* AES_ENC::aesPass = generateKey(256);
int AES_ENC::encrypt(const char* data, size_t dataSize, char **encData) {
size_t blockLen = 0;
size_t encDataLen = 0;
*encData = new char[dataSize + AES_BLOCK_SIZE];
if (EVP_EncryptInit_ex(e_ctx, EVP_aes_256_cbc(), NULL, key, iv) == 0)
return FAILURE;
if (EVP_EncryptUpdate(e_ctx, (unsigned char*) *encData, (int*)&blockLen, (unsigned char*) data, dataSize) == 0)
return FAILURE;
encDataLen += blockLen;
if(EVP_EncryptFinal_ex(e_ctx, (unsigned char*) *encData + encDataLen, (int*)&blockLen) == 0)
return FAILURE;
EVP_CIPHER_CTX_cleanup(e_ctx);
return encDataLen + blockLen;
}
int AES_ENC::decrypt(const char* encData, size_t dataSize, char **data) {
size_t dataLen = 0;
size_t blockLen = 0;
*data = new char[dataSize];
if (EVP_DecryptInit_ex(d_ctx, EVP_aes_256_cbc(), NULL, key, iv) == 0)
return FAILURE;
if (EVP_DecryptUpdate(d_ctx, (unsigned char*) *data, (int*)&blockLen, (unsigned char*) encData, (int)dataSize) == 0)
return FAILURE;
dataLen += blockLen;
if (EVP_DecryptFinal_ex(d_ctx, (unsigned char*) *data + dataLen, (int*)&blockLen) == 0)
return FAILURE;
dataLen += blockLen;
(*data)[dataLen] = '\0';
EVP_CIPHER_CTX_cleanup(d_ctx);
return dataLen;
}
void AES_ENC::setKey(char* sKey) {
strncpy((char*) key, sKey, size / 8);
}
void AES_ENC::setIv(char* sIv) {
strncpy((char*) iv, sIv, size / 8);
}
char* AES_ENC::getKey() {
return (char*) key;
}
char* AES_ENC::getIv() {
return (char*) iv;
}
Classes qui se charge de chiffrer les octets dans des paquets SFML :
#include "encryptedPacket.h"
#include "client.h"
using namespace std;
using namespace sf;
const void* EncryptedPacket::onSend (size_t& dataSize) {
char* buffer = NULL;
dataSize = Rsa::encryptWithPbKey(static_cast<const char*> (getData()), getDataSize(), &buffer);
return &buffer[0];
}
void EncryptedPacket::onReceive (const void* data, size_t dataSize) {
char* buffer = NULL;
int newDataSize = Rsa::decryptWithPbKey(static_cast<const char*> (data), dataSize, &buffer);
append(&buffer[0], newDataSize);
}
#include "symEncPacket.h"
using namespace std;
using namespace sf;
const void* SymEncPacket::onSend (size_t& dataSize) {
char* buffer = NULL;
dataSize = AES_ENC::encrypt(static_cast<const char*> (getData()), getDataSize(), &buffer);
return &buffer[0];
}
void SymEncPacket::onReceive (const void* data, size_t dataSize) {
char* buffer = NULL;
int newDataSize = AES_ENC::decrypt(static_cast<const char*> (data), dataSize, &buffer);
append(&buffer[0], newDataSize);
}
La classe client qui se charge d'établir une connexion sécurisée entre un client et un serveur du framework et d'envoyer des message sur le réseau :
#include "client.h"
#include "network.h"
using namespace sf;
using namespace std;
SrkClient::SrkClient () {
running = false;
selectedCanal = 0;
remotePortUDP = 4568;
}
void SrkClient::setSelectedCanal (int canal) {
this->selectedCanal = canal;
}
int SrkClient::getSelectedCanal () {
return selectedCanal;
}
void SrkClient::getPublicKey () {
string message = "GetPbKeyRsa";
Network::sendTCPMessage(message);
bool done, pbKeyRsaReceived;
done = pbKeyRsaReceived = false;
Packet packet;
EncryptedPacket enc_packet;
while (!done || !pbKeyRsaReceived) {
if (!pbKeyRsaReceived) {
if (clientTCP.receive(packet) == Socket::Done) {
string message;
packet>>message;
Network::setPbKey(message);
pbKeyRsaReceived = true;
message = "GetPbKey";
Network::sendTCPMessage(message);
}
} else if (pbKeyRsaReceived && !done) {
if (clientTCP.receive(enc_packet) == Socket::Done) {
string message;
enc_packet>>message;
Network::setSymPbKey(string(message));
done = true;
}
}
}
}
bool SrkClient::startCli(int portTCP, int portUDP, IpAddress adress) {
if (!running) {
if (clientUDP.bind(portUDP) != Socket::Done) {
cout<<"Erreur : impossible d'écouter sur le port : "<<portUDP<<endl;
return false;
}
if(clientTCP.connect(adress, portTCP) != Socket::Done) {
cout<<"Erreur : impossible de se connecter au serveur!"<<endl;
return false;
} else {
cout<<"Client started!"<<endl;
m_thread = thread (&SrkClient::run, this);
return true;
}
} else {
cout<<"Client already started!"<<endl;
return false;
}
}
void SrkClient::stopCli() {
if(running) {
running = false;
m_thread.join();
} else {
cout<<"Client already stopped"<<endl;
}
}
void SrkClient::sendTCPMessage(Packet &packet) {
lock_guard<recursive_mutex> locker(rec_mutex);
if(clientTCP.send(packet) != Socket::Done)
cout<<"Erreur!"<<endl;
}
void SrkClient::sendUDPMessage(Packet &packet) {
lock_guard<recursive_mutex> locker(rec_mutex);
if(clientUDP.send(packet, Configuration::serverAddress, remotePortUDP) != Socket::Done)
cout<<"Erreur!"<<endl;
}
bool SrkClient::isRunning () {
return running;
}
void SrkClient::run() {
SymEncPacket packet;
running = true;
getPublicKey();
short unsigned int port;
IpAddress address;
selector.add(clientTCP);
selector.add(clientUDP);
while (running) {
if (selector.wait(seconds(10))) {
lock_guard<recursive_mutex> locker(rec_mutex);
if (selector.isReady(clientTCP)) {
packet.clear();
if(clientTCP.receive(packet) == Socket::Done) {
string message;
packet>>message;
Network::addResponse(message);
}
}
if (selector.isReady(clientUDP)) {
packet.clear();
if (clientUDP.receive(packet, address, port) == Socket::Done) {
if (address == Configuration::serverAddress) {
string message;
packet>>message;
Network::addResponse(message);
remotePortUDP = (remotePortUDP != port) ? port : remotePortUDP;
} else {
cout<<"This message don't provide from the server."<<endl;
}
}
}
}
}
}
Et enfin, la classe Network qui permettra de récupérer tout les messages renvoyé par le serveur, et d'envoyer des messages au serveur :
#include "network.h"
using namespace sf;
using namespace std;
SrkClient& Network::cli = Network::getCliInstance();
Clock Network::clock = Clock();
vector<string> Network::messages = vector<string>();
Time Network::timeOut = seconds(3.f);
bool Network::startCli (int portTCP, int portUDP, IpAddress address) {
return cli.startCli(portTCP, portUDP, address);
}
void Network::changeClientChannel(int channel) {
cli.setSelectedCanal(channel);
}
int Network::getClientChannel () {
return cli.getSelectedCanal();
}
void Network::stopCli () {
cli.stopCli ();
}
void Network::addResponse(string message) {
messages.push_back(message);
}
void Network::sendTCPMessage (string message) {
if (message == "GetPbKeyRsa") {
Packet packet;
packet<<message;
cli.sendTCPMessage(packet);
} else if (message == "GetPbKey") {
EncryptedPacket packet;
packet<<message;
cli.sendTCPMessage(packet);
} else {
SymEncPacket packet;
packet<<message;
cli.sendTCPMessage(packet);
}
}
void Network::sendUDPMessage(string message) {
SymEncPacket packet;
packet<<message;
cli.sendUDPMessage(packet);
}
bool Network::getResponse(string tag, string &response) {
vector<string>::iterator it;
//globalMutex->lock();
for (it = messages.begin(); it != messages.end();) {
if (it->find(tag) != string::npos) {
response = *it;
it = messages.erase(it);
return true;
} else {
it++;
}
}
// globalMutex->unlock();
return false;
}
bool Network::hasResponse() {
return messages.size() != 0;
}
string Network::getLastResponse () {
string response = "";
clock.restart();
vector<string>::iterator it;
while (response == "" && clock.getElapsedTime().asSeconds() < timeOut.asSeconds()) {
if (messages.size() > 0) {
it = messages.begin();
response = *it;
it = messages.erase(it);
}
}
return response;
}
string Network::waitForLastResponse(string tag) {
string response = "";
clock.restart();
vector<string>::iterator it;
//globalMutex->lock();
while (response == "" && clock.getElapsedTime().asSeconds() < timeOut.asSeconds()) {
if (messages.size() > 0) {
for (it = messages.begin(); it != messages.end();) {
if (it->find(tag) != string::npos) {
response = *it;
it = messages.erase(it);
return response;
} else {
it++;
}
}
}
}
//globalMutex->unlock();
return response;
}
void Network::setPbKey (string message) {
Rsa::setCertificate(reinterpret_cast<const unsigned char*>(message.c_str()), message.length());
}
void Network::setSymPbKey (string pbKey) {
vector<string> parts = split(pbKey, "-");
AES_ENC::setKey(const_cast<char*>(parts[0].c_str()));
AES_ENC::setIv(const_cast<char*>(parts[1].c_str()));
}