Search code examples
c++socketscryptographycrypto++

How to use SocketSource and SocketSink in crypto++


I am trying to write a network program using socket tools of crypto++. But it always work incorrectly.

Question 1:

I want write two programs. One is server. Another is client. Server can send a lot of datas(many times)to client.

The following is my code.

Server code:

#include<iostream>
#include<socketft.h>
#include<string>
using namespace std;
using namespace CryptoPP;

int main()
{
    try
    {
        Socket::StartSockets();//strating sockets
        Socket socServer;
        socServer.Create(SOCK_STREAM);//create a socket's object
        unsigned int iport;
        string send_str;
        cout << "input port:" ;
        cin >> iport;

        socServer.Bind(iport);//binding
        socServer.Listen();//listening
        Socket socClient;//client's socket
        socServer.Accept(socClient);//accept


        while(true)
        {
            cout << "input string:" ;
            cin >> send_str;
            //cin.clear();
            //getline(cin,send_str);
            StringSource str_send_Src1(send_str,true,new SocketSink(socClient));
        }

        /*
        cout << "input string:" ;
        cin >> send_str;
        StringSource str_send_Src1(send_str,true,new SocketSink(socClient));

        cout << "input string:" ;
        cin >> send_str;
        StringSource str_send_Src2(send_str,true,new SocketSink(socClient));
        */

        socServer.CloseSocket();
        socClient.CloseSocket();
        Socket::ShutdownSockets();
    }
    catch(const Exception& e)
    {
        cout << e.what() << endl;
    }
    return 0;
}

Client code:

#include<iostream>
#include<socketft.h>
#include<string>
using namespace std;
using namespace CryptoPP;

int main()
{
    try
    {
        Socket::StartSockets();
        Socket socClient;
        socClient.Create(SOCK_STREAM);
        string straddr;
        unsigned int iport;
        cout << "input connecting ip:" ;
        cin >> straddr;
        cout << "input connecting port:" ;
        cin >> iport;
        socClient.Connect(straddr.c_str(),iport);//connecting


        while(true)
        {
            string receive;
            SocketSource receiverSrc(socClient.GetSocket(),true,new StringSink(receive));
            cout << receive ;
        }

        socClient.CloseSocket();
        Socket::ShutdownSockets();
    }
    catch(const Exception& e)
    {
        cout << e.what() << endl;
    }
    return 0;
}

Problem is:

When starting server and then starting client, they will run correctly. Howerver, I can input data only once. Then server is stuck and don't accept any input.

How solve it ? who can help me ?

Question 2:

I want to construct a secure channel using crypto++'s socket and other cryptograpy algorithms. But i can't send data correctly between server and client.

The following is my code.

Server code:

#include<iostream> 
#include<socketft.h>
#include<files.h>
#include<osrng.h>
#include<string>
#include<tiger.h>
#include<eccrypto.h>
#include<integer.h>
#include<dh.h>
#include<hex.h>
using namespace std;
using namespace CryptoPP;

int main()
{
    try
    {
        //server
        Socket::StartSockets();
        Socket socServer;
        socServer.Create(SOCK_STREAM);
        unsigned int iport;

        string filename;
        cout << "input port:" ;
        cin >> iport;
        //iport = 5050;

        socServer.Bind(iport);
        socServer.Listen();
        Socket socClient;
        socServer.Accept(socClient);

        string testStr = "you have connected...";
        StringSource testSenSrc(testStr,true,new SocketSink(socClient.GetSocket()));
        SocketSource testRecSrc(socClient.GetSocket(),true,new StringSink(testStr));
        cout << "client'"+testStr+" have connected...";


        AutoSeededRandomPool rng;
        ECDSA<ECP,Tiger>::PrivateKey prikey_server;


       prikey_server.Load(
         FileSource("sin_prikey_server.der",true).Ref());
       ECDSA<ECP,Tiger>::PublicKey pubkey_client;
       pubkey_client.Load(
         FileSource("sin_pubkey_client.der",true).Ref());

        ECDSA<ECP,Tiger>::Signer sig_server(prikey_server);

        ECDSA<ECP,Tiger>::Verifier ver_client(pubkey_client);


        Integer p("B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
            "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
            "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
            "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
            "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
            "DF1FB2BC2E4A4371h");
        Integer g("A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
            "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213"
            "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
            "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A"
            "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
            "855E6EEB22B3B2E5h");
        Integer q("F518AA8781A8DF278ABA4E7D64B7CB9D49462353h");
        DH dh(p,q,g);

        SecByteBlock dh_prikey_server(dh.PrivateKeyLength());

        SecByteBlock dh_pubkey_server(dh.PublicKeyLength());

        dh.GenerateKeyPair(rng,dh_prikey_server,dh_pubkey_server);


        ArraySource Sig_dh_pubkey_Src(
          dh_pubkey_server,dh_pubkey_server.size(),true,
          new SignerFilter(rng,sig_server,
          new SocketSink(socClient),true));


        SecByteBlock dh_pubkey_client(dh.PublicKeyLength());

        SocketSource ArrSrc(socClient,true,
            new SignatureVerificationFilter(ver_client,
            new ArraySink(dh_pubkey_client,dh_pubkey_client.size()),
            SignatureVerificationFilter::SIGNATURE_AT_END
            |SignatureVerificationFilter:: PUT_MESSAGE));   


        SecByteBlock agreedkey(dh.AgreedValueLength());

        boolbResult=dh.Agree(
          agreedkey,dh_prikey_server,dh_pubkey_client);
        if(bResult)
            cout << "key aggrement success..." << endl;
        else
        {
            throw Exception(Exception::INVALID_ARGUMENT,
                "key aggrement failure...");
        }


        socServer.CloseSocket();
        socClient.CloseSocket();
        Socket::ShutdownSockets();
    }
    catch(const Exception& e)
    {
        cout << e.what() << endl;
    }
    return 0;
}

