it-swarm-tr.com

HMAC - Şifre saklama için neden HMAC olmasın?

Not: Şifre depolamayı güvence altına almak için iyi cevap ya scrypt veya bcrypt . Bu soru gerçek yazılımda uygulama için değil, kendi anlayışım için.

Joe Programmer'ın son kullanıcı şifrelerini bir web uygulaması için bir veritabanında güvenli bir şekilde saklamakla görevlendirildiğini varsayalım; veya bir yazılımda oturum açmak için şifreleri diskte saklamak. Büyük olasılıkla:

  1. Son kullanıcıdan $password Edinin.
  2. Yaklaşık 64 veya 128 bit büyüklüğünde rastgele bir değer olarak $nonce Oluşturun.
  3. $hash = SHA256($nonce$password) oluşturun ve $nonce İle birlikte $hash Veritabanında saklayın.

Birinci soru:

Aşağıdakiler neden yukarıdakilerden önemli ölçüde daha iyi değil?

  1. Bir kez ve sadece bir kez $long_string Oluşturun. Bunu uygulama kodunda sabit olarak saklayın. $long_string F.x olabilir. 2 kilobayt rastgele karakter olabilir.
  2. Son kullanıcıdan $password Edinin.
  3. $mac = HMAC-SHA256($long_string)[$password] oluşturun (yani son kullanıcı şifresini anahtar olarak kullanarak bir MAC oluşturun) ve bu $mac Dosyasını veritabanında saklayın.

HMAC'nin aşağıdaki faydaları olduğunu düşünürdüm?

  • Çarpışmalar daha az mı oluyor?
  • Bu hesaplama, sade karma işleminden biraz daha mı pahalı? (Tabii ki scrypt yakınında hiçbir yerde değil.)
  • Makul bir süre içinde bir kaba kuvvet saldırısı ile başarılı olmak için ve saldırganın iki şeye erişmesi gerekir: 1)$mac Depolanan veritabanı, ve 2) orijinal $long_string 'un saklandığı uygulama kodu. Bu, saldırganın veritabanına yalnızca erişmesi gereken bir karma işlevden daha iyi mi?

Ama yine de, kimse bir HMAC kullanmayı önermiyor gibi görünüyor, bu yüzden bir şeyi yanlış anlamam gerekir mi?

İkinci soru:

Tuz değeri eklemenin sonuçları $nonce Ne olurdu?

  1. Bir kez ve sadece bir kez $long_string Oluşturun. Bunu uygulama kodunda sabit olarak saklayın.
  2. Son kullanıcıdan $password Edinin.
  3. 128 bit büyüklüğünde rastgele bir değer olarak $nonce Oluşturun.
  4. $mac = HMAC-SHA256($long_string)[$nonce$password] oluşturun ve veritabanında $nonce Ve $mac Depolayın.
46
Jesper M

Tuzun amacı saldırı maliyeti paylaşımını önlemektir: bir saldırgan iki parola saldırmak istiyorsa, bir parolaya saldırmaktan iki kat daha pahalı olmalıdır.

Teklifinizle ("soru 1"), aynı şifreye sahip iki kullanıcı aynı MAC'yi kullanır. Bir saldırgan veritabanınıza okuma erişimine sahipse, şifreleri "deneyebilir" (MAC'i yeniden hesaplayarak) ve veritabanını eşleşme için arayabilir. Daha sonra parolalara saldırmanın bedeli olarak tümü şifreleri paralel olarak saldırabilir. Eğer senin long_string, uygulama kaynak kodunda sabit kodlanmış bir sabittir, daha sonra uygulamanın yüklü tüm örnekleri bu sabiti paylaşır ve "a" olarak da bilinen büyük bir parola-MAC çifti sözlüğünü önceden hesaplamaya değer (saldırgan için) "Gökkuşağı tablosu".

Bir nonce ("soru 2") ile maliyet paylaşımından kaçınırsınız. Nonce genellikle "tuz" olarak bilinir. Sizin long_string. Bir tuz kullanmak çok iyi bir fikirdir (iyi, değil bir tuz kullanmak en azından çok kötü bir fikirdir) ama işin sadece yarısını yapar. Ayrıca yavaş karma işlemine sahip olmalısınız. Buradaki nokta, tuzun maliyet paylaşımını önlediği, ancak tek bir parolaya saldırmayı önlemediği. Bir parola saldırmak, bir eşleşme olana kadar olası parolaların denenmesi anlamına gelir (bu "sözlük saldırısı" dır) ve ortalama bir insan kullanıcısının hayal gücü göz önüne alındığında, sözlük saldırıları işe yarar: insanlar sadece love tahmin edilmek. Çözüm, genellikle karma işlevini birkaç bin kez yineleyerek, doğal olarak yavaş olan bir karma işlemi kullanmaktır. Fikir parola doğrulamasını daha pahalı hale getirmektir: kullanıcının 1µs yerine 1ms beklemesi zor değildir (kullanıcı bunu fark etmez), ancak sözlük saldırısını 1000 kat daha pahalı hale getirir. Sizin long_stringmayıs çok uzun olması koşuluyla bunun için kullanılabilir (2 kilobayt değil, 20 megabayt).

HMAC may şifre doğrulama sistemini güçlendirmek için farklı bir kurulumda ham karma işlevi yerine kullanılabilir. Şifreleri tuzlarla ve yinelenen karma işlevleriyle kontrol eden bir sistem göz önüne alındığında, karma işlevini K kullanarak HMAC ile değiştirebilirsiniz. Bu, K gizli tutabildiğiniz sürece çevrimdışı sözlük saldırılarını önler. Bir değeri gizli tutmak kolay değildir, ancak 128-bit K sırrını tam bir veritabanından tutmak daha kolaydır.

35
Thomas Pornin

HMAC sizi burada çok fazla satın almıyor olsa da sanırım değiştirilebilir bir hash fonksiyonu olarak işlev görüyor (anahtarı değiştirerek değiştirilebilir). Her neyse, burada aşırıya kaçmış gibi görünüyor.

Bununla birlikte, eğer $ long_string bir saldırgan tarafından bilinirse, yukarıda önerdiğiniz ilk şema felaketle başarısız olur, bu muhtemelen kod muhtemelen gizli olarak kabul edilmez (ve yine de kodun gizliliğine güvenmek zayıf bir uygulamadır).

Önceden hesaplanmış saldırılara karşı korunmak için $ nonce gerektiğinden, ikinci şemayı kullanmalısınız.

3
frankodwyer