我有一个情况我必须保存一个密码,我建立一个系统连接到另一个系统。 这其他系统只允许单个用户帐户,并连接到它的唯一方法就是通过密码。 哈希不适合这里。 我必须说,我可以检索的方式存储的密码。
现在,用知识,这不是一个完美的系统,我试图减少损失应该有人可以访问数据库莫名其妙。 由于这个数据库将需要通过改变平台上使用,我已经决定使用MySQL自己的内置加密功能。 通过这种方式,我不需要担心找不到各种语言和系统兼容的加密/解密算法的实现。 我可以只使用MySQL的函数的查询。
当存储的口令,我会用AES_ENCRYPT("password", "encryption key")
然后,我意识到,我应该使用一些盐,这样,如果他们能够得到一个密码,这将是很难获得别人。 可是等等! 要点是什么? 如果他们能够得到一个密码,就必须有加密密钥,是吗?
此外,这是一种分组密码。 盐可以在某些情况下近没用。
/* Returns 8CBAB2A9260975FF965E5A7B02E213628CBAB2A9260975FF965E5A7B02E21362FBB5D173CBAFA44DC406B69D05A2072C */
SELECT HEX(AES_ENCRYPT("passwordpasswordpasswordpassword", "encryption key"));
/* Returns 8CBAB2A9260975FF965E5A7B02E213628CBAB2A9260975FF965E5A7B02E21362C49AF8D5B194770E64FEF88767206391 */
SELECT HEX(AES_ENCRYPT("passwordpasswordpasswordpassworda", "encryption key"));
我的问题
通常标准AES你提供一个随机数(该IV),以避免您所描述的问题。
大幅度提高加密数据的质量的一种方法是为每个帐户使用不同的主密码,而不是改变所述IV的。 基本上,这是你的密码混合一些数据。 你可以做到这一点的方法很多,最简单的是做一个CONCAT。
如
- 创建一个随机序列。
- 商店现时|| HEX(AES_ENCRYPT(password_to_store,MASTER_PASSWORD ||随机数)
- 通过提取现时检索,然后用MASTER_PASSWORD解密数据|| 现时。
下面是一个例子,具有独特的随机数“iej383u8fjeiw”(每次加密你需要生成一个新的时间)
SELECT CONCAT('iej383u8fjeiw', ':', HEX(AES_ENCRYPT("password", CONCAT("master_password", "iej383u8fjeiw"))))
-> "iej383u8fjeiw:61224653D4DA33D57A42FE5E5E10DEA9"
SELECT AES_DECRYPT(UNHEX(SUBSTRING_INDEX('iej383u8fjeiw:61224653D4DA33D57A42FE5E5E10DEA9', ':', -1)), CONCAT('master_password', SUBSTRING_INDEX('iej383u8fjeiw:61224653D4DA33D57A42FE5E5E10DEA9', ':', 1)))
-> "password"
或变量:
SELECT CONCAT(nonce, ':', HEX(AES_ENCRYPT(password_to_encrypt, CONCAT(master_password, nonce))))
-> encrypted password
SELECT AES_DECRYPT(UNHEX(SUBSTRING_INDEX(encrypted_password, ':', -1)), CONCAT(master_password, SUBSTRING_INDEX(encrypted_password, ':', 1)))
-> password_to_encrypt
这就是说,虽然显著比没有现时的版本更安全,也有很多的弱点和攻击向量离开。 例如,查询的记录或嗅探MySQL的数据包,就会发现密码和主密码!
文章来源: Block ciphers, salt, AES, MySQL, and best practices around credential storage