我正在一个项目中,我有一些有价值的信息,这些信息必须存储在表“ members”中。表结构将如下所示:
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和用户名派生的。
我以为这很省钱,因为如果数据库被盗,小偷将无法派生表'keys'中的键,最终也无法派生出解密的密钥last_name
。
我想确定这是否真的保存,或者是否还有另一种方式来存储密钥。
这称为密钥包装,是的,它是安全的,但是在加密密钥时,应使用专门为此设计的密码。这个问题对原因有一个很好的解释。
不确定您使用的是哪种语言,但是在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实现。
但是请记住,根据您的方案,如果用户忘记了密码,则由于其根密钥是从密码派生的,因此您将无法恢复其加密数据。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句