使用sha-256在postgres中哈希一列

时间:2012-12-03 12:43:47

标签: postgresql

我有一个postrges数据库,其中包含一个表,其中包含使用python函数生成的键代码。我希望能够对此列进行哈希处理,以便每次向其添加密钥代码时,都会对密钥进行哈希处理。我怎么能得到postgres呢?或者什么是存储这些代码的最佳方式。这是我想在表格中散列的列的示例。

 key_codes | 
-----------+
 L7G4J83K  |        
 J70KG169  |         
 L69E540K  |        
 GL8E9C3J  |         
 6C0LE215  |         
 9G01C8JA  |         
 1G9KC58A  |         

3 个答案:

答案 0 :(得分:35)

使用触发器在插入和更新时设置哈希列。对于SHA-256,use the pgcrypto extension module's digest function

由于您尚未指定PostgreSQL版本,我假设您在以下示例中使用了当前的9.2。

以下是调用sha256摘要函数的方法:

regress=# CREATE EXTENSION pgcrypto;
CREATE EXTENSION

regress=> SELECT digest('blah', 'sha256');
                               digest                               
--------------------------------------------------------------------
 \x8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52
(1 row)

请注意,CREATE EXTENSION函数必须以超级用户身份运行。

触发器非常简单。假设您的表格如下所示,这样的事情会发生:

CREATE TABLE some_table ( key_codes text, hash bytea );

CREATE OR REPLACE FUNCTION hash_update_tg() RETURNS trigger AS $$
BEGIN
    IF tg_op = 'INSERT' OR tg_op = 'UPDATE' THEN
        NEW.hash = digest(NEW.key_codes, 'sha256');
        RETURN NEW;
    END IF;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER some_table_hash_update 
BEFORE INSERT OR UPDATE ON some_table 
FOR EACH ROW EXECUTE PROCEDURE hash_update_tg();

用法:

regress=> INSERT INTO some_table(key_codes) VALUES ('fred');
INSERT 0 1
regress=> SELECT * FROM some_table;
 key_codes |                                hash                                
-----------+--------------------------------------------------------------------
 fred      | \xd0cfc2e5319b82cdc71a33873e826c93d7ee11363f8ac91c4fa3a2cfcd2286e5
(1 row)

您可以通过使更新触发器成为条件来减少触发器执行的开销。而不是上述CREATE TRIGGER,请使用以下两者:

CREATE TRIGGER some_table_hash_insert
BEFORE INSERT ON some_table 
FOR EACH ROW 
EXECUTE PROCEDURE hash_update_tg(); 

CREATE TRIGGER some_table_hash_update 
BEFORE UPDATE ON some_table 
FOR EACH ROW 
WHEN ( NEW.key_codes IS DISTINCT FROM OLD.key_codes ) 
EXECUTE PROCEDURE hash_update_tg(); 

答案 1 :(得分:7)

从PostgreSQL 11开始,您可以使用内置函数来计算哈希值:

SELECT sha256('hello world!');
-- x7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9

db<>fiddle demo

  

Other Binary String Functions

+----------------+--------------+---------------+
|   Function     | Return Type  |  Description  |
+----------------+--------------+---------------+
| sha224(bytea)  | bytea        | SHA-224 hash  |
| sha256(bytea)  | bytea        | SHA-256 hash  |
| sha384(bytea)  | bytea        | SHA-384 hash  |
| sha512(bytea)  | bytea        | SHA-512 hash  |
+----------------+--------------+---------------+
     

请注意,由于历史原因,函数md5返回文本类型的十六进制编码值,而SHA-2函数返回bytea类型的值。使用编码和解码功能可在两者之间进行转换,例如,encode(sha256('abc'),'hex')可获取十六进制编码的文本表示形式。

答案 2 :(得分:2)

从PostgreSQL 12开始,您可以使用生成的列。可能很简单:

CREATE TABLE codes (
    ...,
    key_code text,
    sha_code text GENERATED ALWAYS AS (encode(sha256(key_code), 'hex')) STORED
);

与其他方法一样,如果尚未成为架构的一部分,则可能需要CREATE EXTENSION IF NOT EXISTS pgcrypto;

可以选择生成的列并对其进行索引,就像其他任何列一样:

CREATE INDEX idx_sha_codes ON codes USING btree (sha_code);
SELECT id, sha_code FROM codes WHERE sha_code = '...';

有明显的限制,例如他们无法引用其他生成的列或其他表。但是,这种派生值几乎是一个完美的用例。 https://www.postgresql.org/docs/12/ddl-generated-columns.html上有更多内容。