diff --git a/Makefile b/Makefile index c8ba145..6166722 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -CXXFLAGS = -Icryptopp -Isrc/include +CXXFLAGS = -Isrc/include LDFLAGS = -Llib -LIBS = -lcryptopp -lpthread +LIBS = -lpthread TARGETS = bin/client bin/server bin/socket.conf @@ -9,7 +9,7 @@ TARGETS = bin/client bin/server bin/socket.conf CXX = g++ endif -bin/client: bin/client.o bin/Socket.o lib/libcryptopp.so +bin/client: bin/client.o bin/Socket.o $(CXX) -o bin/client bin/client.o bin/Socket.o $(LDFLAGS) $(LIBS) strip bin/client @@ -22,16 +22,13 @@ bin/server.o: src/server.cpp src/include/server.h bin/main_server.o: src/main_server.cpp $(CXX) -o bin/main_server.o -c src/main_server.cpp $(CXXFLAGS) -bin/server: bin/server.o bin/Socket.o bin/main_server.o lib/libcryptopp.so src/include/server.h +bin/server: bin/server.o bin/Socket.o bin/main_server.o src/include/server.h $(CXX) -o bin/server bin/server.o bin/Socket.o bin/main_server.o $(LDFLAGS) $(LIBS) strip bin/server bin/Socket.o: src/Socket.cpp src/include/Socket.h src/include/SocketException.h $(CXX) -o bin/Socket.o -c src/Socket.cpp $(CXXFLAGS) -lib/libcryptopp.so: - cd cryptopp;make clean; make dynamic; mv libcryptopp.so ../lib/libcryptopp.so - bin/socket.conf: cp socket.conf bin/socket.conf diff --git a/bin/Socket.o b/bin/Socket.o index 27e5142..e7116d3 100644 --- a/bin/Socket.o +++ b/bin/Socket.o diff --git a/bin/client b/bin/client index e6aee12..e57a49d 100755 --- a/bin/client +++ b/bin/client diff --git a/bin/client.o b/bin/client.o index 39fe7e4..fff6d3d 100644 --- a/bin/client.o +++ b/bin/client.o diff --git a/bin/main_server.o b/bin/main_server.o index 5b21948..3e405a4 100644 --- a/bin/main_server.o +++ b/bin/main_server.o diff --git a/bin/server b/bin/server index b735c78..c6119eb 100755 --- a/bin/server +++ b/bin/server diff --git a/bin/server.o b/bin/server.o index 8769073..2ea71fc 100644 --- a/bin/server.o +++ b/bin/server.o diff --git a/bin/socket.conf b/bin/socket.conf index 6037e5e..a856e8e 100644 --- a/bin/socket.conf +++ b/bin/socket.conf @@ -1,2 +1,2 @@ bind-ip = 192.168.0.10 -port = 3001 +port = 5700 diff --git a/src/Socket.cpp b/src/Socket.cpp index 763bf38..11d4342 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -6,24 +6,12 @@ * En este fichero se implementan los métodos de la clase Socket definidos en Socket.h */ #include "Socket.h" -#include "SocketException.h" -#include -#include -#include -#include using namespace std; Socket::Socket() { sock = -1; - if(RSALENGTH > 0) - { - memset( myKey, 0x00, AESLENGTH); - memset( myIV, 0x00, AES::BLOCKSIZE ); - memset( theirKey, 0x00, AESLENGTH ); - memset( theirIV, 0x00, AES::BLOCKSIZE ); - } } int Socket::getSock() @@ -39,7 +27,7 @@ void Socket::Create() throw SocketException ( "TCP: Could not create socket" ); } setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,&optval,sizeof optval); - setsockopt(sock, SOL_TCP, TCP_NODELAY, &optval, sizeof optval); + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof optval); } void Socket::Bind(string address, int port) @@ -47,7 +35,7 @@ void Socket::Bind(string address, int port) sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(port); sockAddr.sin_addr.s_addr = inet_addr(address.c_str()); - if(bind(sock, (struct sockaddr *)&sockAddr, sizeof(struct sockaddr)) != 0) + if(::bind(sock, (struct sockaddr *)&sockAddr, sizeof(struct sockaddr)) != 0) { stringstream sstream; sstream << "TCP: Could not bind to address " << address << " on port " << port; @@ -144,48 +132,32 @@ void Socket::Close() } } -void Socket::SendUnencrypted(const string& text) +const Socket& Socket::operator << ( const std::string& text) { - stringstream sstream; + stringstream sstream; int length = text.length(); if(!length) { - string s = "0"; + string s = "0"; Send(s.c_str(), 2); - return; - } - sstream << length; - string len = sstream.str(); - Send(len.c_str(), len.length()+1); - Send(text.c_str(), text.length()); -} - -const Socket& Socket::operator << ( const std::string& text) -{ - if(RSALENGTH <= 0) - { - SendUnencrypted(text); return *this; } - stringstream sstream; - string length, cipher = ""; - int size; - cipher = encryptAES(text); - size = cipher.length(); - sstream << size; - sstream >> length; - length = encryptAES(length); - Send(length.c_str(),length.length()); - Send(cipher.c_str(),size); + sstream << length; + string len = sstream.str(); + char* msg = new char[len.length() + text.length() + 1]; + strcpy(msg,len.c_str()); + strcpy(msg+len.length()+1,text.c_str()); + Send(msg, text.length() + len.length() + 1); + delete[] msg; return *this; } -void Socket::ReceiveUnencrypted(string& text) +const Socket& Socket::operator >> ( std::string& text ) { text = ""; - string len; - int length; - stringstream sstream; + string len; + int length; + stringstream sstream; char c; while(true) { @@ -201,10 +173,10 @@ void Socket::ReceiveUnencrypted(string& text) } sstream << len; sstream >> length; - if(!length) - { - return; - } + if(!length) + { + return *this; + } char *message = new char[length]; Receive(message,length); text.append(message,length); @@ -213,262 +185,5 @@ void Socket::ReceiveUnencrypted(string& text) delete[] message; message = NULL; } -} - -const Socket& Socket::operator >> ( std::string& text ) -{ - if(RSALENGTH <= 0) - { - ReceiveUnencrypted(text); - return *this; - } - int length; - stringstream sstream; - string recover = "", cipher; - char *c = new char[AES::BLOCKSIZE]; - Receive(c, AES::BLOCKSIZE); - cipher = string(c,AES::BLOCKSIZE); - recover = decryptAES(cipher); - sstream << recover; - sstream >> length; - if(c != NULL) - { - delete[] c; - c = NULL; - } - recover = ""; - c = new char[length]; - Receive(c, length); - cipher = string(c,length); - recover = decryptAES(cipher); - text = recover; - if(c != NULL) - { - delete[] c; - c = NULL; - } - return *this; -} - -void Socket::generateRSAKeys() -{ - if(RSALENGTH > 0) - { - privateKey.Initialize(rng, RSALENGTH); - RSAFunction publicKey(privateKey); - myPublicKey.Initialize(publicKey.GetModulus(),publicKey.GetPublicExponent()); - } -} - -void Socket::generateAESKeys() -{ - if(RSALENGTH > 0) - { - rng.GenerateBlock(myKey, AESLENGTH ); - rng.GenerateBlock(myIV, AES::BLOCKSIZE); - } -} - -bool Socket::sendPublicKey() -{ - if(RSALENGTH > 0) - { - stringstream sstream; - sstream << myPublicKey.GetModulus(); - sstream << " "; - sstream << myPublicKey.GetPublicExponent(); - string data = sstream.str(); - try - { - SendUnencrypted(data); - } - catch(SocketException& e) - { - return false; - } - } - return true; -} - -bool Socket::receivePublicKey() -{ - if(RSALENGTH > 0) - { - string data = ""; - struct timeval tv; - tv.tv_sec = 10; - tv.tv_usec = 0; - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); - try - { - ReceiveUnencrypted(data); - } - catch(SocketException& e) - { - return false; - } - tv.tv_sec = 0; - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval)); - stringstream sstream; - sstream.str(data); - Integer modulus,exponent; - sstream >> modulus; - sstream >> exponent; - theirPublicKey.Initialize(modulus,exponent); - if(!theirPublicKey.Validate(rng, 1)) - { - return false; - } - } - return true; -} - -void Socket::setKeys(RSAFunction *pubkey, InvertibleRSAFunction *privkey, byte *key, byte *iv) -{ - if(RSALENGTH > 0) - { - myPublicKey = *pubkey; - privateKey = *privkey; - memcpy(myIV,iv,AES::BLOCKSIZE); - memcpy(myKey,key,AESLENGTH); - } -} - -InvertibleRSAFunction* Socket::getPrivateKey() -{ - return &privateKey; -} - -RSAFunction* Socket::getPublicKey() -{ - return &myPublicKey; -} - -void Socket::sendAES() -{ - if(RSALENGTH > 0) - { - stringstream sstream; - string k((char*)myKey,AESLENGTH); - string i((char*)myIV,AES::BLOCKSIZE); - sstream << k << " " << i; - string key = sstream.str(); - string cipher = encryptRSA(key); - Send(cipher.c_str(), MAXLENGTH); - } -} - -void Socket::recvAES() -{ - if(RSALENGTH > 0) - { - stringstream sstream; - char *c = new char[MAXLENGTH]; - Receive(c, MAXLENGTH); - string key = string(c,MAXLENGTH), k, i; - key = decryptRSA(key); - k = key.substr(0,AESLENGTH); - i = key.substr(AESLENGTH+1); - memcpy(theirKey,k.c_str(),AESLENGTH); - memcpy(theirIV,i.c_str(),AES::BLOCKSIZE); - if(c != NULL) - { - delete[] c; - c = NULL; - } - } -} - -byte* Socket::getAESKey() -{ - return myKey; -} - -byte* Socket::getAESIV() -{ - return myIV; -} - -string Socket::encryptRSA(string& text) -{ - RSAES_OAEP_SHA_Encryptor e(theirPublicKey); - string cipher; - StringSource ss1(text, true, new PK_EncryptorFilter(rng, e, new StringSink(cipher))); - return cipher; -} - -string Socket::decryptRSA(string& crypt) -{ - RSAES_OAEP_SHA_Decryptor d(privateKey); - string recovered; - StringSource ss2(crypt, true,new PK_DecryptorFilter(rng, d,new StringSink(recovered))); // StringSource - return recovered; -} - -string Socket::encryptAES(const string& text) -{ - string cipher; - AES::Encryption aesEncryption(myKey, AESLENGTH); - CBC_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption, myIV ); - StreamTransformationFilter stfEncryptor(cbcEncryption, new StringSink( cipher ) ); - stfEncryptor.Put( reinterpret_cast( text.c_str() ), text.length()); - stfEncryptor.MessageEnd(); - return cipher; -} - -string Socket::decryptAES(const string& crypt) -{ - string recovered; - AES::Decryption aesDecryption(theirKey, AESLENGTH); - CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, theirIV ); - CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink( recovered ) ); - stfDecryptor.Put( reinterpret_cast( crypt.c_str() ), crypt.size() ); - stfDecryptor.MessageEnd(); - return recovered; -} - -void Socket::LoadKey(const string& filename, PublicKey *key) -{ - ByteQueue queue; - FileSource file(filename.c_str(), true); - file.TransferTo(queue); - queue.MessageEnd(); - key->Load(queue); -} - -void Socket::SaveKey(const string& filename, const PublicKey *key) -{ - ByteQueue queue; - key->Save(queue); - FileSink file(filename.c_str()); - queue.CopyTo(file); - file.MessageEnd(); -} - -void Socket::loadKeys(string pub, string priv) -{ - if(RSALENGTH > 0) - { - ifstream pubkey,privkey; - pubkey.open(pub.c_str()); - privkey.open(priv.c_str()); - if(pubkey.is_open() || privkey.is_open()) - { - pubkey.close(); - privkey.close(); - LoadKey(pub, getPublicKey()); - LoadKey(priv, getPrivateKey()); - if(getPublicKey()->Validate(rng, 1) || getPrivateKey()->Validate(rng,1)) - { - generateAESKeys(); - return; - } - } - pubkey.close(); - privkey.close(); - generateRSAKeys(); - SaveKey(priv, getPrivateKey()); - SaveKey(pub, getPublicKey()); - generateAESKeys(); - } + return *this; } diff --git a/src/client.cpp b/src/client.cpp index 945e5a5..25ecfe3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -12,12 +12,6 @@ #include #include -//! Ruta a la llave privada -/*! Ruta relativa o absoluta a la llave privada RSA, si no existe o es inválida, se creará una nueva en esa localización. */ -#define PRIVATEKEY "bin/private_client.key" -//! Ruta a la llave pública -/*! Ruta relativa o absoluta a la llave pública RSA, si no existe o es inválida, se creará una nueva en esa localización. */ -#define PUBLICKEY "bin/public_client.key" using namespace std; @@ -30,28 +24,12 @@ void exitClient(int signal/*! "; diff --git a/src/include/Socket.h b/src/include/Socket.h index a71b1dd..49f1a0d 100644 --- a/src/include/Socket.h +++ b/src/include/Socket.h @@ -9,38 +9,18 @@ #define SOCKET_H_ #include +#include +#include "SocketException.h" #include +#include #include +#include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//! Longitud de la llave RSA -/*! \brief Longitud en bits de la llava RSA usada para encriptar la llave AES. Una longitud de 0 indica que el mensaje se trasnmitirá SIN encriptar. +#include +#include -__NOTA: Si se usara una longitud menor a 728 bits habria que modificar el método que envía y recibe la llave AES, ya que la longitud máxima del -mensaje a encriptar con RSA no sería suficiente para transmitir la llave y el IV en un solo paquete. De todas formas, se recomienda NO USAR una -llave de longitud inferior a 768 bits, la llave RSA de 512 bits se puede descifrar con un Pentium 4 en unas 8 horas.__ */ -#define RSALENGTH 1024 -//! Longitud de la llave AES -/*! \brief Longitud en bytes de la llave AES usada para encriptar el mensaje. Los valores permitidos son 16, 24 y 32 */ -#define AESLENGTH 16 -//! Longitud del paquete encriptado con RSA -/*! \brief Longitud en bytes del tamaño de cada paquete encriptado con RSA, esto sólo se usaría para la transmisión de la llave AES */ -#define MAXLENGTH (RSALENGTH/8) - -using namespace CryptoPP; using namespace std; //! Clase del socket @@ -57,42 +37,6 @@ class Socket //! Estructura de dirección de socket /*! Este struct es usado por el SO para gestionar la dirección del socket abierto. */ struct sockaddr_in sockAddr; - //! Pseudo-generador de números aleatorios - /*! Esta variable se usa para generar los números aleatorios necesarios para la creación de las llaves criptográficas. */ - AutoSeededRandomPool rng; - //! Llave privada RSA - /*! Esta variable contiene la llave privada RSA generada. */ - RSA::PrivateKey privateKey; - //! Llave pública RSA própia - /*! Esta variable contiene la llave RSA pública generada por el própio socket. */ - RSA::PublicKey myPublicKey; - //! Llave pública RSA del peer - /*! Esta variable contiene la llave RSA pública recibida del peer al otro lado del socket. */ - RSA::PublicKey theirPublicKey; - //! Llave AES própia - /*! Esta variable contiene la llave AES generada por el própio socket. */ - byte myKey[AESLENGTH]; - //! IV própio - /*! Esta variable contiene el IV generado por el própio socket. */ - byte myIV[ AES::BLOCKSIZE ]; - //! Llave AES del peer - /*! Esta variable contiene la llave AES recibida del peer al otro lado del socket. */ - byte theirKey[AESLENGTH]; - //! IV del peer - /*! Esta variable contiene el IV recibido del peer al otro lado del socket. */ - byte theirIV[ AES::BLOCKSIZE ]; - //! Método de encriptación RSA - /*! Este método devuelve el mensaje que se le pasa por argumento encriptado con RSA en forma de string. */ - string encryptRSA(string& text /*!setKeys(ss.getPublicKey(), ss.getPrivateKey(), ss.getAESKey(), ss.getAESIV()); - if(!cs->sendPublicKey() || !cs->receivePublicKey()) - { - cs->Close(); - if(cs != 0) - { - delete cs; - cs = 0; - } - pthread_mutex_unlock(&m_mutex); - continue; - } - cs->sendAES(); - cs->recvAES(); thread_args *t_args = new thread_args; pthread_t *thread = new pthread_t; t_args->mutex = &m_mutex;