匿名ユーザーがイベントに関する詳細を入力し、データベースで暗号化して、そのユーザーまたはユーザーが作成時に決定したイベントごとのパスワードを持つ人だけが取得できる Rails 3 Web アプリを作成しています。 .
これはすべて、暗号化とハッシュを使用したプログラミングに頭を悩ませるための演習として行っているため、少しやり過ぎかもしれませんが、「最も安全な」方法の作業モデルが必要です。二要素認証や、地殻の30km下の秘密の金庫に隠されたネットワークに接続されていないコンピューター(私はすでに2つ持っています)に入る必要はありません。
私が保存している現在のデータとそのすべての暗号化は次のとおりです。安全でない方法や、アプリケーション (特にユーザーのデータ) を攻撃するのに弱体化させるような方法を使用しているかどうかについて、フィードバックをお願いします。 .
すべてのイベントには、透過的データ暗号化を使用して Oracle データベースに格納された次のフィールドがあります。
- ID
- イベント_データ
- password_hash
- 暗号化された_iv
- 暗号化されたキー
- admin_retrievable_event_data
- admin_encrypted_iv
- admin_encrypted_key
Web サーバーは制限されたシステム権限で実行され、完全にパッチが適用されており、Web サーバー プロセスはサイトのディレクトリ構造の外を参照できません。Web サーバーは HTTPS のみを実行します。
ユーザーは、イベントを作成するときに、event_data フィールドに入力するクリアテキスト データと、そのデータを保護するためのパスワードを提供します。データを取得するには、フォームを送信した後に与えられた ID 番号と、選択したパスワードを入力するだけです。イベントの作成中に、ユーザーはチェックボックスをオンにして、必要に応じて管理者が取得可能なデータを生成できるようにすることもできます。このオプションは、デフォルトで false に設定されています。
このイベントの平文は、後で説明するように、管理者が取得する目的で引き続きメモリに保持されます。
イベント データは、安全に生成されたランダムな IV とキーを使用して AES256 CBC 暗号化を使用して保護されます。次に、IV とキーの両方が、サーバーに保存されている公開キー (RSA 2048 ビット) を使用して暗号化されます。次に、IV とキーの両方が、ユーザーが指定したパスワードの SHA-256 ハッシュと XOR され、その後両方が DB に格納されます。
次に、ユーザーパスワードは、安全にランダムに生成された 256 ビットのトークンをソルトとして使用して SHA-256 でハッシュされ、ハッシュとソルトを含むコロン区切り文字で文字列が作成され、公開鍵 (前と同じもの) で暗号化されます。 )、データベースの password_hash フィールドに保存されます。
次に、平文のイベント データは、新しくランダムに生成されたキーと管理者の取得用の IV を使用して同じプロセスを経て保存され、キーと IV は別の公開キー (管理者の取得にのみ使用) で暗号化されて、何に対しても XOR を使用せずにデータベースを作成します。
データを取得するには、ユーザーはイベント ID とパスワードを入力します。最初に、password_hash が秘密鍵 (サーバー上の Web からアクセスできないディレクトリに保存されている) を使用して暗号化されていない (その秘密鍵のパスワードはアプリにハードコーディングされている)。ユーザーが入力したパスワードは、現在暗号化されていないデータベース エントリからソルトを取得し、保存されているソルト化されたパスワードのハッシュと一致する場合、プロセスは続行されます (そうでない場合は、「イベント ID が見つからないか、パスワードが正しくありません」というエラーが返されます)。
暗号化されたキーと IV は、新しく生成されたユーザーのパスワードのソルトなしのハッシュと XOR され、パスワード ハッシュに使用されたのと同じ秘密キー/パスワードで復号化されます。これらはその後、event_data を復号化するために使用され、データをユーザーに返します。
管理者がデータを取得したい場合は、秘密鍵をアップロードし、秘密鍵のパスワードを入力する必要があります。この時点で、管理者の IV と鍵が復号化され、メモリ内の秘密鍵が破棄され、管理者が取得可能なイベント データが復号化されます。 .
つまり、これが私の設計です。現在私が特定した唯一の弱点は、イベントとユーザー パスワードの暗号化に使用される秘密鍵をサーバーに保存し、その秘密鍵のパスワードをアプリにハード コードすることです。ただし、ハードウェアベースの暗号化アプライアンスに多額の費用を費やさない限り、それを回避する方法はわかりません. イベントごとに個別の証明書を生成し、秘密鍵を提供して、イベントを復号化するたびに再アップロードを強制することで、その問題を回避し、エンドユーザーに不便をかけないように、これを設計するより良い方法を誰かが提案できる場合データ、私はそれに対してオープンです。
それら以外の問題が見られた場合は、私もそれについて聞きたいと思っています。また、問題の内容とそれを修正するために私ができることについて、読むためのリソースや説明を提供していただければ幸いです。
私は大学レベルの数学知識を持っておらず、むしろ暗号を理解したいと思っていますが、暗号解析を自分で行うことができるレベルにはほど遠いことをご了承ください。このプロジェクトでは、私が理解できるレベルの概要をできるだけ多く読み、その知識を適用しようとしました。