Re: Avoiding string break...
- From: Glus Xof <gtglus gmail com>
- To: gtkmm-list gnome org
- Subject: Re: Avoiding string break...
- Date: Wed, 5 May 2010 15:22:22 +0200
Hi, again,
I post the code of a sample client & server application. Don't worry
about protocol, in a normal escenario the key will not be sent in
clear, non-encrypted manner. Just notice that, in some cases, the
message sent by the server doesn't arrive completely to the client,
which finally breaks throwing an std::bad_alloc exception instance.
Could be managed ? some help ?
Glus
-----
Compile:
$ g++ lt_client.cc rijndael.cc -o lt_client `pkg-config --cflags
--libs glibmm-2.4` `pkg-config --cflags --libs
giomm-2.4` -lssl
$ g++ lt_server.cc rijndael.cc -o lt_server `pkg-config --cflags
--libs glibmm-2.4` `pkg-config --cflags --libs giomm-2.4` -lssl
----- lt_client.cc
------------------------------------------------------------------------------
#include <glibmm.h>
#include <giomm.h>
#include <string>
#include <iostream>
#include <cstring>
#include "./rijndael.h"
const std::string Host = "localhost";
const guint16 Port = 23410;
Glib::RefPtr<Gio::Socket> socket;
Glib::RefPtr<Gio::SocketAddress> address;
Glib::RefPtr<Gio::SocketAddressEnumerator> enumerator;
Glib::RefPtr<Gio::SocketConnectable> connectable;
void connect_to_server ()
{
try
{
socket = Gio::Socket::create (
(Gio::SocketFamily)G_SOCKET_FAMILY_IPV6,
Gio::SOCKET_TYPE_STREAM,
Gio::SOCKET_PROTOCOL_DEFAULT
);
}
catch (const Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("%1", error.what())
<< std::endl;
exit (1);
}
socket->set_blocking (true);
try
{
connectable = Gio::NetworkAddress::create (Host, Port);
}
catch (Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("%1", error.what())
<< std::endl;
exit (1);
}
enumerator = connectable->enumerate();
try
{
address = enumerator->next();
if (!address)
{
std::cerr
<< "No more addresses to try"
<< std::endl;
exit (1);
}
}
catch (const Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("%1", error.what())
<< std::endl;
exit (1);
}
try
{
socket->connect (address);
}
catch (Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("Connection failed: %1"
", trying next", error.what())
<< std::endl;
exit (1);
}
}
std::string generate_key(int n_pos=32)
{
Glib::Rand rand_gen;
std::string mykey="";
for (gint an=0; an < n_pos; an++)
{
gint bn = rand_gen.get_int_range(0,9);
gchar * cn = g_strdup_printf ("%d", bn);
mykey+=cn;
}
return mykey;
}
bool send_my_message (std::string & s_mymess)
{
const gchar * s_message = g_strdup_printf("%s\0", s_mymess.data());
gssize to_send = s_mymess.size();
gssize size = 0;
while (to_send > 0)
{
try
{
size = socket->send (s_message, to_send);
}
catch (Gio::Error & error)
{
if (error.code() == Gio::Error::WOULD_BLOCK)
{
continue;
}
else
{
std::cerr
<< Glib::ustring::compose ("Error sending to socket: %1",
error.what())
<< Glib::ustring::compose ("(%1)", size)
<< std::endl;
return false;
}
}
if (size == 0)
{
std::cerr
<< "Unexpected short write"
<< std::endl;
return false;
}
to_send -= size;
}
return true;
}
std::string recv_my_message()
{
gchar * r_message = g_new0(gchar,999999);
gint messlen=0;
try
{
messlen = socket->receive (r_message, 999999);
}
catch (const Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("Error receiving from socket: %1",
error.what())
<< std::endl;
socket->close();
return "";
}
if (messlen==0)
{
socket->close();
return "";
}
else
{
r_message[messlen]='\0';
std::string r_string (r_message);
return r_string;
}
}
int main (int argc, char * argv[])
{
Glib::init();
Gio::init();
while (true)
{
connect_to_server();
std::string key = generate_key();
std::string s_message = "<_hello_:"+key;
send_my_message (s_message);
std::string r_message = recv_my_message ();
std::string message="";
if (r_message.size() > 3)
{
std::string enc_sub = r_message.substr(4);
AesDecrypt (NormKey(key, 32, ' '), enc_sub, message);
}
else
message = r_message;
std::cout
<< message
<< std::endl;
sleep (1);
}
return 0;
}
-------------------------------------------------------------------------------------------------
----- lt_server.cc
------------------------------------------------------------------------------
#include <glibmm.h>
#include <giomm.h>
#include <string>
#include <iostream>
#include <cstring>
#include "./rijndael.h"
const guint16 Port = 23410;
Glib::RefPtr<Gio::Socket> socket, client_socket;
Glib::RefPtr<Gio::SocketAddress> src_address, address;
bool service_up ()
{
try
{
socket = Gio::Socket::create (
(Gio::SocketFamily) G_SOCKET_FAMILY_IPV6,
Gio::SOCKET_TYPE_STREAM,
Gio::SOCKET_PROTOCOL_DEFAULT
);
}
catch (Gio::Error & error)
{
std::cerr
<< error.what()
<< std::endl;
return false;
}
socket->set_blocking (true);
socket->set_listen_backlog (500);
src_address = Gio::InetSocketAddress::create (
Gio::InetAddress::create_any
((Gio::SocketFamily) G_SOCKET_FAMILY_IPV6),
Port);
try
{
socket->bind (src_address, true);
}
catch (const Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("Can't bind socket: %1", error.what())
<< std::endl;
return false;
}
try
{
socket->listen();
}
catch (const Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("Can't listen on socket: %1",
error.what())
<< std::endl;
return false;
}
return true;
}
std::string recv_my_message()
{
gchar * r_message = g_new0(gchar,50);
gint messlen=0;
try
{
messlen = client_socket->receive (r_message, 50);
}
catch (const Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("Error receiving from socket: %1",
error.what())
<< std::endl;
client_socket->close();
return "";
}
if (messlen==0)
{
client_socket->close();
return "";
}
else
{
r_message[messlen]='\0';
std::string r_string (r_message);
return r_string;
}
}
std::string get_my_reply()
{
Glib::TimeVal h_time;
h_time.assign_current_time();
return h_time.as_iso8601();
}
bool send_my_message (std::string & s_mymess)
{
const gchar * s_message = g_strdup_printf("%s\0", s_mymess.data());
gssize to_send = s_mymess.size();
gssize size = 0;
while (to_send > 0)
{
try
{
size = client_socket->send (s_message, to_send);
}
catch (Gio::Error & error)
{
if (error.code() == Gio::Error::WOULD_BLOCK)
{
continue;
}
else
{
std::cerr
<< Glib::ustring::compose ("Error sending to socket: %1",
error.what())
<< Glib::ustring::compose ("(%1)", size)
<< std::endl;
return false;
}
}
if (size == 0)
{
std::cerr
<< "Unexpected short write"
<< std::endl;
return false;
}
to_send -= size;
}
return true;
}
int main (int argc, char * argv[])
{
Glib::init();
Gio::init();
service_up ();
std::cout
<< "Ready..."
<< std::endl;
while (true)
{
try
{
client_socket = socket->accept();
}
catch (const Gio::Error & error)
{
std::cerr
<< Glib::ustring::compose ("Error accepting socket: %1",
error.what())
<< std::endl;
exit(1);
}
std::string r_message = recv_my_message();
std::cout << r_message << std::endl;
std::string s_message = "";
if (r_message.size() > 9)
{
std::string reply = get_my_reply();
std::string key = r_message.substr(9);
std::string reply_e="";
AesEncrypt(NormKey(key, 32, ' '), reply, reply_e);
s_message = ">00:"+reply_e;
}
else
s_message = ">01";
send_my_message (s_message);
}
return 0;
}
-------------------------------------------------------------------------------------------------
----- rijndael.h
--------------------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <cstdio>
#include <string>
#include <cmath>
#include <cstdlib>
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
using namespace std;
int AesEncrypt(const std::string &sAesKey, const std::string
&ToEncrypt, std::string &Encrypted);
int AesDecrypt(const std::string &sAesKey, const std::string
&ToDecrypt, std::string &Decrypted);
std::string NormKey(std::string Key, const int NoBits, char FillSeq);
-------------------------------------------------------------------------------------------------
----- rijndael.cc
-------------------------------------------------------------------------------
#include "./rijndael.h"
int AesEncrypt(const std::string &sAesKey,
const std::string &ToEncrypt,
std::string &Encrypted) {
const int AesBlockSize=16;
unsigned char cInitVector[AesBlockSize];
EVP_CIPHER_CTX oEncCtx;
const EVP_CIPHER *oChiper=0;
int retval=0;
unsigned char *cOutBuffer=0;
// Set aes key:
if (sAesKey.length()==16) {
oChiper = EVP_aes_128_cbc();
} else if (sAesKey.length()==32) {
oChiper = EVP_aes_256_cbc();
} else {
return -1; // Wrong key size.
}
// Create init vector and add him infront of encrypted output data:
RAND_pseudo_bytes(cInitVector, AesBlockSize);
Encrypted.assign((char *)cInitVector, ((char *)cInitVector)+AesBlockSize);
// Create encryption context.
EVP_CIPHER_CTX_init(&oEncCtx);
EVP_EncryptInit_ex(&oEncCtx, oChiper, 0, (unsigned char
*)sAesKey.c_str(), cInitVector);
// Encrypt most of the data:
int OutBufferByteLen = ToEncrypt.length()+2*AesBlockSize;
cOutBuffer = new unsigned char[OutBufferByteLen];
retval = EVP_EncryptUpdate(
&oEncCtx,
cOutBuffer,
&OutBufferByteLen,
(unsigned char *)ToEncrypt.c_str(),
ToEncrypt.length());
// Doese encryption fail?
if (retval<0) {
delete[] cOutBuffer;
return retval; // Encryption error.
}
// Add encrypted data to output:
Encrypted.append((char *)cOutBuffer, ((char *)cOutBuffer)+OutBufferByteLen);
delete[] cOutBuffer;
//Add last block+padding:
OutBufferByteLen = 2*AesBlockSize;
cOutBuffer = new unsigned char[OutBufferByteLen]; // To be sure add two blocks.
retval = EVP_EncryptFinal_ex(
&oEncCtx,
cOutBuffer,
&OutBufferByteLen);
// Doese encryption fail?
if (retval<0) {
delete[] cOutBuffer;
return retval; // Encryption error.
}
// Add encrypted data to output:
Encrypted.append((char *)cOutBuffer, ((char *)cOutBuffer)+OutBufferByteLen);
delete[] cOutBuffer;
EVP_CIPHER_CTX_cleanup(&oEncCtx);
return 0; // Success
}
int AesDecrypt(const std::string &sAesKey,
const std::string &ToDecrypt,
std::string &Decrypted) {
const int AesBlockSize=16;
unsigned char cInitVector[AesBlockSize];
EVP_CIPHER_CTX oEncCtx;
const EVP_CIPHER *oChiper=0;
int retval=0;
unsigned char *cOutBuffer=0;
// Set aes key:
if (sAesKey.length()==16) {
oChiper = EVP_aes_128_cbc();
} else if (sAesKey.length()==32) {
oChiper = EVP_aes_256_cbc();
} else {
return -1; // Wrong key size.
}
// Get init vector:
const char *constInitVectorPtr = ToDecrypt.c_str();
for (int i=0; i<AesBlockSize; i++) {
cInitVector[i] = *constInitVectorPtr;
constInitVectorPtr++;
}
// Create decryption context.
EVP_CIPHER_CTX_init(&oEncCtx);
EVP_DecryptInit_ex(&oEncCtx, oChiper, 0, (unsigned char
*)sAesKey.c_str(), cInitVector);
// Decrypt most of the data:
int OutBufferByteLen = ToDecrypt.length() - AesBlockSize; // Subtract
the InitVec.
cOutBuffer = new unsigned char[OutBufferByteLen];
retval = EVP_DecryptUpdate(
&oEncCtx,
cOutBuffer,
&OutBufferByteLen,
((unsigned char *)ToDecrypt.c_str()) + AesBlockSize, // Remove the InitVector.
OutBufferByteLen);
// Doese encryption fail?
if (retval<0) {
delete[] cOutBuffer;
return retval; // Encryption error.
}
// Add encrypted data to output:
Decrypted.append((char *)cOutBuffer, ((char *)cOutBuffer)+OutBufferByteLen);
delete[] cOutBuffer;
//Add last block+padding:
OutBufferByteLen = 2*AesBlockSize;
cOutBuffer = new unsigned char[OutBufferByteLen]; // To be sure add two blocks.
retval = EVP_DecryptFinal_ex(
&oEncCtx,
cOutBuffer,
&OutBufferByteLen);
// Doese encryption fail?
if (retval<0) {
delete[] cOutBuffer;
return retval; // Encryption error.
}
// Add encrypted data to output:
Decrypted.append((char *)cOutBuffer, ((char *)cOutBuffer)+OutBufferByteLen);
delete[] cOutBuffer;
EVP_CIPHER_CTX_cleanup(&oEncCtx);
return 0; // Success
}
std::string NormKey(std::string Key, const int NoBits, char FillSeq)
{
Key.insert (Key.end(),NoBits,FillSeq);
return Key.substr (0,NoBits);
}
------------------------------------------------------------------------------------------------
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]