PostgreSQL'de aes-şifreleme nasıl kullanılır?


15

Aes-şifrelemeyi aşağıdaki ifadeyi kullanarak denedim:

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

Bu işe yaradı, ama değerin şifresini çözemiyorum. Bir veri tipi bytea alanına ekledim ama bunun doğru yol olup olmadığından emin değilim.

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

bana hata veriyor

HATA: işlev şifresi (baytea, bilinmeyen, bilinmeyen) mevcut değil
LINE 1: SELECT şifre çözme (pw, 'anahtar', 'aes') tablodan WHERE ID = 7; ^
İPUCU: Verilen ad ve bağımsız değişken türleriyle eşleşen işlev yok. Açık tür yayınlar eklemeniz gerekebilir.

Bu gerçekten, encrypt () işlevinin var olduğu, ancak decrypt () işlevinin olmadığı anlamına mı geliyor? Aes ile şifrelenmiş değerleri başka nasıl alabilirim?

Yanıtlar:


16

\df *cryptpsql'de pgcrypto encryptve decryptişlevlerin bağımsız değişken türlerini ( PgCrypto belgeleri gibi ) gösterir:

                                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
 ...

böylece hem encryptve decryptişlevleri anahtarın olmasını bekler bytea. Hata iletisine göre, "açık tür yayınlar eklemeniz gerekebilir".

Ancak, burada Pg 9.1 üzerinde iyi çalışıyor, bu yüzden gösterdiğinizden daha fazlası olduğundan şüpheleniyorum. Belki de encryptüç argümanla adlandırılmış başka bir fonksiyonunuz var mı?

Temiz bir Pg 9.1 üzerinde nasıl çalıştığı aşağıda açıklanmıştır:

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! Başlıca maruz kalma riski, aşırı idari önlem gereklidir!

BTW, lütfen PgCrypto'nun gerçekten doğru seçim olup olmadığını dikkatlice düşünün. Sorgularınızdaki anahtarlar açığa çıkarılabilir pg_stat_activityve sistem log_statementbir hatayla başarısız olan kripto ifadeleriyle veya aracılığıyla oturum açar. IMO uygulamada kripto yapmak genellikle daha iyidir .

client_min_messagesGünlüklerde nelerin görüneceğini görebilmeniz için bu oturuma etkin olarak tanık olun:

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)

Hata! Eğer log_min_messagesyeterince düşük ise , muhtemelen günlüklerde açık anahtar . Şifrelenmiş verilerle birlikte sunucunun deposunda. Başarısız. İfadenin log_statementgünlüğe kaydedilmesine neden olacak bir hata oluşursa veya büyük olasılıkla auto_explainetkinleştirilirse aynı sorun olmaz .

Yoluyla maruz kalma pg_stat_activityda mümkündür .. İki oturum açın ve:

  • 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();

Tüh! Anahtar yine gidiyor. LOCK TABLEAyrıcalıklı olmayan bir saldırgan olmadan çoğaltılabilir , doğru zamanlamak daha zordur. Üzerinden gelen pg_stat_activityerişimi iptal ederek saldırı önlenebilir , ancak uygulamanızın erişen tek şey olduğunu bilmediğiniz sürece anahtarınızı DB'ye göndermenin en iyi yol olmayabileceğini gösterir. O zaman bile sevmem.pg_stat_activitypublic

Parolalarsa, bunları saklamanız gerekir mi?

Ayrıca, şifreleri saklıyorsanız, bunları iki yönlü şifrelemeyin; tuz şifreleri mümkün olduğunda bunları kesin ve sonucu saklayın . Genellikle parola açık metnini kurtaramazsınız, yalnızca depolanan karmanın, kullanıcının aynı tuzla karıklandığında oturum açmanız için gönderdiği şifreyle eşleştiğini onaylayın.

Eğer doğruysa, başkasının sizin için yapmasına izin verin

Daha da iyisi, şifreyi hiç saklamayın, LDAP, SASL, Active Directory, bir OAuth veya OpenID sağlayıcısına veya önceden tasarlanmış ve çalışan başka bir harici sistemde kimlik doğrulaması yapmayın.

kaynaklar

ve daha fazlası.


Gösterdiğimden daha fazla değil ve yeni işlevler tanımlayamadım, yeni bir yüklü postgresql. Örneğinizin ve gönderdiğim ilk select deyiminin de bu arada çalışmaması oldukça üzücü, yukarıda yayınlananla aynı hatayı döndürüyor. Bir yerlerde bir şeyler ters gitti ... her neyse cevabın için teşekkürler.
32bitfloat

Den yeni bir CREATEd veritabanı deneyin template0; örneğin CREATE DATABASE testdb TEMPLATE template0sonra CREATE EXTENSION pgcrypto;test edin. Şablon1'de tehlikeli bir şey olup olmadığına bakın.
Craig Ringer

Sadece db iki yönlü şifre çözme ile ilgili bir not. Her zaman yanlış yön olduğunu düşünmüyorum, ancak karmaşıklık ekliyor ve bununla uğraştığınız her yerde gerçekten db'de daha karmaşık olabilen anahtar yönetimi ile uğraşmanız gerekiyor.
Chris Travers

Ayrıca% 100 saniye ASLA parolaların şifresini çözmek zorunda kalmamanız ve daha fazla kişi tarafından korunan bir sisteme bağlanmak genellikle güvenlik açısından önemli bir kazançtır.
Chris Travers

3
lol, "Awooga! Awooga!" için +1
Jeromy Fransız
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.