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

昨日の記事で送付するヘッダーは作れたので、今日はメッセージの暗号化を書こうと思います。
[WebSocketのハンドシェイクをエミュレートする](https://qiita.com/ienaga/items/586ec910d2bacd2d8f4f)

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

[参考サイト](https://developer.mozilla.org/ja/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#%E3%83%87%E3%83%BC%E3%82%BF%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%81%AE%E4%BA%A4%E6%8F%9B)

クライアントからサーバーに向かうメッセージは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 ...                |
     +---------------------------------------------------------------+
```

え。。。

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

まじか・・・

やるか・・・



```javascript 
/**
 * @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);
```

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

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

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

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