- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 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;
}
}
最佳答案
(注意:我不是安全专家。我对该领域感兴趣,但仅此而已。记住这一点。)
这在很大程度上取决于您的需求。最好的选择是根本不使用双向加密。如果你只能存储 salted和 one-way-hashed密码摘要是理想的。您仍然可以测试它们以查看它们是否与用户提供的密码相匹配,但您永远不会存储它。
更好的是,如果您的客户端使用一些合理的协议(protocol)(即:不是通常实现的 HTTP),您可以使用 challenge-response authentication mechanism这意味着您的应用永远永远需要查看用户密码,即使在对用户进行身份验证时也是如此。遗憾的是,这在公共(public)网络上几乎是不可能的,公共(public)网络的安全性会让 80 年代的程序员自愧不如。
如果您必须能够解密密码,理想情况下您不应该将所有详细信息放在一个地方,当然也不应该放在一个可复制、易于访问的地方。
出于这个原因,我个人不喜欢为此目的使用 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/
如何选择随机哈希键?对于 my Flash+Perl card game我正在尝试从哈希中随机选择一张卡片,其中的键是:“6 黑桃”、“6 俱乐部”等,如下所示: my $card; my $i =
每当我收到对端点的请求时,我都会使用openssl crate 生成随 secret 钥。我将使用新生成的 key 来加密请求数据,并将其作为响应发送回去。 use openssl::rsa::{Rs
我们知道,我们在代码中生成的“随机”数实际上是伪随机数。在Java的情况下,它们默认使用时间戳作为随机种子,并且从该点开始确定性地创建时间戳之后产生的每个随机数。 如果您使用随机数生成密码,并且恶意方
我想用java生成一个128位随 secret 钥。我正在使用以下内容: byte[] byteBucket = new byte[bytelength]; randomizer.nextBytes(
这个问题已经有答案了: Pick random property from a Javascript object (9 个回答) 已关闭 7 个月前。 如果我有以下内容: var liststuff
我做了一些研究,找不到我需要的东西,基本上我想生成一个具有以下格式的随 secret 钥 XXX-XXX-XXXX 最佳答案 这是一个快速的 Javascript 解决方案: let r = Math
在 Firebase 中,可以使用 .childByAutoId() 创建随 secret 钥 let newEntry = FBRef.child("category").childByAutoId
假设我有一个带有大量键的对象: const myObject = { "a": 1, "b": 2, "c": 3, ... } 如果我存储了一个单独的 key 列表,
我需要计算一些字符串的签名,并计划这样做: using (HMACSHA256 hmacSha256 = new HMACSHA256( )) { Byte[] dataToHmac
我的任务是生成随机的 80 字节 key ,我决定遵循以下策略 在我的电脑中sizeof(char)=1 所以我创建了一个英文字母数组 char *p=" "; char a[0..26] and i
我正在设计一个广告系统,该系统根据广告的权重(出价)在广告之间随机轮换。 local ads = local ads = { ["a"] = { views = 0,
我有一个整数列表(员工 ID)它们都是8位长(虽然几乎都是00开头,但实际上都是8位长) 我需要为每个员工生成一个 key : - 5 chars including [A-Z][a-z][0-9]
我使用 KeyPairGenerator 生成 RSA key 对,我注意到它始终生成完全匹配的 key ,而不是应有的随 secret 钥?也许有人知道为什么会这样? 我的代码现在看起来像这样: p
我正在运行一个 FIRESTORE 数据库,我想创建一个具有与 firestore 相同的模式 的随 secret 钥。 在链接中,我找到了创建文档后调用的函数with: 'db.ref.add()'
这个问题已经有答案了: Add a property to a JavaScript object using a variable as the name? (14 个回答) Creating ob
我想生成 1M 随机(出现)唯一字母数字键并将它们存储在数据库中。每个 key 的长度为 8 个字符,并且仅使用子集“abcdefghijk n pqrstuvxyz 和 0-9”。 字母 l、m、o
我想生成像“7HzdUakp”这样的唯一 key 。 我想将其放入数据库(mysql)中,但我想要几乎无限的组合。 我可以使用随机函数生成它,但有时它可以生成相同的 key 两次 已解决 - 我根据“
我有一个我似乎无法弄清楚的基本问题。我正在尝试在 AES-256-CBC 中生成一个可用于加密/解密数据的随 secret 钥。 这是我正在做的: require 'openssl' cipher =
如果您对 Azure 网站使用自动缩放,是否需要设置计算 secret 钥,以便可以在计算机之间共享加密的身份验证 token ? 这里有一个问题,似乎be the same正如我所问的那样。然而,这
我想根据创建日期和时间从 Firebase 中检索数据我还没有找到任何其他方法,而不是通过使用 orderByChild("Create") 创建每个用户的 child 来保存创建日期和时间排序,但是
我是一名优秀的程序员,十分优秀!