Client code:

#include<iostream>
#include<socketft.h>
#include<files.h>
#include<string>
#include<osrng.h>
#include<files.h>
#include<tiger.h>
#include<eccrypto.h>
#include<integer.h>
#include<dh.h>
#include<hex.h>
#include<secblock.h>
using namespace std;
using namespace CryptoPP;

int main()
{
    try
    {
        //Client
        Socket::StartSockets();
        Socket socClient;
        socClient.Create(SOCK_STREAM);
        string straddr;
        unsigned int iport;

        cout << "input ip:" ;
        cin >> straddr;
        //straddr = "127.0.0.1";
        cout << "input port:" ;
        cin >> iport;
        //iport = 5050;
        socClient.Connect(straddr.c_str(),iport);


        StringSource testSenSrc(straddr,true,
            new SocketSink(socClient));
        string testStr;
        SocketSource testRecSrc(socClient,true,
            new StringSink(testStr));
        cout << testStr << endl;


        AutoSeededRandomPool rng;
        ECDSA<ECP,Tiger>::PrivateKey prikey_client;

        prikey_client.Load(
          FileSource("sin_prikey_client.der",true).Ref());
        ECDSA<ECP,Tiger>::PublicKey pubkey_server;
        pubkey_server.Load(
          FileSource("sin_pubkey_server.der",true).Ref());


        ECDSA<ECP,Tiger>::Signer sig_client(prikey_client);

        ECDSA<ECP,Tiger>::Verifier ver_server(pubkey_server);

        Integer p("B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
            "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
            "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
            "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
            "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
            "DF1FB2BC2E4A4371h");
        Integer g("A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
            "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213"
            "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
            "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A"
            "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
            "855E6EEB22B3B2E5h");
        Integer q("F518AA8781A8DF278ABA4E7D64B7CB9D49462353h");
        DH dh(p,q,g);

        SecByteBlock dh_prikey_client(dh.PrivateKeyLength());
        SecByteBlock dh_pubkey_client(dh.PublicKeyLength());
        dh.GenerateKeyPair(rng,dh_prikey_client,dh_pubkey_client);



        ArraySource Sig_dh_pubkey_Src(
          dh_pubkey_client,dh_pubkey_client.size(),true,
        new SignerFilter(rng,sig_client,
        new SocketSink(socClient.GetSocket()),true));


        SecByteBlock dh_pubkey_server(dh.PublicKeyLength());
        SocketSource ArrSrc(socClient,true,
            new SignatureVerificationFilter(ver_server,
            new ArraySink(dh_pubkey_server,dh_pubkey_server.size()),
            SignatureVerificationFilter::SIGNATURE_AT_END 
            |SignatureVerificationFilter:: PUT_MESSAGE));   

        SecByteBlock agreedkey(dh.AgreedValueLength());

        boolbResult=dh.Agree(
          agreedkey,dh_prikey_client,dh_pubkey_server);
        if(bResult)
            cout << "key agreement success..." << endl;
        else
        {
            throw Exception(Exception::INVALID_ARGUMENT,
                "key agreement failure...");
        }


        socClient.CloseSocket();
        Socket::ShutdownSockets();
    }
    catch(const Exception& e)
    {
        cout << e.what() << endl;
    }
    return 0;
}

Problem is :

when strating server ,then starting client, it will don't work correctly. But when I remove some codes in server and client, it will show "key agreement success...".

The following is codes removed from server.

string testStr = "you have connected...";
StringSource testSenSrc(testStr,true,new 
   SocketSink(socClient.GetSocket()));
SocketSource testRecSrc(socClient.GetSocket(),true,new 
   StringSink(testStr));
cout << "client'"+testStr+" have connected...";

The following is codes removed from client.

StringSource testSenSrc(straddr,true,
            new SocketSink(socClient));
string testStr;
SocketSource testRecSrc(socClient,true,
            new StringSink(testStr));
cout << testStr << endl;

It is similar to the first question. Because the second question is caused by "two times sending and receiving". When removing above codes, it run correctly.

The SocketSink allow to send data only once ? Who can tell me ?

Thanks very very munch.

I have found similar question:CryptoPP: how to use SocketSource and SocketSink


Solution

  • As jww said, we should discard crypto++'s network tools. Because it is quite old and always cause problems. We can try libevent,asio,etc.

    The following links show you some network library about c++.

    Best C/C++ Network Library