【发布时间】:2018-11-28 03:03:27
【问题描述】:
我正在尝试使用 crypto++ 的套接字工具编写网络程序。但它总是不能正常工作。
问题一:
我想写两个程序。一是服务器。另一个是客户端。服务器可以向客户端发送大量数据(多次)。
以下是我的代码。
服务器代码:
#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;
}
问题是:
在设置服务器,然后启动客户端时,它将无法正常工作。但是当我删除服务器和客户端中的一些代码时,它会显示“密钥协议成功...”。
以下是从服务器中删除的代码。
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;
与第一个问题类似。因为第二个问题是由“两次发送和接收”引起的。去掉上面的代码,就可以正常运行了。
SocketSink 只允许发送一次数据?谁能告诉我?
非常感谢。
【问题讨论】:
-
Amazing...
SocketSource和SocketSink是 1990 年的产物,当时 Crypto++ 是 Bitvise SSH 客户端的基础。 Bitvise 停止使用它们,多年来我们找不到使用SocketSource和SocketSink的其他人。即使我从未使用过它们。它们在 Windows Phone 和 Windows 10 上造成了相当多的问题。因此我们将它们从库中删除以用于即将发布的版本...另请参阅 Crypto++ wiki 上的 ThreadLocalStorage。它讨论了删除并提供了源文件的存档。 -
回答您关于如何使用它们的问题...我建议您不要使用它们。使用 libevent 之类的东西进行异步调用和通知。如果您坚持使用它们,请查看
test,cpp。它有一些用途。 -
谢谢jww,我想我应该使用另一个库,例如libevent,asio。
标签: c++ sockets cryptography crypto++