PostgreSQL에서 AES 암호화를 사용하는 방법은 무엇입니까?


15

다음 문장을 사용하여 aes-encryption을 시도했습니다.

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

어느 것이 효과가 있었지만 값을 해독 할 수 없습니다. bytea 데이터 유형의 필드에 삽입 했지만 올바른 방법인지 확실하지 않습니다.

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

나에게 오류를 준다

오류 : decrypt (bytea, unknown, unknown) 함수가 없습니다.
LINE 1 : SELECT decrypt (pw, 'key', 'aes') FROM tabelle WHERE ID = 7; ^
힌트 : 주어진 이름 및 인수 유형과 일치하는 함수가 없습니다. 명시 적 유형 캐스트를 추가해야 할 수도 있습니다.

이것이 실제로 encrypt ()가 기존 함수이지만 decrypt ()가 아님을 의미합니까? AES 암호화 된 값을 어떻게 검색 할 수 있습니까?

답변:


16

\df *cryptpsql에서 pgcrypto encryptdecrypt함수 의 인수 유형을 나타냅니다 ( 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
 ...

따라서 encryptdecrypt함수 모두 키가 될 것으로 예상합니다 bytea. 오류 메시지에 따라 "명시 적 유형 캐스트를 추가해야 할 수도 있습니다".

그러나 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)

아우가! 아우가! 주요 노출 위험, 극도의 관리자주의가 필요합니다!

BTW, PgCrypto가 실제로 올바른 선택인지 신중하게 생각하십시오. 쿼리의 키가 공개 될 수 있으며 pg_stat_activity시스템 log_statement은 오류와 함께 실패한 암호문을 통해 또는 로그를 통해 기록됩니다 . IMO 종종 응용 프로그램에서 암호화를 수행하는 것이 좋습니다 .

이 세션을 감시하고 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권한이없는 공격자가 없이 복제 할 수 있으며 , 정확한 시간을 맞추기가 더 어렵습니다. from에 pg_stat_activity대한 액세스를 취소 하여 공격을 피할 수 있지만 앱이 액세스하는 유일한 방법을 알지 못하면 키를 DB에 보내는 것이 가장 좋지 않을 수도 있습니다. 그럼에도 불구하고, 나는 싫어한다.pg_stat_activitypublic

비밀번호 인 경우 전혀 저장해야합니까?

또한 비밀번호를 저장하는 경우 양방향 암호화하지 마십시오. 모든 가능한 소금 암호라면 해시하고 결과를 저장하십시오 . 일반적으로 비밀번호 일반 텍스트를 복구 할 필요는 없으며 저장된 해시가 사용자가 동일한 소금으로 해시 할 때 사용자가 보낸 비밀번호와 일치하는지 확인하십시오.

인증 된 경우 다른 사람이 대신 해 줄 수 있습니다.

또한 암호를 전혀 저장하지 말고 LDAP, SASL, Active Directory, OAuth 또는 OpenID 공급자 또는 이미 설계되어 작동하는 다른 외부 시스템에 대해 인증하지 마십시오.

자원

그리고 더 많은.


그것은 보여지는 것 이상이 아니며 새로운 기능, 새로운 설치된 postgresql을 정의하지 않았습니다. 샘플과 내가 게시 한 첫 번째 select-statement도 작동하지 않아 위에 게시 된 것과 동일한 오류가 반환되는 것은 매우 자극적입니다. 어딘가에 뭔가 잘못되었습니다 ... 어쨌든 귀하의 답변에 감사드립니다.
32bitfloat

에서 새로 CREATEd 데이터베이스를 사용해보십시오 template0. 예 CREATE DATABASE testdb TEMPLATE template0를 들어 CREATE EXTENSION pgcrypto;테스트하십시오. template1에 이상한 점이 있는지 확인하십시오.
Craig Ringer

db의 양방향 암호 해독에 관한 참고 사항입니다. 나는 그것이 항상 잘못된 방향이라고 생각하지는 않지만 복잡성을 더하고이를 다루는 곳마다 db에서 더 복잡한 키 관리를 다루어야합니다.
Chris Travers

또한 암호를 해독 할 필요가 없으며 더 많은 사람들이 유지 관리하는 시스템에 연결하는 것이 일반적으로 보안 측면에서 중요한 승리라는 개념도 100 % 초입니다.
Chris Travers

3
lol, "Awooga! Awooga!"+1
Jeromy French
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.