您如何对编码或加密数据进行 PostgreSQL 全文搜索?

Set*_*eth 5 sql encryption postgresql base64

出于各种无关紧要的原因,我们在 PostgreSQL 中以加密或 base64 编码格式存储文本块。但是,我们希望能够使用 PostgreSQL 的全文搜索来查找和返回未加密/解码形式与搜索查询匹配的数据。

人们将如何实现这一目标?我已经看到其他帖子提到在将数据发送到数据库之前构建 tsvector 值的能力,但我希望在 Postgres 端会有一些可用的东西(至少对于 base64 文本)。

Cra*_*ger 6

加密值

对于加密值,您不能。即使您创建了tsvector客户端,tsvector 也会包含一种加密文本形式,因此大多数应用程序都无法接受。观察:

regress=> SELECT to_tsvector('my secret password is CandyStrip3r');
               to_tsvector                
------------------------------------------
 'candystrip3r':5 'password':3 'secret':2
(1 row)
Run Code Online (Sandbox Code Playgroud)

……哎呀。如果您创建该值客户端而不是使用 并不重要to_tsvector,它仍然会以明文形式保存您的密码。您可以对 tsvector 进行加密,但随后就无法将其用于全文搜索。

当然,鉴于加密值:

CREATE EXTENSION pgcrypto;

regress=> SELECT encrypt( convert_to('my s3kritPassw1rd','utf-8'), '\xdeadbeef', 'aes');
                              encrypt                               
--------------------------------------------------------------------
 \x10441717bfc843677d2b76ac357a55ac5566ffe737105332552f98c2338480ff
(1 row)
Run Code Online (Sandbox Code Playgroud)

可以(但不应该)做这样的事情:

regress=> SELECT to_tsvector( convert_from(decrypt('\x10441717bfc843677d2b76ac357a55ac5566ffe737105332552f98c2338480ff', '\xdeadbeef', 'aes'), 'utf-8') );
    to_tsvector     
--------------------
 's3kritpassw1rd':2
(1 row)
Run Code Online (Sandbox Code Playgroud)

...但是如果在代码显示框中向右滚动后问题不是很明显,那么你真的应该让其他人为你做你的安全设计;-)

关于在不解密加密值的情况下对加密值执行操作的方法进行了大量研究,例如将两个加密数字相加以产生使用相同密钥加密的结果,因此进行添加的过程不需要解密输入的能力以获得输出。其中一些可能适用于 fts - 但它远远超出了我在该领域的专业知识水平,并且可能会非常低效和/或密码薄弱。

Base64 编码的值

对于 base64,decode在将 base64 送入to_tsvector. 因为decode返回 abytea并且您知道编码的数据是您需要用来将convert_from其解码byteatext数据库编码中的文本,例如:

regress=> SELECT encode(convert_to('some text to search','utf-8'), 'base64');
            encode            
------------------------------
 c29tZSB0ZXh0IHRvIHNlYXJjaA==
(1 row)

regress=> SELECT to_tsvector(convert_from( decode('c29tZSB0ZXh0IHRvIHNlYXJjaA==', 'base64'), getdatabaseencoding() ));
     to_tsvector     
---------------------
 'search':4 'text':2
(1 row)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我使用数据库编码作为 的输入convert_from,但您需要确保使用底层base64编码文本所在的编码。您的应用程序负责正确处理。我建议要么将编码存储在第二列中,要么确保您的应用程序始终utf-8在应用base64编码之前一样对文本进行编码。