1
0

More than 3 years have passed since last update.

Flash Advent Calendar 15日目 - WebSocketのメッセージの暗号化 -

Last updated at Posted at 2020-12-16

昨日の記事で送付するヘッダーは作れたので、今日はメッセージの暗号化を書こうと思います。
WebSocketのハンドシェイクをエミュレートする

昨日も書きました、これらの処理はブラウザがやってくれるので
本来は自前でやる必要のない機能なので、笑い話としてみてもらえればと思います。

参考サイト

クライアントからサーバーに向かうメッセージはXOR暗号化(32ビットキー)を使用してマスクされます。

フォーマット

Frame format:
​​
      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+

え。。。

これやらないと、メッセージを送れないの??

まじか・・・

やるか・・・

/**
 * @param  {string} value
 * @return {array}
 * @public
 */
stringToArray = function (value)
{
    const array  = [];
    const length = value.length;
    for (let idx = 0; idx < length; ++idx) {

        const code = value.charCodeAt(idx);
        if (code > 127) {

            const values = encodeURIComponent(value[idx]).split("%");
            const length = values.length;
            for (let idx = 1; idx < length; ++idx) {
                array[array.length] = parseInt(values[idx], 16);
            }

            continue;
        }

        array.push(code);
    }

    return array;
};

/**
 * @param {Event} event
 * @return {void}
 * @public 
 */
function (event)
{
    // ByteArrayクラスも自前する必要があるのですが、ここはまたいつか・・・
    const byteArray = new ByteArray();

    byteArray.writeByte(129); // fixed opcode 1 only

    // 受け取ったメッセージを数値に変換
    const values = stringToArray(event.data);

    let length = values.length;
    if (126 > length) {

        // メッセージが126桁以下ならペイロードの長さをセット
        byteArray.writeByte(length);

    } else if (length > 125 && length < 65536) {

        // 126以上なら固定値で126をセットして、次にペイロードの長さをセット
        byteArray.writeByte(126);
        byteArray.writeShort(length);

    } else {

        // 65536以上なら固定値で127をセットして、判定の0を入れてペイロードの長さをセット
        byteArray.writeByte(127);
        byteArray.writeUnsignedInt(0);
        byteArray.writeUnsignedInt(length);

    }

    // 最後に文字列を数値化したデータをセット 
    byteArray.length += length;
    byteArray.set(values, byteArray.position);

ヘッダーと一緒に送信して完了です。

メッセージを送るだけでも一苦労です。。。

これを、ブラウザは自動でやってくれるので本当に感謝です。。。

明日は何を書こうかな・・・

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0