Şifrelenmiş alanlarla MySQL veritabanında arama yapma


15

Bir MySQL veritabanının belirli tablo alanlarını şifrelemem gerektiğini varsayalım . Ayrıca, şifrelediğim bu alanlardan bazılarını aramam gerekiyor.

Zaten bu alanlarda nasıl arama yapılır?

Her kaydın adım adım şifresini çözmek bir seçenek değildir: Varsayalım binlerce kayıttan birden fazlasına sahibim. Her kaydın şifresini çözmek ve her kaydın aramayla eşleşip eşleşmediğini kontrol etmek çok fazla zaman ve yer gerektirir.

GÜNCELLEME 2012-09-07

Yeni bir uygulama uygulamak üzereyken veritabanı şemasına daha fazla ayrıntı eklemek sorun olmaz . Ayrıca, şu anda üretimde çalışan uygulamaları genişletmem gerekiyor. Ancak bu uygulama için bile, daha fazla ayrıntı eklemek sorun olmaz.

GÜNCELLEME 2012-09-08

Şifreleme bu sorunun çekirdeğidir.

Bazı yanıtların önerdiği gibi erişim kısıtlamaları zaten geçerlidir - ancak verileri şifrelemek için resmi gereksinime uymamaktadır.

Bu resmi şartı değil Ödeme Kartı Endüstrisi Veri Güvenliği Standardı [PCI].

Yanıtlar:


11

Açıkça görülmesi amaçlanmamıştır, bu nedenle onları aramak sorunlu olacaktır.

Geçmişte kullandığım bir hile, şifrelenmiş verileri şifrelemeden önce karmayı ve karmayı dizine alınmış bir sütunda depolamaktır. Tabii ki, bu sadece tüm değer üzerinde arama yapıyorsanız çalışır; kısmi değerler aynı karmaya sahip olmayacaktır.

Gerekirse, büyük olasılıkla "tam metin" karma indeksi oluşturarak bunu genişletebilirsiniz, ancak çok hızlı bir şekilde karmaşık hale gelebilir.

EK

Sohbette, sözlük saldırılarına karşı güvenlik açığıyla ilgili oldukça uzun bir tartışma başına cevabıma bir dipnot eklemem önerildi, bu nedenle bu potansiyel güvenlik riskini yukarıdaki yaklaşıma tartışacağım.

Sözlük Saldırısı: Sözlük saldırısı, bir kişinin bilinen değerlerin bir listesini önceden karması ve karmaları veritabanındaki karma sütununla karşılaştırmasıdır. Bir eşleşme bulabilirlerse, bilinen değerin aslında karma olan değer olması muhtemeldir (Yine de kesin değildir, çünkü karmaların benzersiz olduğu garanti edilmez). Bu genellikle, değerin eklenmiş veya eklenmiş rastgele bir "tuz" ile hash edilmesiyle hafifletilir, böylece karma sözlükle eşleşmez, ancak yukarıdaki cevap aranabilirliği kaybettiğiniz için bir tuz kullanamaz.

Bu saldırı, parolalar gibi şeylerle uğraşırken tehlikelidir: popüler parola karmalarının sözlüğünü oluşturursanız, tabloyu bu karma değeri için hızlı bir şekilde arayabilir ve böyle bir parolaya sahip bir kullanıcıyı tanımlayabilir ve kullanıcının kimliğini çalmak için kimlik bilgilerini etkili bir şekilde çıkarabilirsiniz. .

SSN'ler, kredi kartı numaraları, GUID'ler vb.Gibi yüksek derecede kardinalliğe sahip öğeler için daha az tehlikelidir (ancak bunları saklamakla ilişkili farklı riskler [read: legal] vardır, bu yüzden bunları saklama konusunda tavsiyede bulunmam ).

Bunun nedeni, bir sözlük saldırısının çalışması için, olası değerler ve bunların karmalarını önceden oluşturmuş olmanız gerekir. Teorik olarak, tüm olası SSN'lerin bir sözlüğünü oluşturabilirsiniz (bir milyar satır, tüm biçimlendirme permütasyonlarının kaldırıldığı varsayılarak; kredi kartları için onlarca trilyonlarca giriş) ... ancak bu genellikle bir sözlük saldırısının noktası değildir ve temelde her değeri sistematik olarak araştırdığınız kaba kuvvet saldırısıyla karşılaştırılabilir hale gelir.

Ayrıca bakmak olabilir belirli bir kişiye bir SSN maç için çalışıyorsanız, SSN veya kredi kartı numarası. Yine, genellikle bir sözlük saldırısının amacı değil, ancak yapılması mümkündür, bu yüzden bu kaçınmanız gereken bir riskse, cevabım sizin için iyi bir çözüm değildir.

