gpt4 book ai didi

php - 存储/检索 PGP 私钥和密码的安全方法?

转载 作者:行者123 更新时间:2023-11-29 11:14:04 26 4
gpt4 key购买 nike

我有一个 Web 应用程序需要存储服务器登录信息。我使用 2048 位 PGP 公钥来加密插入的密码(请参阅 insertServerDef),并使用带有密码的私钥来解密密码(请参阅 getServerDef)。

据我了解,这条链中最薄弱的环节是私钥和密码的处理。正如您从我下面的代码中看到的那样,我只是使用 file_get_contents 从位于当前 Web 目录中的文件中检索 key 和密码——这不太好。

我的问题是:安全检索用于解密登录信息的私钥和密码的好方法是什么?也许我应该通过经过身份验证的远程文件服务器存储/检索私钥?

我已经搜索过最佳实践,但找不到太多。

class DB {

protected $_config;
protected $_iUserId;
protected $_iServerId;
protected $_dbConn;
protected $_sPubKey;
protected $_sPrivKey;


public function __construct($iUserId, $iServerId) {

//bring the global config array into local scope
global $config;
$this->_config = $config;

$this->_iUserId = $iUserId;
$this->_iServerId = $iServerId;

$this->_sPubKey = file_get_contents("public_key");
$this->_sPrivKey = file_get_contents("private_key");
$this->_sPrivKeyPass = trim(file_get_contents("private_key_pass"));

}

//connect to the database
public function connect() {
try {


$this->_dbConn = new PDO("pgsql:host=".$this->_config['db_host']." dbname=".$this->_config['db_name'],$this->_config['db_username'],$this->_config['db_password']);

echo "PDO connection object created";
} catch(PDOException $e) {

echo $e->getMessage();

}

}

public function insertServerDef($sHost, $iPort, $sUser, $sPass) {

//testing
$iUserId = 1;

$oStmt = $this->_dbConn->prepare("INSERT INTO upze_server_def (server_id, host_address, ssh_port, username, pass, user_id) VALUES (DEFAULT, :host_address, :ssh_port, :username, pgp_pub_encrypt(:pass,dearmor(:pub_key)), :user_id)");
$oStmt->bindParam(':host_address',$sHost);
$oStmt->bindParam(':ssh_port',$iPort);
$oStmt->bindParam(':username',$sUser);
$oStmt->bindParam(':pass',$sPass);
$oStmt->bindParam(':pub_key',$this->_sPubKey);

$oStmt->bindParam(':user_id',$iUserId);
$oStmt->execute();

}

public function getServerDef($iServerId) {

$oStmt = $this->_dbConn->prepare(" SELECT server_id, pgp_pub_decrypt(pass,dearmor(:priv_key),:priv_key_pass) As decryptpass
FROM upze_server_def usd
WHERE usd.server_id = :server_id
");

$oStmt->bindParam(':server_id', $iServerId);
$oStmt->bindParam(':priv_key', $this->_sPrivKey);
$oStmt->bindParam(':priv_key_pass', $this->_sPrivKeyPass);
$oStmt->execute();

while($row = $oStmt->fetch()) {
echo "<pre>".print_r($row)."</pre>";
}

}

//close any existing db connection
public function close() {
$this->_dbConn = null;
}


//close any existing db connections on unload
public function __destruct() {
$this->_dbConn = null;
}

}

最佳答案

(注意:我不是安全专家。我对该领域感兴趣,但仅此而已。记住这一点。)

如果可能,根本不要存储密码

这在很大程度上取决于您的需求。最好的选择是根本不使用双向加密。如果你只能存储 saltedone-way-hashed密码摘要是理想的。您仍然可以测试它们以查看它们是否与用户提供的密码相匹配,但您永远不会存储它。

更好的是,如果您的客户端使用一些合理的协议(protocol)(即:不是通常实现的 HTTP),您可以使用 challenge-response authentication mechanism这意味着您的应用永远永远需要查看用户密码,即使在对用户进行身份验证时也是如此。遗憾的是,这在公共(public)网络上几乎是不可能的,公共(public)网络的安全性会让 80 年代的程序员自愧不如。

如果您必须存储密码,请将 key 与应用隔离

如果您必须能够解密密码,理想情况下您不应该将所有详细信息放在一个地方,当然也不应该放在一个可复制、易于访问的地方。

出于这个原因,我个人不喜欢为此目的使用 PgCrypto(正如您正在做的那样),因为它会迫使您向服务器透露私钥和(如果有的话)密码短语,它可能是暴露在 PostgreSQL 的日志文件中或以其他方式可能被嗅探。我想做我的加密客户端,在那里我可以使用 PKCS#11、 key 代理或其他工具来解密数据,而无需我的代码能够访问 key 。

安全 key 存储问题是 PKCS#11 的一部分被发明的。它为应用程序和加密提供者提供了一个通用接口(interface),可以与任何可以提供特定签名和解密服务的东西进行对话,永远不会泄露其 key 。通常但不仅限于使用基于硬件的加密,如智能卡和硬件加密模块。这些设备可以被告知对传递给它们的数据进行签名或解密,并且可以在不泄露 key 的情况下这样做。如果可能,请考虑使用智能卡或 HSM。据我所知,PgCrypto 不能使用 PKCS#11 或其他 HSM/智能卡。

如果你做不到,你仍然可以使用 key 管理代理,当服务器启动时,你手动将 key 加载到 key 管理程序中, key 管理程序提供 PKCS#11(或一些other) 通过套接字进行签名和解密的接口(interface)。这样你的网络应用程序就永远不需要知道 key 了。 gpg-agent 可能符合此目的。同样,据我所知,PgCrypto 不能使用 key 管理代理,尽管添加它是一个很棒的功能。

即使是很小的改进也会有所帮助。最好不要将 key 的密码短语存储在磁盘上,这样您可能需要在应用程序启动时输入它,以便可以解密 key 。您仍然将解密的 key 存储在内存中,但解密它的所有详细信息不再在磁盘上并且很容易获得。攻击者从内存中窃取解密 key 比从磁盘中获取“password.txt”要难得多。

您选择做什么在很大程度上取决于您的安全需求细节和您正在处理的数据。在你的位置,我只是尽可能不存储密码,如果必须的话,我想使用 PKCS#11 兼容的硬件设备。

关于php - 存储/检索 PGP 私钥和密码的安全方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12329652/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com