Neden std :: hash 'in deterministik olduğu garanti edilmiyor?


28

Bundan böyle N4140 (C ++ 14 Standard) kullanacağız .


Göre 17.6.3.4 Hash gereksinimlerini § ,

Döndürülen değer yalnızca tartışmaya bağlı olacaktır k programın süresine ilişkin .

[Not: Böylece h(k)aynı değer için ifadenin tüm değerlendirmeleri kaynı sonucu verir , programın belirli bir yürütülmesi için verir . - son not]

ve § 20.9.12 Sınıf şablonu karması diyor

...

örnekleme hash<Key> :

(1.1) - Karma gereksinimlerini karşılar (17.6.3.4) ...

(1.2) - ...


Bu, value(yanihash<decltype(value)>(value) , programı yeniden ) farklı bir değer alabileceği .

Ama neden? Bu sınırlama C ++ 11 standardında değil, C ++ 14, C ++ 17 ve C ++ 20 standardındaydı. Bir kullanıcı olarak (STL geliştiricisi değil), std::hashdeterministik olsaydı oldukça yararlı olurdu . Deterministik bir hash fonksiyonunun uygulanmasında herhangi bir matematiksel zorluk var mı? Ancak günlük kullandığımız hash işlevlerinin (örneğin kullanımdan kaldırılmış md5sumveya daha güvenli sha256) hepsi belirleyicidir. Verimlilik sorunu var mı?


7
"... Karma işlevlerinin yalnızca bir programın tek bir yürütmesinde aynı girdi için aynı sonucu üretmesi gerekir; bu, çarpışma hizmet reddi saldırılarını önleyen tuzlanmış karmalara izin verir ." Kaynak: en.cppreference.com/w/cpp/utility/hash
Richard Critten

5
Deterministik bir algoritmanın deterministik olmayan girdileri almasına izin verir. İşaretçi değerleri, örneğin. Değişmez bir veri yapısı, dahili verilerinin adreslerini içerebilir, bu da içeriğin özetlenmesinden çok daha hızlı olabilir.
John Kugelman

4
Bu cevabın neden determinizm istemeyeceğine dair bazı güzel bağlantıları var.
NathanOliver

3
Bunu bir sınırlama olarak tehdit etmeyin, ancak standart kısıtlamaları biraz daha az katı hale getirin.
Marek R

4
İşte bu yüzden tam açıklama kısıtlamaları gevşetmek edilmiştir.
Marek R

Yanıtlar:


17

Karma işlevinin çalışmalar arasında belirleyici olmasına gerek yoktur, ancak yine de kendi karma işleminizi sağlayabilirsiniz, örneğin güvendiğiniz bir davranışsa sıralanmamış konteynerler için.

Neden gelince, cppreference diyor ki:

Karma işlevlerinin yalnızca bir programın tek bir yürütmesinde aynı girdi için aynı sonucu üretmesi gerekir; bu, çarpışma hizmet reddi saldırılarını önleyen tuzlanmış karmalara izin verir.

Eğer Hash şartlar bunu deterministik olmak söyler, o zaman gereksinimi kırmadan tuzlu karma sağlamak mümkün olmaz.

İşte asıl açıklama neden


7

@NathanOliver tarafından önerilen bu cevap (ve içindeki bağlantılar) sonuçta yardımcı olur. Önemli kısımlardan bahsedeyim.

Kriptografik olmayan bir karma işlevi için, sıralanmamış kapları algoritmik olarak yavaşlatmak ve aynı zamanda bir hizmet reddi saldırısına neden olmak için aynı karma değere sahip büyük girişleri önceden hesaplamak mümkündür.

( Sayı 2291'den itibaren. std :: karma DoS saldırısına karşı savunmasızdır )

Bu nedenle, dil tasarımcıları rastgele karmaya geçiyor. Rastgele karma işleminde, programınızı her çalıştırdığınızda “a” dizesinin karma değeri değişebilir. Rastgele karma artık Python (sürüm 3.3'ten itibaren), Ruby (sürüm 1.9'dan itibaren) ve Perl (sürüm 5.18'den itibaren) için varsayılan değerdir.

( Rastgele karma kullandığınızı biliyor musunuz? )

Reflektör tartışmasında izin bile tartışmalı olduğundan, Hemen değil Hazır'a geçin

( Sayı 2291'den itibaren. std :: karma DoS saldırısına karşı savunmasızdır )

Pratikte, anladığım kadarıyla, std::hashrastgele karma uygulama yok ama kendi yazabilirsinizmy::secure_hash .

( bu cevaptan )


PS

Ben sadece "karma tablo dos" googled ve bilgilendirici bir sayfa buldum: Dünyadaki her sunucuyu fark ettiğiniz an savunması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.