web-dev-qa-db-ja.com

ローカルに保存された文字列の改ざんをチェックする

WebSocketを使用したマルチプレイヤーゲームに取り組んでいます。すべてのユーザーデータはクライアントに保存されるため、パスワードなどを使用した認証は不要になります。

LocalStorage
'save' -> '{"key":"value", "key2":"value2"}'
'hash' -> '<hash of save>'

ユーザーデータをプレーンテキストで保存するだけでなく、(Node.JSを実行している)サーバーでのみ計算できるハッシュも保存するという考え方です。クライアントはsavehashの両方をサーバーに送信して、このセッションのチェックとメモリへのロードを行います。

今、私の質問は:

  • SHA256を使用してすべてのsaveデータをハッシュする場合、ユーザーがデータに対して独自のハッシュを生成できないようにするにはどうすればよいですか?
  • 次に、(パート1への答えが「塩」であると仮定して)、塩を使用すると私を安全に保つことができますか、またはこれを計算できますか? (ユーザーごとに部分的にソルトを変えることができます)
3
Peter Gordon

必要なのは、データの整合性を保証するものです。

これに対する最も一般的な解決策は、キー付きダイジェストであるHMACを使用することです。 NodeJSには HMACを計算するAPI があります。ソルトをプライベートに保つ「ソルト」ハッシュと比較して、HMACは、長さ拡張攻撃などの追加の攻撃に対しても安全であるように設計されています。

キーを秘密に保つ(そして十分に大きい)限り、すべてのユーザーに同じキーを使用できるはずです。

これにより、以前のバージョンのデータが送信されるのを防ぐことはできません。これにより、データがいつか有効であったことが保証されます。彼らがあなたに最新バージョンを送信していることを確認したい場合は、バージョン番号、タイムスタンプ、または最新のデータダイジェストのいずれかを格納するサーバー側のストレージが必要になります。最後のダイジェストを保存することを選択した場合、通常のハッシュで十分であり、ハッシュまたはHMACをクライアントに送信する必要はありません。

4
user2313067

いいえ、ソルト(古典的な意味で-サーバーとクライアントの両方に知られている値)は役に立ちません。

ハッシュを生成するとき、サーバーはそれ自体だけが知っている(そしてクライアントは決して知らない)秘密を使用してそれを暗号化し、それを受け取ったらそれを復号化してチェックする必要があります。

しかし、saltによって、おそらくサーバー専用のシークレットデータ(save data)の前にある程度(できればかなり大きい)のデータを追加することを意味していたと思います。次に、その結​​果に対してSHA3(またはHMAC)を実行します。はい、それでも十分に安全です。 (ただし、ユーザーがそれをブルートフォースできないように、シークレットが適度に大きいことを確認してください。1つの大きなシークレットを前に追加し、回復力を高めるために別の大きなシークレットを追加することをお勧めします)。

コメントで@AgentMEが言及したように、一部の Length extension attack が疑われるため、ハッシュアルゴリズムが使用されることに注意してください。

1
Matija Nalis