チリペヂィア

リンクフリー。サンプルコードなどは関連記事内でライセンスについて明示されない限り商用利用なども自由に行って構いませんが、自己責任でお願いします。またこれら日記内容の著作権自体は放棄していません。引用部分については引用元の権利に従ってください。

端末固有のハッシュ生成

通信する時はユニークなプレーヤー識別か装置識別があると便利。

仮にサーバーを立ててSNSとの連携やランキング等を扱うのであればプレーヤー情報のDBとともにプレーヤー識別システムを独自に設計すると思いますが、そこまで商魂たくましいわけでもなければ装置の識別で事は足ります。それには、UnityではSystemInfo.deviceUniqueIdentifierを持ってくれば万事解決!

と思ったら。まずWinXP32sp3(自作機)でアサーション発生。どうもdeviceUniqueIdentifier内部でHRESULT()マクロがassertしているようです。しかし一応値は返してくれているのですが、まずこれが原因不明…というより調べてみるとそれ以前の問題が判明してdeviceUniqueIdentifierの使用を諦めました。

  • android2.2以前では、全デバイスで共通の値を返してしまう(全然ユニークじゃない)。
  • iOS実装で現在使っているUDIDは、iOS5以降では打ち切りの予定。

要するに「各環境で各装置のシリアルナンバーを取得する処理のクロスプラットフォームラッパー関数のつもりで作ってたんだけど、とても擦り合わせられそうもなくなってしまった処理」て事みたいです。とりあえず今はアテに出来そうもなく、将来的に楽観視するかどうか…。というわけで.NetライブラリからMacアドレスを取得する作戦にします(*1)。とりあえず以下の方法で何らかのMACアドレスは取得できます(WIN/MACで動作を確認。iOSAndroidでは未確認)。

// get first find mac address
byte[] bytes = null;
System.Net.NetworkInformation.NetworkInterface[] allNics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
if ( allNics != null ) foreach ( System.Net.NetworkInformation.NetworkInterface ni in allNics ) {
	System.Net.NetworkInformation.PhysicalAddress addr = ni.GetPhysicalAddress();
	if ( addr != null ) bytes = addr.GetAddressBytes();
	if ( bytes != null && 6 == bytes.Length ) {
		Debug.Log( addr.ToString() ); // find first mac address
	}
}

なんとなくMACアドレスを生で送受信するのは気が引けるので、幸い6バイトと短くも半端な長さのMACアドレスに加え、以下の文字列からGetHashCode()を抜いて64bitか128bitを冗長に埋めてバイト並べ替えやらXOR暗号やら等値演算子のオーバーライドやら、軽く誤魔化しといた方が良さそうです。

System.deviceModel System.deviceName
Win自作 CPU名にシステムメモリサイズが記録された文字列 コンピューター名(LANで共有する時とかに使う名前)
iMac iMac5.1とかの機種名 Winと同じ、システムにつけてある名前

しかしとは言えスマホはともかく、WinPCではLANの有効/無効とUSB無線子機の抜き差しなんかでも取得できるMACアドレスはコロコロ変わりそうですね。運用にはコツが入りそうな…例えば、ノートPCとかでボード標準のLANを無効にして、USB無線子機で接続し無線子機のMACアドレスでIDを生成した後、無線子機を抜いてLANを復帰するなり別の接続で再接続し、今度は別のノートに先ほどの子機をつないで、ID生成させてしまうと通信先が自分と同じID、みたいな事になりかねません。ある程度頻繁にIDを再生成するとか、何かしらの運用方法は考えた方が良さそうです。

*1:ちなみに、手元のリース落ちiMACOSX突っ込んだMAC機でdeviceUniqueIdentifierを取得すると、LANデバイスのMACアドレスをもとに冗長化した数値列で返ってきました。なんだ結局MACアドレスしかないんやん…