Skip to content

Latest commit

 

History

History
209 lines (135 loc) · 5.9 KB

20221215_01.md

File metadata and controls

209 lines (135 loc) · 5.9 KB

使用 PostgreSQL 大对象和pgcrypto加解密文件

作者

digoal

日期

2022-12-15

标签

PostgreSQL , PolarDB , extension , pgcrypto , 加解密 , bytea , 文件 , 大对象


背景

1、如何将文件导入为bytea

三种方法, 根据版本选择, 新版本直接使用read函数

-- 1  
create or replace function bytea_import(p_path text, p_result out bytea)   
                   language plpgsql as $$  
declare  
  l_oid oid;  
begin  
  select lo_import(p_path) into l_oid;  
  select lo_get(l_oid) INTO p_result;  
  perform lo_unlink(l_oid);  
end;  
$$;  
  
-- 2  
pg_read_binary_file('/path/to/file')  
  
-- 3  
pg_read_file('location_of file')::bytea  

2、如何加密bytea内容

pgp_sym_encrypt_bytea(data bytea, psw text [, options text ]) returns bytea  
  
  
  
postgres=# show bytea_output ;  
 bytea_output   
--------------  
 hex  
(1 row)  

3、如何解密bytea内容

pgp_sym_decrypt_bytea(msg bytea, psw text [, options text ]) returns bytea  

4、如何将bytea导出为文件

借助大对象接口

DO language plpgsql $$   
DECLARE     
   l_lob_id OID;  
   r record;   
BEGIN  
  for r in  
    select data, filename from bytea_table  
   LOOP  
    l_lob_id:=lo_from_bytea(0,r.data);  
    PERFORM lo_export(l_lob_id, '/home/...'||r.filename);  
    PERFORM lo_unlink(l_lob_id);     
    END LOOP;  
  
END;   
$$;  

例子

1、写一个测试文件

echo "PolarDB X and PostgreSQL 数据库其乐无穷" > ~/1.txt  

2、创建加密插件

create extension pgcrypto;  

3、创建测试表, 存储文件导入并加密后的bytea

create table test (id int, file_encrypt bytea);  
  
insert into test values (1, pgp_sym_encrypt_bytea(pg_read_binary_file('/Users/digoal/1.txt'), 'z...j'));  
postgres=# \x  
Expanded display is on.  
postgres=# select * from test;  
-[ RECORD 1 ]+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  
id           | 1  
file_encrypt | \xc30d0407030210f2661fffc6862b78d260019b8df8eb439cf28ea4325af03f0a9607e86e1db073eec17036f9a3aeb34f920c9199479c33cfda90f20717ed658d73455e4ac9d4001d918781ad8550c2126a55fe564b9248fd0be41b16f1a6006e2177b26ed5ac30ff360ac05614cb43b8ff  

4、将bytea解密并导出到文件

DO language plpgsql $$   
DECLARE     
   l_lob_id OID;  
BEGIN  
  SELECT lo_from_bytea(0, pgp_sym_decrypt_bytea(file_encrypt, 'z...j')) into l_lob_id FROM test where id=1;  
  PERFORM lo_export(l_lob_id, '/Users/digoal/1.txt.from.pg');  
  PERFORM lo_unlink(l_lob_id);     
END;   
$$;  

5、你也可以把加密后的bytea存储到文件中, 可以从这个文件恢复原始内容

copy (select file_encrypt from test) to '/Users/digoal/1.csv';  -- 加密后的bytea导出到csv文件  
  
create table test_import (file_encrypt bytea);  -- 导入加密后的bytea  
  
copy test_import from '/Users/digoal/1.csv';    
  
DO language plpgsql $$   -- 解密并导出为原始文件  
DECLARE     
   l_lob_id OID;  
BEGIN  
  SELECT lo_from_bytea(0, pgp_sym_decrypt_bytea(file_encrypt, 'z...j')) into l_lob_id FROM test_import;    
  PERFORM lo_export(l_lob_id, '/Users/digoal/1.txt.from.pg');  
  PERFORM lo_unlink(l_lob_id);     
END;   
$$;  

6、比对文件内容和md5, 完全一致

IT-C02YW2EFLVDL:~ digoal$ cat 1.txt.from.pg   
PolarDB X and PostgreSQL 数据库其乐无穷  
  
IT-C02YW2EFLVDL:~ digoal$ cat 1.txt  
PolarDB X and PostgreSQL 数据库其乐无穷  
  
IT-C02YW2EFLVDL:~ digoal$ md5 1.txt  
MD5 (1.txt) = cab5daf2095974f3aaf63c139e186848  
  
IT-C02YW2EFLVDL:~ digoal$ md5 1.txt.from.pg   
MD5 (1.txt.from.pg) = cab5daf2095974f3aaf63c139e186848  

参考

《大对象 - Use PostgreSQL server program import binary data into database bytea type》

《PostgreSQL 大对象或bytea存取pdf,jpg等文件 - PostgreSQL export regular file like pdf, word, text, doc stored in bytea type》

《PostgreSQL 大对象使用》

https://www.postgresql.org/docs/current/lo-funcs.html

https://www.postgresql.org/docs/current/functions-admin.html

https://www.postgresql.org/docs/current/pgcrypto.html

https://dba.stackexchange.com/questions/1742/how-to-insert-file-data-into-a-postgresql-bytea-column

digoal's wechat