İşte burada. Tüm şifrelenmiş verilerde olduğu gibi, genellikle bir nedenden dolayı şifrelenir, bu nedenle verilerinizin ve verilerinizi korumaya çalıştığınızın farkında olun.


Bu cevapla ilgili tartışma sohbete taşındı .
Paul White 9

5

CryptDB'ye bir göz atmak isteyebilirsiniz . Şifrelenmiş verilerin şeffaf bir şekilde depolanmasını ve sorgulanmasını sağlayan MySQL ve PostgreSQL için bir ön uçtur. Uygulama ve veritabanı arasında geçerken verileri şifreleyerek ve şifresini çözerek, şifrelenmiş veriler üzerinde çalışmak üzere sorguları yeniden yazarak çalışır. ve her sütunun şifreleme modunu, uygulamanın kullandığı sorgular için yalnızca gerektiği kadar bilgi gösterecek şekilde dinamik olarak ayarlayarak.

CryptDB tarafından kullanılan çeşitli şifreleme yöntemleri şunları içerir:

  • RND , veriler hakkında hiçbir bilgi sızdırmayan (varlığı ve değişken uzunluklu türler için uzunluk hariç) tamamen IND-CPA güvenli şifreleme şemasıdır, ancak yalnızca depolama ve geri çağırma işlemine izin vermez.

  • DET , belirleyici olan bir RND varyantıdır, böylece iki özdeş değer (aynı sütunda) aynı şifreleme metnine şifrelenir. Formun eşitlik sorgularını destekler WHERE column = 'constant'.

  • OPE , gibi bir sipariş koruma şifreleme düzeni gibi eşitsizlik sorguları destekler WHERE column > 'constant'.

  • HOM , kısmen homomorfik şifreleme şeması (Paillier), şifrelenmiş değerleri bir araya getirerek şifrelenmiş değerlerin birlikte eklenmesine izin verir. SUM()Sorguları, toplama ve artırmayı destekler .

  • SEARCH , formun anahtar kelime aramalarını destekleyen bir şema WHERE column LIKE '% word %'.

  • JOIN ve OPE-JOIN , farklı sütunlardaki değerlerin birbiriyle karşılaştırılmasına izin veren DET ve OPE varyantları. Eşitliği ve aralık birleşimlerini destekleyin.

CryptDB'nin gerçek gücü, her bir sütunun şifreleme yöntemini gördüğü sorgulara dinamik olarak uyarlamasıdır, böylece daha yavaş ve / veya daha az güvenli şemalar yalnızca bunları gerektiren sütunlar için kullanılır. Şifreleme anahtarlarını kullanıcı parolalarına zincirleme gibi çeşitli diğer kullanışlı özellikler de vardır.

İlgileniyorsanız, CryptDB web sitesinden, özellikle Popa, Redfield, Zeldovich ve Balakrishnan'ın “CryptDB: Şifreli Sorgu İşlemeyle Gizliliğin Korunması” başlıklı makalelere bakmanız önerilir ( SOSP 2011 ). Bu belgeler ayrıca, farklı sorgu türlerini desteklemeye ilişkin çeşitli güvenlik ve performans ödünleşmelerini daha ayrıntılı olarak açıklamaktadır.


1
It works by encrypting and decrypting data as it passes between the application and the database: Şüphesiz bu, aranan veriler zaten veritabanındaysa (şifreli), ancak açıkçası veritabanını arayan sorgunun yalnızca CryptDB'ye (ve sonra şifreli?) Aktarılması durumunda sorunlara neden olabilir . Bu yöntemin nasıl verimli olabileceğini anlayamıyorum?
Martin

3

Mevcut cevapların neden gereksinimleri tam olarak sorgulamadığını anlamıyorum, bu yüzden soracağım ve cevap olarak bırakacağım.

İş nedenleri nelerdir? Hangi verileri şifrelemeniz gerekiyor ve neden? PCI uyumluluğunu arıyorsanız, bir deneme yazabilirim.

İhtiyacınız hakkında sorular:

  • Sonuç olarak var olan / olmayan varlıkları mı yoksa gerçek verileri mi döndürmeniz gerekiyor?
  • LIKE '% OMG_SEKRIT%' yeteneğine mi ihtiyacınız var?
  • Verileri kim göremiyor ve neden?

RDBMS güvenliği normalde kullanıcı / rol tarafından uygulanan izinler temelinde yapılır. Veriler normalde diskteki RDBMS tarafından şifrelenir, ancak sütunlu verilerin içinde şifrelenmez, çünkü bu, verileri verimli bir şekilde depolamak ve almak için tasarlanmış bir uygulama için gerçekten bir anlam ifade etmez.

Kullanıcı / rol / api ile kısıtla. Diskte şifrele. Daha önemli verileri saklıyorsanız neden MySQL kullandığınızı bilmek isterim.


