Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 如何搜索加密属性?_Postgresql_Ruby On Rails 4_Rails Activerecord - Fatal编程技术网

Postgresql 如何搜索加密属性?

Postgresql 如何搜索加密属性?,postgresql,ruby-on-rails-4,rails-activerecord,Postgresql,Ruby On Rails 4,Rails Activerecord,我有一个敏感属性,除了在显示过程中,它必须一直加密(不是我的规则,我认为这太过分了,但我必须遵循这个规则)。此外,用于加密/解密此数据的机密不得位于数据库上或通过数据库访问。因此,目前我为用户提供了一个会话,用于存储他们的加密密码,并在需要时解密这些数据。但是,现在我需要通过加密属性查找记录。我目前使用ActiveSupport::MessageEncryptor对属性进行加密/解密。我认为我应该朝着这个方向努力: decryptor = ActiveSupport::MessageEncryp

我有一个敏感属性,除了在显示过程中,它必须一直加密(不是我的规则,我认为这太过分了,但我必须遵循这个规则)。此外,用于加密/解密此数据的机密不得位于数据库上或通过数据库访问。因此,目前我为用户提供了一个会话,用于存储他们的加密密码,并在需要时解密这些数据。但是,现在我需要通过加密属性查找记录。我目前使用ActiveSupport::MessageEncryptor对属性进行加密/解密。我认为我应该朝着这个方向努力:

decryptor = ActiveSupport::MessageEncryptor.new(encrypted_password)
Family.where("decryptor.decrypt_and_verify(name) == ?", some_search_name)

很明显,这种情况的第一个方面不起作用,但我需要一些方法来做到这一点。有什么想法吗?

数据库密码快速入门

这表明数据库中的加密很困难,除非您仔细考虑了威胁模型并了解了所有的权衡,否则不应该这样做。老实说,我非常怀疑ORM能否在需要加密的地方(出于重要的知识原因)为您提供所需的安全性,而在PostgreSQL上,由于日志文件中可能会泄露密钥,所以这一点尤其困难。一般来说,您确实需要在密码方面适当地保护加密文本和纯文本,因此您确实不希望这里有一个关系接口,而是一个功能接口,查询在完全不同的权限集下运行

现在,在你的例子中,我无法判断你是否在试图保护密码,但如果你是,那完全是错误的做法。下面的示例将使用MD5。现在我知道,加密社区不喜欢MD5,因为它的输出相对较短,但在这种情况下,它的优势是不需要pg_crypto来支持,并且可能比直接攻击密码更强大(在短密码字符串的情况下,它可能“足够好”特别是当与其他措施相结合时)

现在,您要做的是:先对密码进行加密,然后对其进行散列,然后搜索散列值。实现这一点最有效的方法是使用一个不包含密码但包含salt的users表,以及一个包含散列密码但不包含用户可访问数据的shadow表。阴影表将被限制为其所有者,并且该所有者也可以访问用户表

然后您可以编写如下函数:

 CREATE OR REPLACE FUNCTION get_userid_by_password(in_username text, in_password text)
 RETURNS INT LANGUAGE SQL AS
 $$
      SELECT user_id 
        FROM shadow
        JOIN users ON users.id = shadow.user_id
       WHERE users.username = $1 AND shadow.hashed_password = md5(users.salt || $2);
 $$ SECURITY DEFINER;
 ALTER FUNCTION get_userid_by_password(text, text) OWNER TO shadow_owner;
然后,您必须转到SQL来运行此函数(不要通过ORM)。但是,您可以为shadow.hashed_password编制索引,并使其与此处的索引一起工作(因为可以在扫描表之前生成匹配的哈希),并且可以合理地防止SQL注入泄露密码哈希。您仍然必须确保日志记录通常不会启用这些查询,而且还有很多其他的事情要考虑,但它会告诉您如何最好地管理密码本身。或者,在ORM中,您可以执行一些操作,生成SQL查询,如:

  SELECT * FROM users WHERE id = get_userid_by_password($username, $password)
(以上是伪代码,仅用于说明目的。如果使用原始查询(如组装为文本字符串),则要求SQL注入。)

如果不是密码怎么办?

如果您需要可逆加密,那么您需要更进一步。请注意,在上面的示例中,可以使用索引,因为我只是在搜索加密数据上的等式。搜索未加密的数据意味着索引不可用。如果为未加密的数据编制索引,那么首先为什么要对其进行加密?此外,解密确实会给处理器带来负担,因此速度会很慢


在任何情况下,您都需要仔细考虑您的威胁模型,并询问其他漏洞如何使您的密码不那么安全。

MD5不受欢迎“因为输出相对较短”,它不受欢迎是因为它计算速度如此之快,以至于可以非常容易地强制使用,因为它有已知的漏洞。这些漏洞会影响非密码应用程序(如果您在输入时将密码限制为单个密码块大小,那么您是安全的),并且还可以通过小心保护哈希来降低速度。因此,我认为其他措施也很重要。无论如何,向全世界披露散列密码都是不明智的。您的方案的一个改进是在应用程序级别对密码进行一次散列,使用用户名作为salt(因为您尚未检索随机salt),然后将其传递到SQL函数中(并再次散列),从而降低记录SQL的风险(如果有人在没有其他服务器访问权限的情况下读取日志,那么就没有足够的信息通过公共UI重播登录)。这就是为什么我建议在两个地方使用不同的salt进行哈希运算。发送第一个哈希值的安全性不能低于发送纯文本密码的安全性,并且仅使用用户名salt进行计算不需要应用程序尚未处理的信息。