it-swarm-eu.dev

HMAC - Proč ne HMAC pro ukládání hesel?

Nota bene: Jsem si vědom, že dobrá odpověď pro bezpečné uložení hesla je scrypt nebo bcrypt . Tato otázka není pro implementaci do skutečného softwaru, je to pro mé vlastní pochopení.

Řekněme, že Joe Programmer má za úkol bezpečně ukládat hesla koncových uživatelů do databáze pro webovou aplikaci; nebo ukládání hesel na disk pro přihlášení k určitému softwaru. Nejpravděpodobněji:

  1. Získejte $password Od koncového uživatele.
  2. Vytvořte $nonce Jako náhodnou hodnotu o velikosti 64 nebo 128 bitů.
  3. Vytvořte $hash = SHA256($nonce$password) a uložte $nonce Spolu s $hash Do databáze.

Otázka 1:

Proč není následující podstatně lepší než výše uvedené?

  1. Vytvořte $long_string Jednou a pouze jednou. Uložte to jako konstantu v kódu aplikace. $long_string Mohl f.x. být 2 kilobyte náhodných znaků.
  2. Získejte $password Od koncového uživatele.
  3. Vytvořte $mac = HMAC-SHA256($long_string)[$password] (tj. Vytvořte MAC pomocí hesla koncového uživatele jako klíče) a uložte tento $mac Do databáze.

Představoval bych si, že HMAC má následující výhody?

  • Srážky jsou méně časté?
  • Je to z výpočtového hlediska o něco dražší než prosté hašování? (Samozřejmě ne nikde poblíž scrypt.)
  • Aby bylo možné v přiměřené době uspět s útokem brutální síly, musel by útočník získat přístup ke dvěma věcem: 1) k databázi, kde je uložen $mac, a 2) kód aplikace, kde je uložen původní $long_string. To je lepší než hašovací funkce, kde útočník potřebuje pouze přístup k databázi?

Ale přesto se zdá, že nikdo nenavrhuje použití HMAC, takže musím něco nechápat?

Otázka druhá:

Jaké by byly důsledky přidání hodnoty soli $nonce?

  1. Vytvořte $long_string Jednou a pouze jednou. Uložte to jako konstantu v kódu aplikace.
  2. Získejte $password Od koncového uživatele.
  3. Vytvořte $nonce Jako náhodnou hodnotu o velikosti 128 bitů.
  4. Vytvořte $mac = HMAC-SHA256($long_string)[$nonce$password] a uložte do databáze $nonce A $mac.
46
Jesper M

Smyslem soli je zabránit sdílení nákladů na útok: pokud útočník chce zaútočit na dvě hesla, pak by to mělo být dvakrát tak drahé než útočit na jedno heslo.

S vaším návrhem („otázka 1“) skončí dva uživatelé se stejným heslem pomocí stejného MAC. Pokud útočník má přístup ke čtení do vaší databáze, může si „vyzkoušet“ hesla (přepočítáním MAC) a vyhledat databázi, aby se shodovala. Poté může zaútočit na všechny hesla paralelně, za cenu útoku na ně. Pokud vaše long_string je pevně zakódovaná konstanta ve zdrojovém kódu aplikace, pak všechny nainstalované instance aplikace sdílejí tuto konstantu a pro útočník se vyplatí předkompilovat velký slovník párů hesel-MAC, také známý jako „a Duhový stůl ".

S nonce (vaše "otázka 2") se vyhnete sdílení nákladů. Nonce je obvykle známý jako "sůl". Vaše long_string a použití HMAC vás tady moc nekoupí (a mimochodem nepoužíváte HMAC k tomu, na co bylo navrženo, takže mimochodem jste na nestabilních základech, kryptograficky). Použití soli je velmi dobrý nápad (dobře, ne použití soli je velmi špatný nápad), ale dělá jen polovinu práce. Musíte také provést postup hašování pomalý. Jde o to, že sůl brání sdílení nákladů, ale nebrání útoku na jediné heslo. Útok na heslo znamená vyzkoušet možná hesla až do jednoho zápasu (to je „slovníkový útok“), a vzhledem k představivosti průměrného člověka jsou útoky na slovníky sklon fungovat: lidé prostě láska pomocí hesel, která mohou hádat. Řešením je použití hashovacího procesu, který je ze své podstaty pomalý, obvykle opakováním hašovací funkce několik tisíckrát. Záměrem je, aby ověření hesla bylo dražší: nechat uživatele čekat 1ms namísto 1µs není obtížné (uživatel si toho nevšimne), ale také zrychlí útok na slovník 1000krát. Vaše long_stringmůže k tomu použít, za předpokladu, že je opravdu dlouhý (ne 2 kilobajty, spíše 20 megabajtů).

HMAC může může být použito místo hrubé hashovací funkce k posílení systému ověřování heslem, ale v jiném nastavení. Vzhledem k tomu, že systém kontroluje hesla pomocí solí a iterovaných hashovacích funkcí, můžete hashovací funkci nahradit HMAC pomocí tajného klíče K . Tím se zabrání útokům offline slovníku, pokud budete udržovat K tajné. Udržování tajemství hodnoty není snadné, ale stále je snazší udržet 128bitový K tajný než úplná databáze.

35
Thomas Pornin

HMAC vás tady moc nekoupí, ale myslím, že to funguje jako vyměnitelná hashovací funkce (vyměnitelná změnou klíče). Každopádně se to tady zdá jako zbytečné.

První schéma, které navrhujete výše, však katastroficky selže, pokud se $ long_string dozví útočníkovi, což pravděpodobně bude, protože kód se pravděpodobně nepovažuje za tajný (a obecně je špatnou praxí spolehnout se na jeho tajnost).

Druhé schéma byste měli používat, protože $ nonce je nutný k ochraně před předpočítanými útoky.

3
frankodwyer