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使用密钥加密。该密钥存储在表“密钥”中:

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

这些密钥也使用另一个密钥加密,该密钥源自未散列的密码、id 和用户名。

我认为这是保存,因为如果数据库被盗,窃贼无法导出表“密钥”中的密钥,最终无法导出解密last_name.

我想确定这是否真的被保存了,或者是否有另一种存储密钥的方法。

4

1 回答 1

1

This is called key wrapping and yes it's safe to do, but when you're encrypting your keys you should use a cipher specifically designed for it. This question has a decent explanation as to why.

Not sure what language you're using, but in Java you'd do it like this:

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);

Also be sure to use a good key derivation function such as SCrypt to derive each users root key. Bouncy Castle has SCrypt implementations for both Java and C#, as well as it's own key wrap implementations. Or a you can find a PHP SCrypt implementation here.

Do keep in mind though, given your scheme, if a user forgets their password you won't be able to recover their encrypted data because the their root key is derived from the password.

于 2013-09-14T14:55:07.157 回答