\df *crypttrong psql tiết lộ các loại đối số của pgcrypto encryptvà các decrypthàm ( cũng như các tài liệu PGCrypto ):
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+-----------------+------------------+--------------------------+--------
...
public | decrypt | bytea | bytea, bytea, text | normal
public | encrypt | bytea | bytea, bytea, text | normal
...
vì vậy cả hàm encryptvà decrypthàm đều mong muốn khóa được bytea. Theo thông báo lỗi, "bạn có thể cần thêm các kiểu phôi rõ ràng".
Tuy nhiên, nó hoạt động tốt ở đây trên trang 9.1, vì vậy tôi nghi ngờ có nhiều thứ hơn nó đã hiển thị. Có lẽ bạn có một chức năng khác cũng được đặt tên encryptvới ba đối số?
Đây là cách nó hoạt động trên một bản sạch 9.1:
regress=# create table demo(pw bytea);
CREATE TABLE
regress=# insert into demo(pw) values ( encrypt( 'data', 'key', 'aes') );
INSERT 0 1
regress=# select decrypt(pw, 'key', 'aes') FROM demo;
decrypt
------------
\x64617461
(1 row)
regress=# select convert_from(decrypt(pw, 'key', 'aes'), 'utf-8') FROM demo;
convert_from
--------------
data
(1 row)
Awooga! Awooga! Rủi ro tiếp xúc chính, cần hết sức thận trọng của quản trị viên!
BTW, xin vui lòng suy nghĩ cẩn thận về việc liệu PGCrypto có thực sự là lựa chọn đúng đắn hay không. Các khóa trong truy vấn của bạn có thể được tiết lộ pg_stat_activityvà hệ thống đăng nhập thông qua log_statementhoặc thông qua các câu lệnh về tiền điện tử không có lỗi. IMO thường xuyên tốt hơn để làm tiền điện tử trong ứng dụng .
Chứng kiến phiên này, với client_min_messagestính năng được bật để bạn có thể thấy những gì sẽ xuất hiện trong nhật ký:
regress# SET client_min_messages = 'DEBUG'; SET log_statement = 'all';
regress=# select decrypt(pw, 'key', 'aes') from demo;
LOG: statement: select decrypt(pw, 'key', 'aes') from demo;
LOG: duration: 0.710 ms
decrypt
------------
\x64617461
(1 row)
Rất tiếc, khóa có thể bị lộ trong nhật ký nếu log_min_messagesđủ thấp. Giờ đây nó đã được lưu trữ trên máy chủ, cùng với dữ liệu được mã hóa. Thất bại. Vấn đề tương tự mà không log_statementcó lỗi xảy ra để làm cho câu lệnh được ghi lại, hoặc có thể nếu auto_explainđược bật.
Tiếp xúc qua pg_stat_activitycũng có thể .. Mở hai phiên và:
- S1:
BEGIN;
- S1:
LOCK TABLE demo;
- S2:
select decrypt(pw, 'key', 'aes') from demo;
- S1:
select * from pg_stat_activity where current_query ILIKE '%decrypt%' AND procpid <> pg_backend_pid();
Rất tiếc! Lại có chìa khóa. Nó có thể được sao chép mà không LOCK TABLEcó kẻ tấn công không có đặc quyền, nó chỉ khó hơn để đúng lúc. Có pg_stat_activitythể tránh được cuộc tấn công thông qua bằng cách thu hồi quyền truy cập pg_stat_activitytừ public, nhưng nó chỉ cho thấy rằng có thể không tốt nhất để gửi khóa của bạn đến DB trừ khi bạn biết ứng dụng của mình là thứ duy nhất từng truy cập. Ngay cả sau đó, tôi không thích.
Nếu đó là mật khẩu, bạn có nên lưu trữ chúng không?
Hơn nữa, nếu bạn đang lưu trữ mật khẩu, đừng mã hóa hai chiều; nếu có thể có mật khẩu muối thì hãy băm chúng và lưu trữ kết quả . Bạn thường không cần phải có khả năng khôi phục mật khẩu Cleartext, chỉ xác nhận rằng hàm băm được lưu trữ khớp với mật khẩu mà người dùng gửi cho bạn để đăng nhập khi nó được băm với cùng một loại muối.
Nếu đó là auth, hãy để người khác làm điều đó cho bạn
Thậm chí tốt hơn, đừng lưu trữ mật khẩu, xác thực với LDAP, SASL, Active Directory, nhà cung cấp OAuth hoặc OpenID hoặc một số hệ thống bên ngoài khác đã được thiết kế và hoạt động.
Tài nguyên
và nhiều hơn nữa.