2016-12-04 3 views
0

私のサーバーからメッセージをクライアントに送信しようとしています。メッセージの確認に問題があります。私は、wikiで提供されているコード例に基づいて、フィルタリングされた方法とフィルタリングされていない方法を試しました。私はGoogleで見つけることができるほとんどすべてを試しましたが、私はうんざりしています。ソケット上でメッセージ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

ソケットに移動する前に、まずローカルファイルで練習してください。たぶん、Googleの[プロトコルバッファ](http://developers.google.com/protocol-buffers/)は、ソケットの詳細を抽象化するのに役立つでしょう。これらも機能するので、コード内の低レベルのバグをクリアすることについて心配する必要はありません。 – jww

答えて

1
string signature; 

// ... 

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

std::stringある比較的小さなクラスです。私のstd::stringは32バイトです。だから私のsizeof(signature)は32です。

sizeof(signature)はおそらく同じです。そして、あなたが知っているように、sizeofはコンパイル時定数です。文字列に数バイトか数メガバイトが含まれているかどうかにかかわらず、32または16などになります。

あなたがしなければならないことは、書き込むバイト数を決定するのにsignature.size()を使用することです。

また、使用しているソケットAPIライブラリは不明ですが、ほとんどのAPIでは要求されたバイト数を正常に送信できないことがあります。指定されたバイト数を送信する要求は、通常、書き込まれたバイト数を返します。これは少なくてもかまいません。その場合、再試行する必要があります。同じことがソケットからの読み取りにも当てはまります。受信すると予想されるバイト数を事前に知っていなければなりません。バイト数を減らすと、読み続ける必要があります。

戻り値をSend()Receive()にチェックして、適切な処置を講ずる必要があります。

+0

文字列サイズの問題に気付きましてありがとうございます。私は階段を上っていて、物事を変えてしまったので、その途中でその詳細を逃した。私はCrypto ++ Socket APIを使用しています。私は署名検証以外に何か問題はありませんでした。私はRSAの暗号化と復号化もやっており、うまくいきます。私が送信側の署名をしているのは、MITM Diffie-Hellman攻撃を止めようとしているからですが、公開鍵と秘密鍵のペアは1つしかありません。私は攻撃の片側だけを切り離すことができますが、それは問題ありません。 –

+0

サイズの問題も修正しました。まだパイプラインフィルタ法を使用した検証はありません。それはうまくいかない? –

+0

'byteBuf'バッファもクリアしていないようです。おそらく、ランダムなジャンクを含んでいます。 'Receive()'はそれにバイトをダンプしており、明示的に '\ 0'を終了していません。 'std :: string'sにはnullバイトを入れることができ、プレーンバッファから文字列や文字列ストリームを初期化すると、最初の' '\ 0''までしかすべてを収集しないことに注意してください。実際、その文字列全体は有用な目的を果たさない。 'Receive()' dのバイト数を正確に知る必要があります。期間。 –

関連する問題