จะใช้การเข้ารหัส aes ใน PostgreSQL ได้อย่างไร


15

ฉันลองเข้ารหัส aes โดยใช้ข้อความต่อไปนี้:

SELECT encrypt('test', 'key', 'aes');

ซึ่งใช้งานได้ แต่ฉันไม่สามารถถอดรหัสค่าได้ ฉันใส่มันลงในเขตข้อมูลชนิดข้อมูลไบต์แต่ฉันไม่แน่ใจว่าเป็นวิธีที่ถูกต้องหรือไม่

SELECT decrypt(pw, 'key', 'aes') FROM table WHERE ID = 1;

ทำให้ฉันมีข้อผิดพลาด

ข้อผิดพลาด: ถอดรหัสฟังก์ชัน (bytea, ไม่ทราบ, ไม่ทราบ) ไม่มีอยู่
บรรทัดที่ 1: เลือกตัวถอดรหัส (pw, 'key', 'aes') จาก tabelle WHERE ID = 7; ^
คำแนะนำ: ไม่มีฟังก์ชันที่ตรงกับชื่อและประเภทอาร์กิวเมนต์ที่กำหนด คุณอาจจำเป็นต้องเพิ่ม casts ประเภทชัดเจน

นั่นหมายความว่าการเข้ารหัส () เป็นฟังก์ชั่นที่มีอยู่ แต่ไม่ถอดรหัส () หรือไม่? ฉันสามารถกู้ค่า aes ที่เข้ารหัสได้อีกวิธี

คำตอบ:


16

\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 หรือระบบภายนอกอื่น ๆ ที่ออกแบบและใช้งานอยู่

ทรัพยากร

และอีกมากมาย


มันไม่ได้มากกว่าที่ฉันแสดงและฉันไม่ได้กำหนดฟังก์ชั่นใหม่มันเป็น postgresql ที่ติดตั้งใหม่ ค่อนข้างน่ารำคาญที่ตัวอย่างและคำสั่งเลือกคำแรกที่ฉันโพสต์ยังใช้งานไม่ได้ในขณะเดียวกันก็ส่งคืนข้อผิดพลาดเดียวกับที่โพสต์ด้านบน มีบางอย่างผิดพลาด ... ขอบคุณสำหรับคำตอบของคุณ
32bitfloat

ลองบนใหม่CREATEวันที่ฐานข้อมูลจากtemplate0; เช่นCREATE DATABASE testdb TEMPLATE template0จากนั้นCREATE EXTENSION pgcrypto;และทดสอบ ดูว่ามีบางอย่างที่หลบใน template1 หรือไม่
Craig Ringer

เพียงทราบเกี่ยวกับการถอดรหัสแบบสองทางในฐานข้อมูล ฉันไม่คิดว่ามันจะเป็นทิศทางที่ผิดเสมอไป แต่มันเพิ่มความซับซ้อนและที่ใดก็ตามที่คุณจัดการกับสิ่งนี้คุณต้องจัดการกับการจัดการคีย์ซึ่งซับซ้อนกว่าในฐานข้อมูล
Chris Travers

นอกจากนี้ 100% ความคิดที่สองที่คุณไม่ควรถอดรหัสรหัสผ่านและการเชื่อมต่อเข้าสู่ระบบที่ดูแลโดยผู้คนจำนวนมากมักเป็นเรื่องสำคัญที่จะชนะความปลอดภัย
Chris Travers

3
lol +1 สำหรับ "Awooga! Awooga!"
Jeromy French
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.