我想存储一些加密的数据,例如密码管理器,其中您的主密码可以解锁所有底层的应用/网站密码。
环顾四周,我发现了一些像this这样的例子,但他们似乎使用密码作为加密的一部分,类似于哈希中的盐。这意味着要解密您需要完全相同的密码,因此您无法更改密码。从安全性/可用性的角度来看,这似乎并不是很好;如果PW受到损害,您必须在不同的PW下重新制作整个数据库。
您如何建立一个可以更改主密码的系统?您是否进行了简单的登录检查,然后使用字符串进行加密/解密?静态性质加上该字符串的存储不会不安全吗?
我知道一些PHP和一些Javascript,所以如果你有这些语言中的例子会很好,但更高级的解释也非常受欢迎。
答案 0 :(得分:4)
有几种方法可行。 Jannes's answer提到了一个可行的解决方案(虽然提防vulnerabilities in openssl_private_decrypt()
)。
如果您正在使用Defuse Security's PHP encryption library,则会抽象出受密码保护的密钥。 (目前有open pull request来解决制作"更改密码"操作无缝且易于使用。)
另请参阅:https://github.com/defuse/php-encryption/blob/master/docs/classes/KeyProtectedByPassword.md
您如何建立一个可以更改主密码的系统?
这样的事情:
secret
。passwordKey
。
Argon2id(password, salt)
=> passwordKey
secret
加密passwordKey
,使用带随机随机数的安全AEAD模式,并将结果与salt一起存储。
$saved = $salt . $nonce . sodium_crypto_secretbox($secret, $nonce, $passwordKey);
secret
加密,而不是passwordKey
。如果您需要更改密码,只需使用新密码(以及不同的盐)重复步骤2和3。
对于Argon2id,您可以在PHP 7.2及更高版本上使用sodium_crypto_pwhash()
。
答案 1 :(得分:1)
您可以使用公钥加密,使用公钥加密数据并使用私钥中的密码进行更改。
一种解决方案是: 1)生成rsa私钥和公钥(在Ubuntu上):
openssl genrsa -des3 -out private.key 1024
openssl rsa -in private.key -pubout > public.key
2)使用公钥加密:
$key = file_get_contents('/path/to/public.key');
openssl_public_encrypt("password", $encryptedData, $key);
将$ encryptedData保存到您的数据库(您不能使用此字符串作为密码哈希来匹配登录,因为$ encryptedData在加密之前添加了随机位,您仍然需要使用哈希函数作为密码)。
3)使用私钥解密,提供密码:
$key = openssl_pkey_get_private(file_get_contents('/path/to/private.key'), $password);
if($key === false) {
// false password
die;
}
openssl_private_decrypt($encryptedData, $decryptedData, $key);
4)更改密码:
openssl rsa -des3 -in private.key -out private.key
这为您提供了两个优势:
这将满足您更改密码而不重新加密数据的主要要求。
如果您想进一步保护您的私钥(不允许php直接访问您的私钥,这对您的应用被黑客攻击很有用),您可以在系统中创建一个解密服务,您可以使用使用密码发送加密数据并获取解密数据。
答案 2 :(得分:-1)
您是否考虑过使用GPG?
http://php.net/manual/en/ref.gnupg.php
或libsoduim PECL扩展
https://pecl.php.net/package/libsodium
使用久经考验的加密与滚动自己将会为您节省时间,但可以根据需要保护您的帐户