読者です 読者をやめる 読者になる 読者になる

備忘録

備忘録

C# で HMACSHA256を計算する

string CalculateHMACSHA256(byte[] bytes)
{
  using (var hmacsha256 = new HMACSHA256(key))
  {
    var bs = hmacsha256.ComputeHash(bytes.Concat(slalt).ToArray());
    return BitConverter.ToString(bs).ToLower().Replace("-", "");
  }
}

// 出力例
// b248bb2b861e5efe1e5bea3722b19c65ec73f77a64deaf76906cc513f40db534

Photonの生パケットを読む

f:id:kagasu:20170521183308p:plain

Ⅰ. はじめに

1. Photon とは

クロスプラットフォームで動作する「ネットワークエンジン」です。
ドイツのベンチャー企業「Exit Games」が開発しています。

クラウド(SaaS)」と「オンプレミス」が選択できます。
アジアリージョンのクラウドGMOが独占して提供しています。

サーバは Windows Server のみで動作します

2. 仕組み

Photon には「ネームサーバ」と「マスタサーバ」と「ゲームサーバ」が存在します。
※この記事では「ネームサーバ」について触れません。
「マスタサーバ」は「ゲームサーバ」のインスタンスの状態を全て監視します。
負荷状態等をもとにユーザーをどの「ゲームサーバ」に割り当てて通信させるか最適な選択を行います。

Ⅱ. マスタサーバの生パケットを読む

詳しいことはこちらに書いてあるようです。

英語
https://doc.photonengine.com/en-us/onpremise/current/reference/binary-protocol
日本語
https://doc.photonengine.com/ja-jp/onpremise/current/reference/binary-protocol

重要な部分だけをメモ。

1. 赤色の枠で囲んでいる部分を見つける

f:id:kagasu:20170521191036p:plain
画像の場合 0x04 0xF3 0x02 です。

# 意味
1バイト目 データ送信(受信)回数
2バイト目 0xF3固定
3バイト目 不明。0x01~0x10の場合が多い

2. 緑色の枠で囲んでいる部分を見つける

f:id:kagasu:20170521191138p:plain
画像の場合 0xE1 です。
この部分は 「OperationCode」 を意味しています。
0xE1 を 10進数表記すると 225 です。
以下のリファレンスから 225 は OperationCode.JoinRandomGame であることが解ります。
https://photonengine.jp/pun-api/class_exit_games_1_1_client_1_1_photon_1_1_operation_code.html

3. オレンジ色の枠で囲んでいる部分を見つける

f:id:kagasu:20170521191346p:plain
画像の場合 0x00 0x04 です。
この部分は「パラメータが何個あるか」を意味しています。
0x00 0x04の場合4個です。

4. 水色の枠で囲んでいる部分を見つける

f:id:kagasu:20170521191551p:plain
画像の場合 0xD5 です。
この部分は「ParameterCode」を意味しています。
0xD5 を 10進数表記すると 213 です。
以下のリファレンスから 213 は ParameterCode.LobbyName であることが解ります。
https://photonengine.jp/pun-api/class_exit_games_1_1_client_1_1_photon_1_1_parameter_code.html

5. ピンク色の枠で囲んでいる部分を見つける

画像の場合 0x73 です。
f:id:kagasu:20170521192000p:plain
この部分は「GpType」を意味しています。
0x73 を 10進数表記すると 115 です。
GpType は 逆コンパイラを用いて調べます。
以下の表から 115 は GpType.String であることが解ります。

GpType 値(10進数)
Array 121
Boolean 111
Byte 98
ByteArray 120
ObjectArray 122
Short 107
Float 102
Dictionary 68
Double 100
Hashtable 104
Integer 105
IntegerArray 110
Long 108
String 115
StringArray 97
Custom 99
Null 42
EventData 101
OperationRequest 113
OperationResponse 112

6. 茶色の枠で囲んでいる部分を見つける

f:id:kagasu:20170521192910p:plain
画像の場合 0x00 0x01 です。
この部分は「長さ」を意味しています。
0x00 0x01 の場合1バイトです。

5 の項目が GpType.String だったので、String型で1バイトということが解ります。

7. 紫色の枠で囲んでいる部分を見つける

