リンク先のページにプロセスが記述されていますが、詳細を確認してC#の例を示します。
まず、発生するハッシュが2つあります。あなたが賭けるときにサーバーがサーバーキーを変更していないことを証明する一般的なハッシュの1つは、このハッシュは秘密ではなく、プレイの開始時にプレイヤーに与えられます。実際にダイスロールを生成するためのキー付きハッシュ(HMACと呼ばれる)もあり、サーバーキー、ユーザーが提供したデータ、およびカウントアップする数字の組み合わせを使用します。ここで
が起こるプロセスである:
- サーバーがプレイセッションのための秘密鍵を生成し、0
- SHA256にカウンタを設定しますが、ハッシュを生成するためのキーで使用され、このハッシュプレーヤーに与えられる。このハッシュは、ダイスロールを生成するための数学では使用されません。プレーヤーの検証にのみ使用されます。
- プレイヤーはサイコロロールを要求し、番号の生成に使用するフレーズを提供します。
- サーバーは、秘密キーをキーとして使用し、ユーザーが指定した文字列に「 - 」とステップ1で設定したカウンターの番号を加えてハッシュを生成するSHA512-HMACを使用します。
- サーバはカウンタを1ずつインクリメントします。これは同じサーバキーが毎回使用され、同じユーザ文字列が使用された場合に同じ番号を何度も繰り返し生成するために行われます。
- サーバーは、生成されたハッシュの最初の21ビットを取り出し、
int
に変換してから、999999以上でない番号が見つかるまで繰り返している場合、int
が999999より大きいかどうかを確認します。
- 手順6から番号を取り、
number%(10000)/100.0
に浮動小数点数を取得します。
- その浮動小数点数がユーザーに返されます。
- 手順3で新しいロールを開始するか、手順10に進みます。
- プレイセッションは終了しました。サーバは秘密鍵をユーザに返し、ステップ1で再起動する。
ステップ10の秘密鍵を取得すると、ユーザーはSHA256を使用してハッシュし、再生セッションの開始時に聞いたのと同じハッシュを取得することができます。その後、彼は秘密鍵を持っていて、サーバーがダイスロールを偽造していないことを確認した後、サーバーが行ったすべてのステップを再実行できます。コード内でこれを行う方法を
:
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace SandboxConsole
{
public class Result
{
public Result(string hmacMessage, float roll)
{
HmacMessage = hmacMessage;
Roll = roll;
}
public string HmacMessage { get; }
public float Roll { get; }
}
class FairDiceRollServer
{
private byte[] _serverKey;
private ulong _nonce;
public byte[] StartSession()
{
if (_serverKey != null)
throw new InvalidOperationException("You must call EndSession before starting a new session");
//Generate a new server key.
using (var rng = RandomNumberGenerator.Create())
{
_serverKey = new byte[128];
rng.GetBytes(_serverKey);
}
_nonce = 0;
//Hash the server key and return it to the player.
using (var sha = SHA256.Create())
{
return sha.ComputeHash(_serverKey);
}
}
public Result RollDice(string userKey)
{
if(_serverKey == null)
throw new InvalidOperationException("You must call StartSession first");
if(_nonce == ulong.MaxValue)
throw new InvalidOperationException("Ran out of Nonce values, you must start a new session.");
using (var hmac = new HMACSHA256(_serverKey))
{
float? roll = null;
string message = null;
while (roll == null)
{
message = userKey + "-" + _nonce;
_nonce++;
var data = Encoding.UTF8.GetBytes(message);
var hash = hmac.ComputeHash(data);
roll = GetNumberFromByteArray(hash);
}
return new Result(message, roll.Value);
}
}
private float? GetNumberFromByteArray(byte[] hash)
{
var hashString = string.Join("", hash.Select(x => x.ToString("X2")));
const int chars = 5;
for (int i = 0; i <= hashString.Length - chars; i += chars)
{
var substring = hashString.Substring(i, chars);
var number = int.Parse(substring, System.Globalization.NumberStyles.HexNumber);
if(number > 999999)
continue;
return (number % 10000)/100.0f;
}
return null;
}
public byte[] EndSession()
{
var key = _serverKey;
_serverKey = null;
return key;
}
}
}
それの使用例で
使用algorthom、
RollDice
によって返された情報とに与えられたキーに関する公開された情報を使用して
using System;
using System.Linq;
namespace SandboxConsole
{
class Program
{
private int _test;
static void Main(string[] args)
{
var server = new FairDiceRollServer();
var hash = server.StartSession();
Console.WriteLine(string.Join("", hash.Select(x => x.ToString("X2"))));
for (int i = 0; i < 10; i++)
{
var roll = server.RollDice("My Key");
Console.WriteLine("Message: {0} Result: {1}", roll.HmacMessage, roll.Roll);
}
var key= server.EndSession();
Console.WriteLine(string.Join("", key.Select(x => x.ToString("X2"))));
Console.ReadLine();
}
}
}
ユーザーはEndSession
から返され、すべてのダイスロールを再作成してサーバーが本当にランダム世代を行ったことを証明することができます(サーバーが選択することができなかったロールのユーザーのおかげで)それは損失を引き起こすことが保証されています。
* 1つの質問につき質問してください.4つではありません。詳細については、[Meta](https://meta.stackexchange.com/questions/39223/one-post-with-multiple-questions-or-multiple-posts)を参照してください。 – Amy
申し訳ありませんが、私は、複数の関連する質問をまとめることができると仮定しましたが、すべて同じ金額で公平なダイスロールを生成します。 –