如何在crypto++中使用SocketSource和SocketSink

How to use SocketSource and SocketSink in crypto++

我正在尝试使用 crypto++ 的套接字工具编写网络程序。但它总是工作不正常。

问题 1:

我想写两个程序。一是服务器。另一个是客户端。服务器可以向客户端发送大量数据(多次)。

以下是我的代码。

服务器代码:

#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;
}

客户代码:

#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;
}

问题是:

当启动服务器然后启动客户端时,他们将运行正确。但是,我只能输入一次数据。然后服务器卡住了,不接受任何输入。

如何解决?谁能帮帮我?

问题 2:

我想使用 crypto++ 的套接字和其他密码算法构建一个安全通道。但是我无法在服务器和客户端之间正确发送数据。

以下是我的代码。

服务器代码:

#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;
}

客户代码:

#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;
}

问题是:

当启动服务器,然后启动客户端时,它将无法正常工作。但是当我删除服务器和客户端中的一些代码时,它会显示 "key agreement success...".

以下是从服务器中删除的代码。

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...";

以下是从客户端删除的代码。

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

与第一个问题类似。因为第二题是"two times sending and receiving"引起的。删除上述代码时,运行 正确。

SocketSink 只允许发送一次数据吗?谁能告诉我?

非常非常感谢。

我发现了类似的问题:CryptoPP: how to use SocketSource and SocketSink

正如jww所说,我们应该抛弃crypto++的网络工具。因为它很旧并且总是会引起问题。我们可以试试libevent,asio等

以下链接向您展示了一些有关 c++ 的网络库。

Best C/C++ Network Library