无法通过套接字验证消息 RSA 签名方案
Trouble Verifying Message RSA Signature Scheme Over Sockets
我正在尝试通过套接字将已签名的消息从我的服务器发送到客户端。我在验证消息时遇到问题。我已经根据 wiki 上提供的代码示例尝试了过滤和非过滤方式。我已经尝试了几乎所有我能在 Google 上找到的东西,但我被难住了。
如何通过套接字执行此签名验证方案?我把我一直在尝试的所有内容都注释掉了,只是为了展示我一直在尝试做的事情。
SERVER:
try
{
AutoSeededRandomPool rng;
stringstream ss;
string signature;
// byte* signature = new byte[tdata->signer.MaxSignatureLength()];
// if( NULL == signature )
// {
// throw Exception(Exception::OTHER_ERROR, "Invalid Signature");
// }
//
// size_t length = tdata->signer.SignMessage( rng, (const byte*) sendBuf.c_str(),
// sendBuf.length(), signature );
//string signature;
// byte* message = (byte*) sendBuf.c_str();
// SecByteBlock signature(tdata->signer.MaxSignatureLength(sendBuf.size()));
//
// size_t signatureLen = tdata->signer.SignMessageWithRecovery(rng, message,
// sendBuf.size(), NULL, 0, signature);
//
// cout << "Signature Length: " << signatureLen << endl;
// ss << signatureLen;
// string len = ss.str();
// string send;
// send = (char*)signature.data();
// send += " " + len;
StringSource(sendBuf, true,
new SignerFilter(rng, tdata->signer, new StringSink(signature),
true // putMessage
)// SignerFilter
);// StringSource
// cout << "Signature: " << std::hex << signature << endl;
// // Encode the message as an Integer
// m = Integer((const byte *) sendBuf.c_str(), sendBuf.size());
//
// //Encrypt
// c = tdata->privateKey.CalculateInverse(rng, m);
//
// //Turn the encrypted value into a string
// ss << c;
// sendBuf = ss.str();
// ss.str("");
// ss.clear();
// cout << "Cipher Sent: " << sendBuf << endl;
tdata->sockSource.Send((byte*)signature.c_str(), sizeof(signature));
这是客户
CLIENT:
string signature, recovered;
stringstream ss("");
AutoSeededRandomPool rng;
byte byteBuf[ 1000 ];
try
{
// Retrieve message from socket
cout << "Waiting for reply from server..." << endl;
sockServer.Receive(byteBuf, sizeof(byteBuf));
ss << byteBuf;
string signature = ss.str();
ss.str("");
ss.clear();
// byte sig[2048];
// bool result = verifier.VerifyMessage( (const byte*)message.c_str(),
// message.length(), sig, 2048 );
//
// if( true == result )
// {
// cout << "Message Verified" << endl;
// }
// else
// {
// cout << "Message Verification Failed" << endl;
// }
// cout << endl << std::hex << "Cipher Received: " << byteBuf << endl;
//
// SecByteBlock recovered(
// verifier.MaxRecoverableLengthFromSignatureLength(length));
//
// DecodingResult result = verifier.RecoverMessage(recovered, NULL, 0,
// byteBuf, length);
//
// if ( !result.isValidCoding )
// {
// throw Exception(Exception::OTHER_ERROR, "Invalid Signature");
// }
//
// ////////////////////////////////////////////////
// // Use recovered message
// size_t recoveredLen = result.messageLength;
//
// assert(
// 0
// == memcmp(byteBuf, (const byte* )recovered,
// std::min(sizeof(byteBuf), recoveredLen)));
// Convert message to a string
// StringSource ss1(byteBuf, sizeof(byteBuf), true,
// new StringSink(temp));
//
// ss << byteBuf;
// signature = ss.str();
// ss.str("");
// ss.clear();
//
// cout << "Signature received: " << std::hex << signature << endl;
//
StringSource(signature, true,
new SignatureVerificationFilter(verifier,
new StringSink(recovered),
SignatureVerificationFilter::THROW_EXCEPTION
| SignatureVerificationFilter::PUT_MESSAGE) // SignatureVerificationFilter
);// StringSource
cout << "Verified signature on message" << endl;
return recovered;
// return recovered;
// //Convert the string to an Integer so we can calculate the inverse
// c = Integer(recBuf.c_str());
// r = serverKey.ApplyFunction(c);
// cout << "r: " << r << endl;
//
// // Recover the original message
// size_t req = r.MinEncodedSize();
// recovered.resize(req);
// r.Encode((byte *) recovered.data(), recovered.size());
// cout << "Recovered: " << recovered << endl;
}
catch ( Exception& e )
{
cerr << "caught Exception..." << endl;
cerr << e.what() << endl;
sockServer.ShutDown(SHUT_RDWR);
return "";
}
string signature;
// ...
tdata->sockSource.Send((byte*)signature.c_str(), sizeof(signature));
一个std::string
比较小class。我的 std::string
是 32 字节长。所以,我的 sizeof(signature)
是 32.
你的sizeof(signature)
可能是一样的。而且,如您所知,sizeof
是一个编译时常量。它将是 32 或 16 或其他,无论字符串包含几个字节还是几兆字节。
您应该做的是使用 signature.size()
确定要写入的字节数。
此外,不清楚您使用的是什么套接字 API 库,但对于大多数 APIs,您不能保证成功发送请求的字节数。发送给定字节数的请求通常会 return 写入了多少字节,这可能会更少,在这种情况下您需要重试。从套接字读取也是如此。你必须事先知道你期望接收多少字节,如果你读取的字节少,你必须继续读取。
您可能必须检查 Send()
和 Receive()
中的 return 值,并采取适当的措施。
我正在尝试通过套接字将已签名的消息从我的服务器发送到客户端。我在验证消息时遇到问题。我已经根据 wiki 上提供的代码示例尝试了过滤和非过滤方式。我已经尝试了几乎所有我能在 Google 上找到的东西,但我被难住了。
如何通过套接字执行此签名验证方案?我把我一直在尝试的所有内容都注释掉了,只是为了展示我一直在尝试做的事情。
SERVER:
try
{
AutoSeededRandomPool rng;
stringstream ss;
string signature;
// byte* signature = new byte[tdata->signer.MaxSignatureLength()];
// if( NULL == signature )
// {
// throw Exception(Exception::OTHER_ERROR, "Invalid Signature");
// }
//
// size_t length = tdata->signer.SignMessage( rng, (const byte*) sendBuf.c_str(),
// sendBuf.length(), signature );
//string signature;
// byte* message = (byte*) sendBuf.c_str();
// SecByteBlock signature(tdata->signer.MaxSignatureLength(sendBuf.size()));
//
// size_t signatureLen = tdata->signer.SignMessageWithRecovery(rng, message,
// sendBuf.size(), NULL, 0, signature);
//
// cout << "Signature Length: " << signatureLen << endl;
// ss << signatureLen;
// string len = ss.str();
// string send;
// send = (char*)signature.data();
// send += " " + len;
StringSource(sendBuf, true,
new SignerFilter(rng, tdata->signer, new StringSink(signature),
true // putMessage
)// SignerFilter
);// StringSource
// cout << "Signature: " << std::hex << signature << endl;
// // Encode the message as an Integer
// m = Integer((const byte *) sendBuf.c_str(), sendBuf.size());
//
// //Encrypt
// c = tdata->privateKey.CalculateInverse(rng, m);
//
// //Turn the encrypted value into a string
// ss << c;
// sendBuf = ss.str();
// ss.str("");
// ss.clear();
// cout << "Cipher Sent: " << sendBuf << endl;
tdata->sockSource.Send((byte*)signature.c_str(), sizeof(signature));
这是客户
CLIENT:
string signature, recovered;
stringstream ss("");
AutoSeededRandomPool rng;
byte byteBuf[ 1000 ];
try
{
// Retrieve message from socket
cout << "Waiting for reply from server..." << endl;
sockServer.Receive(byteBuf, sizeof(byteBuf));
ss << byteBuf;
string signature = ss.str();
ss.str("");
ss.clear();
// byte sig[2048];
// bool result = verifier.VerifyMessage( (const byte*)message.c_str(),
// message.length(), sig, 2048 );
//
// if( true == result )
// {
// cout << "Message Verified" << endl;
// }
// else
// {
// cout << "Message Verification Failed" << endl;
// }
// cout << endl << std::hex << "Cipher Received: " << byteBuf << endl;
//
// SecByteBlock recovered(
// verifier.MaxRecoverableLengthFromSignatureLength(length));
//
// DecodingResult result = verifier.RecoverMessage(recovered, NULL, 0,
// byteBuf, length);
//
// if ( !result.isValidCoding )
// {
// throw Exception(Exception::OTHER_ERROR, "Invalid Signature");
// }
//
// ////////////////////////////////////////////////
// // Use recovered message
// size_t recoveredLen = result.messageLength;
//
// assert(
// 0
// == memcmp(byteBuf, (const byte* )recovered,
// std::min(sizeof(byteBuf), recoveredLen)));
// Convert message to a string
// StringSource ss1(byteBuf, sizeof(byteBuf), true,
// new StringSink(temp));
//
// ss << byteBuf;
// signature = ss.str();
// ss.str("");
// ss.clear();
//
// cout << "Signature received: " << std::hex << signature << endl;
//
StringSource(signature, true,
new SignatureVerificationFilter(verifier,
new StringSink(recovered),
SignatureVerificationFilter::THROW_EXCEPTION
| SignatureVerificationFilter::PUT_MESSAGE) // SignatureVerificationFilter
);// StringSource
cout << "Verified signature on message" << endl;
return recovered;
// return recovered;
// //Convert the string to an Integer so we can calculate the inverse
// c = Integer(recBuf.c_str());
// r = serverKey.ApplyFunction(c);
// cout << "r: " << r << endl;
//
// // Recover the original message
// size_t req = r.MinEncodedSize();
// recovered.resize(req);
// r.Encode((byte *) recovered.data(), recovered.size());
// cout << "Recovered: " << recovered << endl;
}
catch ( Exception& e )
{
cerr << "caught Exception..." << endl;
cerr << e.what() << endl;
sockServer.ShutDown(SHUT_RDWR);
return "";
}
string signature;
// ...
tdata->sockSource.Send((byte*)signature.c_str(), sizeof(signature));
一个std::string
比较小class。我的 std::string
是 32 字节长。所以,我的 sizeof(signature)
是 32.
你的sizeof(signature)
可能是一样的。而且,如您所知,sizeof
是一个编译时常量。它将是 32 或 16 或其他,无论字符串包含几个字节还是几兆字节。
您应该做的是使用 signature.size()
确定要写入的字节数。
此外,不清楚您使用的是什么套接字 API 库,但对于大多数 APIs,您不能保证成功发送请求的字节数。发送给定字节数的请求通常会 return 写入了多少字节,这可能会更少,在这种情况下您需要重试。从套接字读取也是如此。你必须事先知道你期望接收多少字节,如果你读取的字节少,你必须继续读取。
您可能必须检查 Send()
和 Receive()
中的 return 值,并采取适当的措施。