0

テーブル「メンバー」に保存する必要がある貴重な情報があるプロジェクトに取り組んでいます。テーブル構造は次のようになります。

id | username | password | salt | last_name 
———|——————————|——————————|——————|———————————
 1 | VARCHAR  |   HASH   | CHAR |    BLOB   
 2 | VARCHAR  |   HASH   | CHAR |    BLOB   
 3 | VARCHAR  |   HASH   | CHAR |    BLOB   
 4 | VARCHAR  |   HASH   | CHAR |    BLOB   
 5 | VARCHAR  |   HASH   | CHAR |    BLOB   

この例でlast_nameは、 は鍵で暗号化されています。そのキーはテーブル 'keys' に保存されます。

id | key  
———|—————— 
 1 | BLOB 
 2 | BLOB 
 3 | BLOB 
 4 | BLOB 
 5 | BLOB 

これらのキーは、ハッシュ化されていないパスワード、ID、およびユーザー名から派生した別のキーでも暗号化されます。

データベースが盗まれた場合、泥棒はテーブル「キー」のキーを導出できず、最終的にlast_name.

これが本当に保存されているかどうか、またはキーを保存する別の方法があるかどうかを確認したかった.

4

1 に答える 1

1

これはキー ラッピングと呼ばれ、安全に実行できますが、キーを暗号化する場合は、そのために特別に設計された暗号を使用する必要があります。この質問には、その理由についての適切な説明があります。

使用している言語はわかりませんが、Java では次のようにします。

Key rootKey = new SecretKeySpec(keyBytes, "AES");
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128);
Key keyToWrap = generator.generateKey();

Cipher cipher = Cipher.getInstance("AESWRAP");
cipher.init(Cipher.WRAP_MODE, rootKey);
byte[] wrappedKey = cipher.wrap(keyToWrap);

Cipher uncipher = Cipher.getInstance("AESWRAP");
uncipher.init(Cipher.UNWRAP_MODE, rootKey);
Key unwrappedKey = uncipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);

また、SCrypt などの適切なキー派生関数を使用して、各ユーザーのルート キーを派生させてください。Bouncy Castleには、Java と C# の両方の SCrypt 実装と、独自のキー ラップ実装があります。または、ここでPHP SCrypt の実装を見つけることができます。

ただし、スキームを考えると、ユーザーがパスワードを忘れた場合、ルートキーがパスワードから派生しているため、暗号化されたデータを回復できないことに注意してください

于 2013-09-14T14:55:07.157 に答える