\df *crypt
ใน psql เปิดเผยประเภทอาร์กิวเมนต์ของ pgcrypto encrypt
และdecrypt
ฟังก์ชั่น ( เช่นเดียวกับ PgCrypto docs ):
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
...
เพื่อให้ทั้งสองencrypt
และฟังก์ชั่นที่สำคัญคาดว่าจะเป็นdecrypt
bytea
ตามข้อความแสดงข้อผิดพลาด "คุณอาจต้องเพิ่ม casts ประเภทชัดเจน"
อย่างไรก็ตามมันใช้งานได้ดีที่ Pg 9.1 ดังนั้นฉันสงสัยว่ามันมีอะไรมากกว่าที่คุณแสดง บางทีคุณอาจมีฟังก์ชั่นอื่นที่มีชื่อencrypt
ด้วยสามข้อโต้แย้ง?
นี่คือวิธีการทำงานบน Pg ที่สะอาด 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! ความเสี่ยงจากการสัมผัสคีย์ต้องมีการเตือนผู้ดูแลระบบอย่างมาก!
BTW โปรดคิดอย่างรอบคอบว่า PgCrypto เป็นตัวเลือกที่เหมาะสมหรือไม่ สามารถเปิดเผยคีย์ในข้อความค้นหาของคุณpg_stat_activity
และระบบจะบันทึกผ่านlog_statement
หรือผ่านคำสั่ง crypto ที่ล้มเหลวด้วยข้อผิดพลาด IMO เป็นการดีกว่าที่จะทำ crypto ในแอปพลิเคชั่น
ร่วมเป็นสักขีพยานในเซสชั่นนี้ด้วยการclient_min_messages
เปิดใช้งานเพื่อให้คุณสามารถเห็นสิ่งที่จะปรากฏในบันทึก:
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)
อ๊ะกุญแจอาจถูกเปิดเผยในบันทึกถ้าlog_min_messages
ต่ำพอ ขณะนี้อยู่ในที่เก็บข้อมูลของเซิร์ฟเวอร์พร้อมกับข้อมูลที่เข้ารหัส ล้มเหลว. ปัญหาเดียวกันโดยไม่มีlog_statement
ข้อผิดพลาดเกิดขึ้นเพื่อให้คำสั่งเข้าสู่ระบบหรืออาจauto_explain
จะเปิดใช้งานถ้า
การเปิดรับผ่านpg_stat_activity
ยังเป็นไปได้ .. เปิดสองเซสชันและ:
- 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();
อ๊ะ! มีคีย์ไปอีกครั้ง มันสามารถทำซ้ำได้โดยไม่ต้องLOCK TABLE
มีผู้โจมตีที่ไม่มีสิทธิมาก่อนมันยากที่จะทำในเวลาที่เหมาะสม การโจมตีผ่านpg_stat_activity
สามารถหลีกเลี่ยงได้โดยเพิกถอนการเข้าถึงpg_stat_activity
จากpublic
แต่เพียงไปเพื่อแสดงให้เห็นว่าการส่งคีย์ของคุณไปยังฐานข้อมูลนั้นอาจไม่เป็นการดีที่สุดเว้นแต่คุณจะรู้ว่าแอปของคุณเป็นสิ่งเดียวที่เข้าถึงได้ ถึงอย่างนั้นฉันก็ไม่ชอบ
หากเป็นรหัสผ่านคุณควรเก็บไว้หรือไม่
นอกจากนี้หากคุณกำลังเก็บรหัสผ่านอย่าเข้ารหัสสองทาง ถ้าเป็นไปได้รหัสผ่านเกลือแล้วสับพวกเขาและเก็บผล โดยปกติแล้วคุณไม่จำเป็นต้องกู้คืนรหัสผ่านของข้อความแทนรหัสผ่านเพียงยืนยันว่าแฮชที่จัดเก็บตรงกับรหัสผ่านที่ผู้ใช้ส่งคุณเข้าสู่ระบบเมื่อแฮชด้วยเกลือเดียวกัน
ถ้าเป็น auth ให้คนอื่นทำเพื่อคุณ
ยิ่งกว่านั้นอย่าเก็บรหัสผ่านเลยรับรองความถูกต้องกับ LDAP, SASL, Active Directory, ผู้ให้บริการ OAuth หรือ OpenID หรือระบบภายนอกอื่น ๆ ที่ออกแบบและใช้งานอยู่
ทรัพยากร
และอีกมากมาย