Öncelikle, var / var değil bulup sonra belirli bir kaydı bulmalıyım. Tam LIKE desteği iyi olur. Ama merak ediyorum, kelimelerin eşleştirilmesinden başka bir şey mümkün olacak. Yetkili kullanıcının verileri görmesine izin verilir. Uygulama bu öğelerin şifresini çözer, meşru bir kullanıcının görme hakları vardır. İzin tabanı şemaları bir seçenek değildir.
SteAp

"Daha önemli veriler" için ölçütler nelerdir?
arcanine

2

Bunu inceliyorum ve sorunuzla karşılaştım. "Şifrelenmiş Verileri Aramada Pratik Teknikler" başlıklı makalenin 5.4 bölümünde belirtilen yaklaşıma yöneliyorum. Http://www.cs.berkeley.edu/~dawnsong/papers/se.pdf

Temel öz, şifrelenmiş arama belgesinde bulunan şifreli anahtar kelimeleri içeren bir dizin oluşturmaktır. İşin püf noktası, belgede (veya veritabanında) bu anahtar kelimelerin bulunduğu konumları da şifrelemektir.


1

Programlı olarak verimli bir çözüm

  1. SADECE kayıt kimliği ile aradığınız alanın TÜM kayıtlarını alın
  2. bunları geçici bir tabloya deşifre edin
  3. bu tabloya göre arama yapın
  4. arama ölçütleriyle eşleşen tüm kayıtları (tüm alanlar) almak için kimliği kullanın
  5. bunların şifresini çözme ve kullanıcıya geri gönderme

Mesele şu ki, 1 ve 4 başlangıçta tüm kayıtların tüm alanlarını almak ve şifresini çözmek yerine önemli ölçüde daha küçük veri setleri.

Umarım yardımcı olur.


Düz metindeki geçici tabloların nispeten (yani çok) tutulması ve okunması, sunucunun doğru anda kesilmesi veya sadece temp/klasörü ve patlamayı kopyalaması kolaydır , tüm sütun için düz metin değerleri vardır, bu güvenli bir çalışma yöntemi değildir
Martin

1

Bu, MYSQL'in dahili şifreleme işlevlerini kullanarak tam arama işlevselliğiyle mümkündür.

İşte bir örnek:

!!! MYSQL ENCODE () KULLANMAK BURADA BASİTLİK İÇİN, MYSQL_ENCODE ŞİMDİ KONUSUNDA GÜVENİLİR, KURULU DİĞER İÇ MYSQL FONKSİYONLARINDAN BİRİ KULLANIN !!!

UPDATE my_table
SET field=ENCODE('my_data', 'my_password')
WHERE ID=1;

SELECT DECODE(field, 'my_password') as field FROM my_table
WHERE field LIKE 'data';

Yukarıdaki yorumun önerdiği gibi, ENCODE () kullanmayın , basitliği nedeniyle bu örnekte yalnızca ENCODE kullandığım diğer şifreleme işlevlerinden birini kullanın

Bunu php gibi bir uygulama içinde yapıyorsanız, bunu, her tablonun şifrelenmiş sütunlarının bir listesini / dizisini ilgili ağ geçidi sınıfında depolayarak db ağ geçidinizde veya depo sınıflarınızda yapabilirsiniz.

class UserGateway
{
    protected $encrypted_fields = array(
        'username',
        'email'
    );

    public function get($fields, ...)
    {
        foreach ($fields as $k => $field) {
            if (in_array($field, $fields)) {
                $fields[$k] = $this->decodeSelect($field);
            }
        }

        $sql = 'SELECT '.implode(',', $fields);

        //......
    }

    protected function decodeSelect($field)
    {
        return "DECODE($field, $pass) AS $field";
    }
}

Tabii ki bu çok kaba ve güvensiz bir koddur ve önemli bir gelişme olmadan üretimde kullanılmamalıdır. Ancak genel fikri verme amacına hizmet etmelidir.


-1

SQL'de ve kısmi değil tam değere karşı arama yaptığınızı varsayarsak (ör. LIKE 'değeri%') ... arama verilerini yakalarken, verileri şifrelendiğinde kullanılan algoritmayı kullanarak bu verileri şifreleyin ve arayın.

Örneğin:

Ne olurdu:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'Value'

Bunun yerine şöyle görünebilir:

SELECT FieldA, FieldB 
FROM Table1 
WHERE FieldC = 'hsk&%67ghhks83'

1
Hayır. İyi şifreleme bir tuz değeriyle çalışacaktır, bu nedenle örneğin her bir satır için benzersiz bir tuzunuz varsa, o zaman her satır tuzunun arama dizesinde kullanılması gerekir, bu karmaşık ve pahalı, oldukça hızlı olacaktır
Martin
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.