WebSocketを使用したマルチプレイヤーゲームに取り組んでいます。すべてのユーザーデータはクライアントに保存されるため、パスワードなどを使用した認証は不要になります。
LocalStorage
'save' -> '{"key":"value", "key2":"value2"}'
'hash' -> '<hash of save>'
ユーザーデータをプレーンテキストで保存するだけでなく、(Node.JSを実行している)サーバーでのみ計算できるハッシュも保存するという考え方です。クライアントはsave
とhash
の両方をサーバーに送信して、このセッションのチェックとメモリへのロードを行います。
今、私の質問は:
save
データをハッシュする場合、ユーザーがデータに対して独自のハッシュを生成できないようにするにはどうすればよいですか?必要なのは、データの整合性を保証するものです。
これに対する最も一般的な解決策は、キー付きダイジェストであるHMACを使用することです。 NodeJSには HMACを計算するAPI があります。ソルトをプライベートに保つ「ソルト」ハッシュと比較して、HMACは、長さ拡張攻撃などの追加の攻撃に対しても安全であるように設計されています。
キーを秘密に保つ(そして十分に大きい)限り、すべてのユーザーに同じキーを使用できるはずです。
これにより、以前のバージョンのデータが送信されるのを防ぐことはできません。これにより、データがいつか有効であったことが保証されます。彼らがあなたに最新バージョンを送信していることを確認したい場合は、バージョン番号、タイムスタンプ、または最新のデータダイジェストのいずれかを格納するサーバー側のストレージが必要になります。最後のダイジェストを保存することを選択した場合、通常のハッシュで十分であり、ハッシュまたはHMACをクライアントに送信する必要はありません。
いいえ、ソルト(古典的な意味で-サーバーとクライアントの両方に知られている値)は役に立ちません。
ハッシュを生成するとき、サーバーはそれ自体だけが知っている(そしてクライアントは決して知らない)秘密を使用してそれを暗号化し、それを受け取ったらそれを復号化してチェックする必要があります。
しかし、saltによって、おそらくサーバー専用のシークレットデータ(save
data)の前にある程度(できればかなり大きい)のデータを追加することを意味していたと思います。次に、その結果に対してSHA3(またはHMAC)を実行します。はい、それでも十分に安全です。 (ただし、ユーザーがそれをブルートフォースできないように、シークレットが適度に大きいことを確認してください。1つの大きなシークレットを前に追加し、回復力を高めるために別の大きなシークレットを追加することをお勧めします)。
コメントで@AgentMEが言及したように、一部の Length extension attack が疑われるため、ハッシュアルゴリズムが使用されることに注意してください。