Buradaki sorun temelde bir entropi sorunudur. Öyleyse oraya bakmaya başlayalım:
Karakter Başına Entropi
Bayt başına entropi bit sayısı:
- Onaltılık Karakterler
- Bit sayısı: 4
- Değerler: 16
- 72 Karakterde Entropi: 288 bit
- Alfa Sayısal
- Bit Sayısı: 6
- Değerler: 62
- 72 Karakterde Entropi: 432 bit
- "Ortak" Semboller
- Bitler: 6.5
- Değerler: 94
- 72 Karakterde Entropi: 468 bit
- Tam Bayt
- Bitler: 8
- Değerler: 255
- 72 Karakterde Entropi: 576 bit
Öyleyse, nasıl davranacağımız, ne tür karakterler beklediğimize bağlıdır.
İlk Sorun
Kodunuzla ilgili ilk sorun, "biber" karma adımınızın onaltılık karakterler çıkarmasıdır (dördüncü parametrehash_hmac()
ayarlanmadığından).
Bu nedenle, biberinizi karıştırarak, şifrenin kullanabileceği maksimum entropiyi etkili bir şekilde 2 kat azaltıyorsunuz ( olası 576'dan 288'e bit) .
İkinci Problem
Ancak, ilk etapta sha256
yalnızca 256
entropi bitleri sağlar . Yani 576 biti 256 bit'e kadar etkili bir şekilde kesiyorsunuz. Karma adımınız * hemen *, tanımı gereği şifredeki olası entropinin en az % 50'sini kaybeder
.
SHA512
Mevcut entropiyi yalnızca yaklaşık% 12 azaltacağınız yere geçerek bunu kısmen çözebilirsiniz . Ancak bu yine de önemsiz olmayan bir fark. Bu% 12, permütasyon sayısını bir faktör kadar azaltır 1.8e19
. Bu büyük bir sayı ... Ve bu onu azalttığı faktör ...
Temel Sorun
Temel sorun, 72 karakterden uzun üç tür parola olmasıdır. Bu tarz sistemin onlar üzerindeki etkisi çok farklı olacaktır:
Not: Bundan sonra SHA512
, ham çıktıyla (hex değil) kullanan bir biber sistemiyle karşılaştırdığımızı varsayıyorum .
Yüksek entropili rastgele şifreler
Bunlar, parolalar için ne kadar büyük anahtarlar üreten parola oluşturucuları kullanan kullanıcılarınızdır. Rastgele (oluşturulmuş, insan tarafından seçilmemiş) ve karakter başına yüksek entropiye sahip. Bu türler yüksek bayt (karakterler> 127) ve bazı kontrol karakterleri kullanır.
Bu grup için, hashing fonksiyonunuz mevcut entropiyi önemli ölçüde azaltacaktır bcrypt
.
Tekrar söyleyeyim. Yüksek entropi, uzun parolalar kullanan kullanıcılar için çözümünüz , parolalarının gücünü ölçülebilir bir miktarda önemli ölçüde azaltır. (72 karakterlik bir parola için 62 bitlik kayıp ve daha uzun parolalar için daha fazlası)
Orta entropi rasgele şifreler
Bu grup, ortak semboller içeren şifreler kullanıyor, ancak yüksek bayt veya kontrol karakterleri kullanmıyor. Bunlar yazılabilir şifrelerinizdir.
Bu grup için, biraz daha fazla entropinin kilidini açacaksınız (onu yaratmayacak, ancak daha fazla entropinin bcrypt şifresine sığmasına izin vereceksiniz). Biraz dediğimde, biraz kast ediyorum. Başa dön, SHA512'nin sahip olduğu 512 biti maksimize ettiğinizde ortaya çıkar. Bu nedenle, zirve 78 karakterde.
Tekrar söyleyeyim. Bu sınıftaki parolalar için, entropi bitmeden önce yalnızca ek 6 karakter kaydedebilirsiniz.
Düşük entropili rastgele olmayan şifreler
Bu, muhtemelen rastgele oluşturulmayan alfa sayısal karakterleri kullanan gruptur. İncil'den alıntı falan gibi bir şey. Bu ifadeler karakter başına yaklaşık 2,3 bit entropiye sahiptir.
Bu grup için, karma oluşturma yoluyla daha fazla entropinin kilidini önemli ölçüde açabilirsiniz (onu oluşturmaz, ancak bcrypt şifre girişine daha fazla sığdırabilirsiniz). Başabaş, entropi bitmeden yaklaşık 223 karakterdir.
Tekrar söyleyelim. Bu sınıftaki parolalar için, ön hashing kesinlikle güvenliği önemli ölçüde artırır.
Gerçek Dünyaya Dönüş
Bu tür entropi hesaplamaları gerçek dünyada pek önemli değil. Önemli olan entropiyi tahmin etmektir. Saldırganların yapabileceklerini doğrudan etkileyen şey budur. En üst düzeye çıkarmak istediğiniz şey budur.
Entropiyi tahmin etmeye yönelik çok az araştırma olsa da, belirtmek istediğim bazı noktalar var.
Arka arkaya 72 doğru karakteri rastgele tahmin etme şansı son derece düşüktür. Powerball piyangosunu 21 kez kazanma olasılığınız, bu çarpışmaya sahip olmaktansa ... İşte bu kadar büyük bir sayıdan bahsediyoruz.
Ama istatistiksel olarak yanılmayabiliriz. Cümleler söz konusu olduğunda, ilk 72 karakterin aynı olma şansı, rastgele bir paroladan çok daha yüksektir. Ancak yine de önemsiz derecede düşük (karakter başına 2,3 bit temel alınarak Powerball piyangosunu 5 kez kazanma olasılığınız daha yüksektir).
Pratikte
Pratik olarak, gerçekten önemli değil. Birinin ilk 72 karakteri doğru tahmin etme şansı, sonrakilerin önemli bir fark yaratması o kadar düşük ki endişelenmeye değmez. Neden?
Peki, bir cümle aldığınızı varsayalım. Kişi ilk 72 karakteri doğru anlayabiliyorsa, ya gerçekten şanslı (muhtemel değil) ya da bu yaygın bir ifade. Yaygın bir ifadeyse, tek değişken ne kadar uzun yapılacağıdır.
Bir örnek alalım. İncil'den bir alıntı yapalım (başka bir nedenle değil, uzun metnin ortak bir kaynağı olduğu için):
Komşunun evine göz dikmeyeceksin. Komşunuzun karısına, uşağına ya da hizmetçisine, öküzüne ya da eşeğine ya da komşunuza ait herhangi bir şeye göz dikmeyeceksiniz.
Bu 180 karakter. 73. karakter g
ikinci karakterdir neighbor's
. Bu kadar çok tahmin ettiyseniz, muhtemelen durmayacaksınız nei
, ancak ayetin geri kalanına devam ediyorsunuz (çünkü şifre büyük olasılıkla bu şekilde kullanılacaktır). Bu nedenle, "hash" iniz pek bir şey eklemedi.
BTW: KESİNLİKLE bir incilden alıntı kullanmayı savunmuyorum. Aslında tam tersi.
Sonuç
İlk önce hashing yaparak uzun şifreleri kullanan insanlara pek yardımcı olmayacaksınız. Kesinlikle yardımcı olabileceğiniz bazı gruplar. Bazılarını kesinlikle incitebilirsin.
Ama sonuçta bunların hiçbiri aşırı derecede önemli değil. Biz ilgileniyor sayılar sadece vardır YOL çok yüksek. Entropideki fark çok fazla olmayacak.
Bcrypt'i olduğu gibi bırakmanız daha iyi. Karıştırmayı bozma olasılığınız (kelimenin tam anlamıyla, zaten yaptınız ve bu hatayı yapan ilk veya son değilsiniz), engellemeye çalıştığınız saldırı gerçekleşecek.
Sitenin geri kalanını korumaya odaklanın. Ve parola gücünü belirtmek için kayıt sırasında parola kutusuna bir parola entropi ölçer ekleyin (ve bir parolanın kullanıcının değiştirmek isteyebileceği kadar uzun olup olmadığını belirtin) ...
Bu benim en az 0,02 dolarım (veya muhtemelen 0,02 dolardan çok daha fazla) ...
"Gizli" Bir Biber Kullanırken:
Bir hash işlevini bcrypt'e beslemek için tam anlamıyla hiçbir araştırma yoktur. Bu nedenle, "biberli" bir hash'i bcrypt'e beslemenin, bilinmeyen güvenlik açıklarına neden olup olmayacağı en iyi ihtimalle belirsizdir (yapmanın hash1(hash2($value))
, çarpışma direnci ve ön görüntü saldırıları etrafındaki önemli güvenlik açıklarını ortaya çıkarabileceğini biliyoruz ).
Zaten gizli bir anahtarı ("biber") saklamayı düşündüğünüzü düşünürsek, neden onu iyi çalışılmış ve anlaşılmış bir şekilde kullanmıyorsunuz? Neden karmayı depolamadan önce şifrelemiyorsunuz?
Temel olarak, parolayı karıştırdıktan sonra, tüm karma çıktısını güçlü bir şifreleme algoritmasına besleyin. Ardından şifrelenmiş sonucu saklayın.
Şimdi, bir SQL-Enjeksiyon saldırısı, şifreleme anahtarına sahip olmadıkları için yararlı hiçbir şey sızdırmaz. Ve eğer anahtar sızdırılırsa, saldırganların durumu, sade bir hash kullandığınızdan daha iyi olamaz (ki bu kanıtlanabilir, "ön karma" biberinin sağlamadığı bir şey).
Not: Bunu yapmayı seçerseniz, bir kitaplık kullanın. PHP için Zend Framework 2'leri şiddetle tavsiye ederimZend\Crypt
paketini . Aslında şu anda bu noktada önerdiğim tek şey bu. İyice gözden geçirildi ve sizin için tüm kararları veriyor (ki bu çok iyi bir şey) ...
Gibi bir şey:
use Zend\Crypt\BlockCipher;
public function createHash($password) {
$hash = password_hash($password, PASSWORD_BCRYPT, ["cost"=>$this->cost]);
$blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
$blockCipher->setKey($this->key);
return $blockCipher->encrypt($hash);
}
public function verifyHash($password, $hash) {
$blockCipher = BlockCipher::factory('mcrypt', array('algo' => 'aes'));
$blockCipher->setKey($this->key);
$hash = $blockCipher->decrypt($hash);
return password_verify($password, $hash);
}
Ve faydalıdır çünkü tüm algoritmaları iyi anlaşılan ve iyi çalışılan şekillerde (en azından nispeten) kullanıyorsunuz. Hatırlamak:
En beceriksiz amatörden en iyi kriptografa kadar herkes kendi kıramayacağı bir algoritma yaratabilir.