【问题标题】:Is storing an encrypted cipher key in another table a good idea?将加密的密钥存储在另一个表中是个好主意吗?
【发布时间】:2013-09-13 13:46:40
【问题描述】:

我正在做一个项目,我有一些有价值的信息必须存储在表“成员”中。表结构将如下所示:

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 和用户名。

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

我想确定这是否真的被保存了,或者是否有其他方法来存储密钥。

【问题讨论】:

    标签: database security encryption key aes


    【解决方案1】:

    这称为密钥包装,是的,这样做很安全,但是当您加密密钥时,您应该使用专门为其设计的密码。 This question 有一个很好的解释。

    不确定您使用的是什么语言,但在 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 实现 here

    请记住,但鉴于您的方案,如果用户忘记了他们的密码,您将无法恢复他们的加密数据,因为他们的根密钥是从密码中派生的。 p>

    【讨论】:

    • 我实际上想使用 SHA-512 散列算法的 275000 次迭代来生成派生密钥(解锁包装密钥的密钥)。包装的密钥由 512 个字节的随机字符组成。还保存吗?
    • SHA-512 比 SCrypt 更容易使用 GPU 进行破解优化,并且 SCrypt 的参数允许您调整它使用的 CPU 数量以及内存。您可以使用 SHA-512,但 SCrypt 是更好的选择。
    猜你喜欢
    • 2018-08-26
    • 1970-01-01
    • 2014-03-09
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    相关资源
    最近更新 更多