2016-12-04 37 views
0

我试图通过套接字将签名消息从套接字发送到客户端。我在验证邮件时遇到问题。我尝试了基于wiki上提供的代码示例的过滤和非过滤方式。我尝试了几乎所有可以在谷歌上找到的东西,但我却遭受了沉重的打击。无法验证消息RSA签名套接字方案

如何在套接字上执行此签名验证方案?为了展示我一直在尝试做的事情,我留下了所有我一直想要评论的内容。

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 ""; 
    } 
+0

在移动到套接字之前,您应该先练习本地文件。也许谷歌[Protocol Buffers](http://developers.google.com/protocol-buffers/)将有助于抽象出套接字细节。他们也可以工作,所以您不必担心清除代码中的低级错误。 – jww

回答

1
string signature; 

// ... 

tdata->sockSource.Send((byte*)signature.c_str(), sizeof(signature)); 

一个std::string是一个相对较小的类。我的std::string s长度为32个字节。所以,我的sizeof(signature)是32.

您的sizeof(signature)可能是相同的。而且,如你所知sizeof是一个编译时常量。无论该字符串是否包含几个字节或几MB,它将会是32或16或其他。

你应该做的是使用signature.size()来确定要写入的字节数。

此外,你不清楚你正在使用什么套接字API库,但是对于大多数API,你不能保证成功发送请求的字节数。发送给定字节数的请求通常会返回写入的字节数,可能会少一些,在这种情况下,您需要再次尝试。从套接字读取也是如此。您必须事先知道您期望接收多少字节,如果您读取的字节较少,则必须继续阅读。

您很可能必须检查Send()Receive()的返回值,并采取适当的措施。

+0

感谢您注意我的字符串大小问题。我一直在努力改变周围事物,所以我错过了沿途的某个细节。我正在使用Crypto ++ Socket API。除了签名验证之外,我还没有遇到任何问题。我也在做RSA加密和解密,并且工作正常。我为发送方签名的原因是因为我试图阻止MITM Diffie-Hellman攻击,但我只有一对公钥/私钥对。我只能切断攻击的一方,但那很好。 –

+0

我也修复了尺寸问题。仍然没有使用流水线过滤方法进行验证。不应该那样工作? –

+0

看起来你并没有清除'byteBuf'缓冲区。它可能包含随机垃圾。 'Receive()'将字节转储到它中,并且不会显式终止''\ 0'。请注意,'std :: string's可以包含空字节,并且从普通缓冲区初始化一个字符串或一个字符串流将收集所有内容,直到第一个“\ 0”。实际上,整个串流不会有任何用处。你需要确切知道你接收()'d的字节数。期。 –