2012-05-13 10 views
2

現在、WebSocketと通信できるC++サーバを稼働させようとしています。 HandShakeはいくつかのステップから成り立ち、私は最後のものでは成功しません。Sha1のC++ Base64 - WebSocketハンドシェイク

最初の手順では、SHA1でエンコードされた文字列を生成し、正しく16進文字列を取得しました。 (例http://en.wikipedia.org/wiki/WebSocket & http://tools.ietf.org/html/rfc6455)。

私の出力は、ドキュメントに記載されているように、両方の場合で同じです:

Wikipedia: 1d 29 ab 73 4b 0c 95 85 24 00 69 a6 e4 e3 e9 1b 61 da 19 69 
My Server: 1d 29 ab 73 4b 0c 95 85 24 00 69 a6 e4 e3 e9 1b 61 da 19 69 

IETF Docu: b3 7a 4f 2c c0 62 4f 16 90 f6 46 06 cf 38 59 45 b2 be c4 ea 
My Server: b3 7a 4f 2c c0 62 4f 16 90 f6 46 06 cf 38 59 45 b2 be c4 ea 

だから、これは正しいです。私は今、Base64エンコードを行うとき、私は次のような結果に来る:

Wikipedia: HSmrc0sMlYUkAGmm5OPpG2HaGWk= 
My Server: MWQyOWFiNzM0YjBjOTU4NTI0MDA2OWE2ZTRlM2U5MWI2MWRhMTk2OQ== 

IETF Docu: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= 
My Server: YjM3YTRmMmNjMDYyNGYxNjkwZjY0NjA2Y2YzODU5NDViMmJlYzRlYQ== 

そして、これは完全に異なります。私はBase64アルゴリズムが特定のオンラインコンバーターで動作することを確認しました。だから、問題は入力形式です。私は同じ問題を抱えていたjavascriptフォーラムでフォーラムのエントリを見つけました。その答えは、40文字の16進数文字列を渡す代わりに、20文字のバイナリ表現を渡す必要があります。

私はopenssl SHA1がバイナリ表現を返しますが、特定の理由でライブラリを使用できないことは知っています。私が使用するSHA1ライブラリは、エンコードされた出力をint配列に置きます。今

std::ostringstream oss; 
oss << std::setfill('0'); 
      for (int i = 0; i < 5; ++i) { 
        oss << std::setw(8) << std::hex << result[i]; 
      } 

大きな問題:私はこのような六角よりも、この変換

result[0] = 3011137324 
result[1] = 3227668246 
result[2] = 2432058886 
result[3] = 3476576581 
result[4] = 2998846698 

:出力は、この(IETF例)のように見えます。私はどのようにバイナリに私の16進文字列を変換できますか?

ありがとうございます。 マルクス

EDIT

誰かがコードに関心がある場合: https://github.com/MarkusPfundstein/C---Websocket-Server

答えて

1

ほとんどBaser64エンコーダバイナリデータのバイト配列/ストリームを期待しています。ビットマスクとロジックシフトを使用して、intをバイトに分割したいとします。 byteResult結果アレイよりバイト[] 4倍大きい

for(i = 0; i < 5; i++) { 

    byteResult[(i * 4) + 0] = result[i] & 0x000000ff; 
    byteResult[(i * 4) + 1] = (result[i] & 0x0000ff00) >> 8; 
    byteResult[(i * 4) + 2] = (result[i] & 0x00ff0000) >> 16; 
    byteResult[(i * 4) + 3] = (result[i] & 0xff000000) >> 24; 
} 

を次のように各intは4つのバイトを含む32ビットシステムでは、それらを抽出することができます。私はバイトがintsにここにパックされていると仮定している、それは別の方法ラウンドかもしれない。

このバイト[]をBase64エンコーダに渡します。

+0

私は非常に試してみます –

+0

非常に申し訳ありませんが、それは動作しません:(結果は5の配列ですので、私は列挙子をi <5にする必要はありませんか?それはまた非常に奇妙な出力を生成します –

+0

申し訳ありません、私はバイトオーダーに関する私の注意を参照してください。どのように出力が奇妙ですか? –

2

私はcでwebsocketをテストしていましたが、バイトが間違った順序であることが判明しました。順序を適応させる(逆に)正しい受け入れられたキー文字列で、その結果、base64エンコーディングと私の問題を解決:やや関連のノートで

unsigned char byteResult [20]; 
    for(i = 0; i < 5; i++) { 
     byteResult[(i * 4) + 3] = sha.result[i] & 0x000000ff; 
     byteResult[(i * 4) + 2] = (sha.result[i] & 0x0000ff00) >> 8; 
     byteResult[(i * 4) + 1] = (sha.result[i] & 0x00ff0000) >> 16; 
     byteResult[(i * 4) + 0] = (sha.result[i] & 0xff000000) >> 24; 
    } 
+0

ここであなたは私がそれを固定した方法を見ることができます(Connection :: Authenticate()メソッドhttps://github.com/MarkusPfundstein/C---Websocket-Server/blob/master/Network/Connection.cc –

1

は(私はあなたがすでにEVP BIO base64 wayを発見見...):私が正しく理解していれば

result[0] = 3011137324 
... 
oss << std::setw(8) << std::hex << result[i]; 

これはあなたのIETFドキュ例である出力b37a4f2c、になります。あなたがプラットホーム特有の開放的な水の危険についているので、ここでは非常に注意してください。endianess 0n3011137324は確かに0xb37a4f2cですが、はIntelアーキテクチャのようにリトルエンディアンのマシンでのみです。おそらく、&result[0]unsigned char*にキャストし直してから、(符号なし)intの配列ではなく、バイトの配列として扱う方がよいでしょう。

関連する問題