f:id:kagasu:20170521193148p:plain
画像の場合 0x31 です。
この部分は「データの値」を意味しています。
5 の項目が GpType.String だったので、0x31はASCII文字コード表より'A'であることが解ります。

8. これ以降は同様にします。

留意点
・ParameterCode の Enum に含まれてない値が出てきた。
Photon マスタサーバに対する独自の拡張です。
Photon Server (On-Premises) を利用している場合は独自の拡張が可能となります。

・GpType.String は最大 0xFFFF バイトです。
・GpType.ByteArrayは最大 0xFFFFFFFF バイトです。

Ⅲ. ゲームサーバの生パケットを読む

こちらを使います。
WiresharkLua スクリプを読み込むだけです。
https://github.com/AltspaceVR/wireshark-photon-dissector

C#で bzip2 の圧縮、展開を行う方法

Ⅰ. はじめに

タイトルの通り「C#で bzip2 の圧縮、展開を行う方法」です。

Ⅱ. SharpZipLib をインストールする

SharpZipLib というライブラリを使います。

1. NuGet から SharpZipLib で検索し、インストールする。

f:id:kagasu:20170519230429p:plain
※.NET Standard 版もありますが、作成者の名前が異なるので非公式リリースのような気がします。
(深く調べていないので詳細は不明です。)
f:id:kagasu:20170519230500p:plain

Ⅲ. サンプル

1. 圧縮する

private byte[] BZip2Compress(byte[] bytes)
{
  var outStream = new MemoryStream();
  BZip2.Compress(new MemoryStream(bytes), outStream, true, 9);
  return outStream.ToArray();
}

2. 展開する

private byte[] BZip2Decompress(byte[] bytes)
{
  var outStream = new MemoryStream();
  BZip2.Decompress(new MemoryStream(bytes), outStream, true);
  return outStream.ToArray();
}

Ⅳ. その他

isStreamOwner を true にすると自動的に stream を close してくれます。
level は 0-9 までの数値です。0が圧縮率が最低で、9が圧縮率が最高です。

リバースエンジニアリングを楽にする英単語のメモ

Ⅰ. はじめに

タイトルの通り「リバースエンジニアリングを楽にする英単語のメモ」です。
随時追加します。

Ⅱ. 一覧

algorithm
encrypt
encode
decrypt
decode
cipher
extract
rijndael
aes
pkcs
rsa
x509
certificate
key
block
cbc

WebSocket4Net C# .NET Standard対応 WebSocket ライブラリ

Ⅰ. はじめに

WebSocket4Net は2017/05/11 時点でベータ段階ですが .NET Standard 対応の WebSocket ライブラリです。

Ⅱ. 使い方

1. 「プレリリースを含める」にチェックを入れる

2017/05/11 時点で .NET Standard 対応版がベータ段階なのでチェックを入れます。

2. 「WebSocket4Net」で検索し、インストールする

f:id:kagasu:20170511113556p:plain

3. サンプルプログラム
using System;
using WebSocket4Net;

namespace WebSocketSample
{
  class Program
  {
    static void Main(string[] args)
    {
      var websocket = new WebSocket("ws://example.com:81/...");

      websocket.Opened += Websocket_Opened;
      websocket.MessageReceived += Websocket_MessageReceived;
      websocket.Closed += Websocket_Closed;
      websocket.DataReceived += Websocket_DataReceived;
      websocket.Error += Websocket_Error;

      websocket.AutoSendPingInterval = 30;
      websocket.EnableAutoSendPing = true;

      websocket.Open();

      Console.ReadKey();
    }

    private void Websocket_Opened(object sender, EventArgs e)
    {
      Console.WriteLine("Websocket_Opened");
    }

    private static void Websocket_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
    {
      Console.WriteLine("Websocket_Error");
    }

    private static void Websocket_DataReceived(object sender, DataReceivedEventArgs e)
    {
      Console.WriteLine($"Websocket_DataReceived { e.Data }");
    }

    private static void Websocket_Closed(object sender, EventArgs e)
    {
      Console.WriteLine("closed");
    }

    private static void Websocket_MessageReceived(object sender, MessageReceivedEventArgs e)
    {
      Console.WriteLine($"Websocket_MessageReceived { e.Message }");
    }
  }
}