Какво е ключова деривационна функция (KDF) и как работят?
Ключовите деривационни функции (KDF) са критични части на криптографските системи. Както подсказва името им, те могат да се използват за извличане на силни ключове от други входове. Те включват:
- Пароли
- Споделени тайни
- Други защитени ключове (когато са необходими допълнителни ключове)
- По-слаби ключове
Те могат да се използват и за безопасно съхраняване на пароли.
Но ключовите функции за извличане и техните припокриващи се употреби могат да бъдат малко объркващи. За да ги разберем наистина, най-добре е да се върнем към основите и да обясним какво представляват ключовете, как се различават от паролите и най-добрите начини за съхраняване на пароли.
Какво представляват ключовете?
Нека започнем с абсолютните основи. The Национален институт за стандарти и технологии (NIST) дефинира ключ като:
„Параметър, използван с криптографски алгоритъм, който определя работата му по такъв начин, че субект с познания за ключа може да възпроизведе или обърне операцията, докато субект без познания за ключа не може.“
Това е сложно определение, така че нека го разбием малко по-подробно. Ключът е основно допълнителен вход, който добавяме към различни видове криптографски алгоритми, за да произведем конкретен резултат . Ключовете са под формата на наистина големи числа, често наричани низове.
Нека ви дадем по-конкретно обяснение на ключовете. В контекста на алгоритъм за криптиране със симетричен ключ като AES — което използваме за шифроване на повечето от нашите данни — вземаме данните, които искаме да шифроваме, и ги пускаме през алгоритъма заедно със таен ключ, за да ни даде шифрования текст.
Този шифрован текст не може да бъде дешифриран без ключа (тук има няколко предупреждения, но нека не усложняваме нещата на този етап). Когато искаме да дешифрираме данните, за да имаме достъп до тях, ние вземаме нашия шифрован текст и ключа и по същество ги прекарваме през алгоритъма назад, за да ни дадат оригиналните данни.
Тъй като ключовете ни позволяват да пазим данните поверителни, често трябва да ги пазим в тайна. Когато ние сме единствените, които знаят ключ, който защитава данните, това означава, че ние сме и единствените, които имат достъп до тези данни. Това предпазва нападателите от нашата чувствителна информация.
Асиметрични ключове
Не всички ключове трябва да се пазят в тайна. Асиметричната криптография, известна още като криптография с публичен ключ, е жизненоважна част от нашата среда за киберсигурност, която включва поддържането на някои ключове публични.
Алгоритми за асиметрично криптиране като RSA ни позволяват да правим всякакви неща извън това, на което е способно криптирането със симетричен ключ, което току-що очертахме. Те ни позволяват да комуникираме сигурно с хора, които никога не сме срещали преди, и внасят доверие в нашите комуникации чрез цифрови подписи .
Ключовете са сложни и има набор от различни типове, които ни помагат да постигнем различни важни неща. Въпреки това, в тази статия ще се фокусираме върху типовете ключове, които трябва да пазим в тайна .
Свойствата на ключовете
Ако нашите важни данни са защитени от таен ключ, трябва да сме сигурни, че хакерите не могат да разберат ключа. Ако могат да намерят ключа, те могат да дешифрират данните също толкова лесно, колкото и ние.
В допълнение към необходимостта да пазим ключа в тайна, той също трябва да отговаря на определени свойства, за да сме сигурни, че нападателят няма да може да го разбере:
Дължина на ключа
Дължината на ключа е важен фактор за цялостната сигурност на дадена криптосистема. Дължината на ключа по същество се отнася до размера на ключа, с по-големите ключове обикновено са по-сигурни (има изключения от това). Винаги обаче има компромис между сигурност и скорост.
Основната концепция е сравнително проста: ако някой мисли за число между едно и десет, ще можете да го познаете само с няколко опита. Ако мислят за число между едно и милион, вероятно ще се отегчите, преди да го разберете.
Ключовете са основно големи числа, така че колкото по-голямо е полето от числа, от които да избирате, толкова по-трудно ще бъде за атакуващия да разбере вашия ключ. Ключовете трябва да са с определена дължина или повече, за да бъдат сигурни за дадена цел. Това зависи от ситуацията, но като пример AES има три ключови дължини:
- 128 бита
- 192 бита
- 256 бита
Други алгоритми, като RSA , използвайте много по-големи ключове. Не е необичайно RSA да използва 4096 битови ключове. Тези големи RSA ключове обаче не предоставят непременно повече сигурност на криптосистемата от по-малките AES ключове. Това се дължи на някои сложности на математиката, която е в основата на тези два алгоритъма, но е извън обхвата на тази статия.
Случайност
Ключът трябва да е случаен или достатъчно близък до произволния, така че дори сложните техники да не могат да открият никакви модели . Ако има някакви модели или ограничения, това може да улесни много хакера да разбере ключа.
Нека обясним това по-подробно, като се върнем към нашия пример от по-горе: Ако вашият приятел избере наистина произволно число между едно и милион, тогава има равен шанс това да е всяко едно число в този диапазон. За да го разберете, ще трябва да познаете всяко едно число по систематичен начин, докато не извадите късмет и не попаднете на правилното. Средно ще са ви необходими 500 000 предположения, за да го направите правилно. Това ще ви отнеме изключително много време.
Нека променим примера и кажем, че сте виждали ваш приятел да играе тази игра с други преди. Забелязахте, че числата, които избират, всъщност не са случайни. Винаги, когато играят, номерът винаги завършва на 837. Не сте сигурни защо, но по някаква причина вашият приятел има мания за това число. Забелязали сте модел и можете да го използвате, за да улесните много работата си.
Вместо да се налага да си проправяте път през всяко едно число, можете да ускорите нещата драстично, като отгатвате само числа, които завършват на 837:
837, 1837, 2837, 3837, 4837 и т.н.
Тъй като сте разбрали модела, трябва да ви отнеме само средно 500 предположения, за да разберете числото, за което вашият приятел мисли.
Защитата на ключовете работи по абсолютно същия начин. Ако всички ключове от дадена система следват предсказуем модел, много по-лесно е да разберете какъв всъщност е ключът.
Равномерно разпределение
Трябва да се тревожим не само за моделите. Също така трябва да се тревожим дали ключовете са от a равномерно разпределение . Например, да кажем, че имате генератор на ключове, който трябва да ви даде произволни 128-битови ключове. Ще използваме десетични числа, за да обясним това, за да избегнем усложняването на нещата повече от необходимото.
В десетична система най-голямото 128-битово число е:
340,282,366,920,938,463,463,374,607,431,768,211,456
Ако генераторът на ключове беше наистина случаен и имаше равномерно разпределение, бихте очаквали да е еднакво вероятно ключът да бъде всяко едно число между 0 и 340,282,366,920,938,463,463,374,607,431,768,211,456.
Но да кажем, че има грешка в генератора на ключове. Стартирате го няколко пъти и това са ключовете, които извежда:
- 8722
- 9345
- 0497
- 1438
- 7506
- 4379
- 3984
Какво стана? Тези числа са привидно произволни, но със сигурност не са еднакви и равномерно разпределени между 0 и 340,282,366,920,938,463,463,374,607,431,768,211,456. Всички те се групират под 10 000 заради грешката.
Ако хакер разбере, че генераторът на ключове, използван в криптосистемата, е дефектен и извежда само ключове в такъв ограничен диапазон, това би направило работата им много по-лесна. Поради ограниченото разпространение на ключовете, 128-битовият ключ би бил тривиален за отгатване.
Това ще отнеме средно само 5000 предположения, вместо трилионите и трилионите, които един наистина случаен и еднообразен 128-битов ключ би изисквал. Ето защо еднаквостта е друг важен аспект на генерирането на ключове.
Не трябва да има видима връзка между различните ключове
Една заплаха срещу криптосистемите, която трябва да разгледаме, е известна като a атака със свързан ключ . В този сценарий нападателят може да наблюдава работата на алгоритъм за криптиране, докато обработва данни, използвайки редица различни ключове.
В началото на наблюдението нападателят не знае стойностите за нито един от ключовете, но знае, че има връзка между тях.
Един пример е WEP, дефектен протокол, на който може да сте се натъкнали, когато настройвате Wi-Fi рутер. Той прилага един главен ключ за всички потребители на WLAN. Когато шифрова данни с RC4, той използва този ключ плюс 24-битов вектор за инициализация като ключ за шифроване за всеки пакет. Това означава, че има връзка между ключовете.
Повторното използване на ключа плюс сравнително краткия вектор за инициализация означава, че атакуващият може да прихване пакетите с данни за сравнително кратък период от време и след това да използва известните свойства на графика на ключа RC4, за да възстанови ключа .
Повторното използване на подобни ключове в крайна сметка означава, че нападателите могат лесно да възстановят обикновения текст, като напълно отменят всяка защита, предполагаемо предоставена от WEP. Това е само един пример защо нашите криптосистеми никога не трябва да използват повторно ключове, които имат видими връзки между тях .
Ключове срещу пароли
Паролите са важна част от нашите системи за сигурност.
Ключовете могат да изглеждат много като пароли на повърхностно ниво и наистина има много прилики между двете. Въпреки това е важно да разберем разликите и отделните роли, които всеки играе в нашите криптосистеми.
Подобно на ключовете, паролите също са части от данни, които трябва да се пазят в тайна от неоторизирани лица. Те играят жизненоважна роля и за запазването на нашите данни в безопасност. Въпреки това, паролите първоначално са предназначени да бъдат запомнени от хората , и те се използват най-вече като начин за потребителите да докажат своята самоличност.
Когато влиза в система, потребителят може по същество да поиска всяко потребителско име, тъй като не се изисква потребителското име да бъде лично. Системите за контрол на достъпа използват пароли, за да сортират законните потребители от нападателите и измамниците. По същество, ако човек се опита да влезе катопотребител123, системата по същество ги моли да го докажат:
„Ако наистина сипотребител123, тогава го докажи! Кажете ми тайната информация, която самопотребител123знае.”
След това лицето въвежда своята парола. Ако съвпада с информацията, която системата има във файлпотребител123, тогава предполага, че лицето трябва да е легитимнопотребител123и им предоставя достъп. Това не е перфектна система, но повече или по-малко работи.
Ако се предполага, че паролите са секретна информация, която използваме, за да доказваме самоличността си, тогава се нуждаем от начин да ги съхраняваме, който ограничава риска от нападателите да могат да ги разкрият. Традиционно това се прави най-добре, като ги пазим в главите си и може би имаме резервно копие, заключено в сейф у дома.
Това ни води до първата основна точка на разграничение между ключове и пароли:
Паролите трябва да бъдат запомнящи се
Исторически погледнато, хората трябваше да могат да запомнят своите пароли, за да ги пазят сигурни, но лесно достъпни. като хора, ние сме страхотни в запомнянето на модели и думи, но сме и мързеливи . Това води до създаването на пароли, които често не са достатъчно дълги, нито са напълно произволни поредици от данни с еднакво разпределение.
Хората са склонни да избират неща католовец2, или името на любимия им спортен отбор плюс рождената им дата (имайте предвид, че това не са добри пароли), а неZq4t7w!z%C^F-J@N. Те са много по-лесни за запомняне от произволни низове.
Резултатът е, че повечето пароли нямат дължината или произволността, които са необходими, за да бъдат подходящи ключове , нито са взети от равномерно разпределение. Ако ги използваме като ключове, това ще направи системите ни уязвими за атаки.
През последните години нещата се промениха малко с възхода на мениджърите на пароли. Те позволяват на потребителите да запомнят само една главна парола, която след това контролира достъпа до всичките им други пароли. Тъй като само една парола трябва да бъде запомнена, това прави възможно всички останали да бъдат произволни и от еднакви разпределения – потребителите не трябва да ги държат заключени в мозъците си.
Много хора обаче все още не са приели мениджъри на пароли, така че това не е причинило големи промени в цялостната структура на системите за сигурност.
Как можем да превърнем паролите в ключове?
Заявихме, че се нуждаем от ключове, които да действат като сигурни входове за нашите криптографски системи, но хората са склонни да запомнят и въвеждат пароли.
Това ни води до основен проблем: Как можем да превърнем запомнящите се от човека пароли в ключове, които нашите криптосистеми могат да използват?
С ключови деривационни функции (KDF).
Какво е ключова деривационна функция (KDF)?
В най-общ смисъл, функция за извличане на ключове (KDF) приема вход, прекарва го през специална функция и след това извежда защитен ключов материал . Въведеното може да бъде парола или друг слаб ключов материал.
За какво се използват ключови функции за извеждане (KDF)?
Ключовите функции за извличане всъщност могат да правят редица неща, включително:
- Превръщане на пароли и други слаби източници на ключов материал в силни ключове. Това е известно като разтягане на ключове .
- Генериране на множество ключове от един източник на ключов материал. Това ни позволява да използваме отделни ключове за всеки аспект на криптосистемата.
- Сигурно съхраняване на пароли, за да ги предпазите от хакери.
Как работят базираните на парола функции за извличане на ключове (PBKDF)?
Има редица различни базирани на парола функции за извличане на ключове, но ние ще демонстрираме как работят, като обсъдим PBKDF2:
Как работи PBKDF2?
Както вероятно се досещате, PBKDF2 означава базирана на парола функция за извличане на ключове 2. PBKDF2 е публикуван през 2000 г. като част от поредицата на RSA Laboratories за криптографски стандарти с публичен ключ (PKCS). PKCS излага основите за това как трябва да се внедри защитена криптосистема с публичен ключ. PBKDF2 замени PBKDF1, който произвежда ключове, които не са достатъчно големи, за да бъдат защитени в текущата среда.
Една от целите на базирана на парола функция за извличане на ключ е да превърне парола, тайна с ниска ентропия, в ключ с подходяща дължина и достатъчна произволност от равномерно разпределение.
PBKDF2 прави това, като взема четири входа:
- Парола — Това е паролата на потребителя, която трябва да се превърне в силен ключ. Разбира се, паролата трябва да се пази в тайна.
- А сол — Солта по същество е допълнително произволно въвеждане на данни, които се обработват от KDF заедно с паролата. Солите не трябва да са тайни и те се съхраняват заедно с хешовете на паролите.
- Брой итерации — Броят на итерациите определя колко пъти стойностите ще бъдат преминати през функцията.
- Получената дължина на ключа — Това е дължината, която внедрителят иска да бъде изходът – силният ключ.
PBKDF2 поставя паролата и солта през a псевдослучайна функция определен брой пъти, според стойността за броя на итерациите. Крайният изход е силен ключ с дължината, която е определена във входа за дължина на извлечения ключ. След това този ключ може да се използва за защита на различни аспекти на криптосистема.
PBKDF2 може да използва набор от различни псевдослучайни функции. Те включват:
- HMAC-SHA-256
- HMAC-SHA-512
- Дори HMAC-SHA-1 може да се използва за хеширане на пароли, въпреки че се нуждае от много по-голям брой итерации, за да бъде защитен. SHA-1 обикновено не се счита за сигурен в повечето други приложения.
Сега, след като очертахме цялостния дизайн на PBKDF2, нека направим крачка назад и разгледаме някои от неговите компоненти по-подробно.
Какво е псевдослучайна функция (PRF)?
В общ смисъл, псевдослучайна функция е функция, която приема a тайно произволно семе и а променлива данни като негови входове. Той извежда стойност, която е изчислително неразличима от наистина случаен изход.
PBKDF2 използва базиран на хеш код за удостоверяване на съобщения (HMAC) функционира като своя PRF. Първоначално HMAC бяха проектирани за удостоверяване на съобщения, но те могат лесно да бъдат адаптирани, за да отговарят на ролята на PRF.
Какво представляват базираните на хеш кодове за удостоверяване на съобщения (HMAC)?
Функциите на базиран на хеш код за удостоверяване на съобщения (HMAC) са изградени върху криптографски хеш функции като:
В по-традиционните приложения функциите на HMAC приемат ключ като произволно начално число и текста на съобщение като променлива на данните. Те извеждат код за удостоверяване на съобщения (MAC), който се използва за удостоверяване на съобщения, както вероятно можете да познаете от името му.
Първоначалният ключ първо се превръща в ключ с размер на блок, който след това се използва като вход в HMAC два пъти. Първият път се добавя към вътрешната подложка и се свързва (това основно означава, че една стойност се добавя към другата, образувайки по-голям низ, съставен от една стойност след друга) към текста на съобщението. След това този низ преминава през хеш, което ни дава първия изход.
След това ключът се добавя към външната подложка и се свързва с изхода от предишната операция. След това този низ се хешира, което води до крайния изход, кода за удостоверяване на съобщението (MAC).
Хеш функцията, използвана в цялостната HMAC функция, може да варира, но в HMAC-SHA-256 тя е SHA-256. В този случай SHA-256 се използва и за двете хеш операции на функцията HMAC.
В математическа нотация изглежда така:
HMAC = H (K XOR opad ‖ H(K XOR ipad ‖ текст))
Където:
- HMACе полученият базиран на хеш код за удостоверяване на съобщението.
- зе хеш функцията. В HMAC-SHA-256 това би било SHA-256.
- Ке версия с размер на блок на първоначалния ключ.
- БЕЗПЛАТНОпредставлява XOR операция .
- нагорепредставлява външна подложка.
- ‖символизира конкатенацията.
- Ай Падпредставлява вътрешна подложка.
- текстпредставлява текста на съобщението.
Как се използват функциите за удостоверяване на съобщение на базата на хеш (HMAC) в PBKDF?
Може би сте забелязали, че нормалният вид HMAC работи в цикъл. Ключът с един тип подложка се свързва с текста, след което този низ се хешира:
H(K XOR ipad ‖ текст)
След това ключът с друг тип подложка се свързва с изхода от горната функция:
H(K XOR opad ‖ първи изход)
Обикновено функцията HMAC ще спре дотук и ще имаме код за удостоверяване на съобщението, който можем да използваме, за да удостоверим съобщението.
Но какво ще стане, ако просто продължим в този цикъл?
H(K ‖ текст)
Тогава:
H(K ‖ първи изход)
Тогава:
H(K ‖ втори изход)
Тогава:
H(K ‖ трети изход)
Тогава:
H(K ‖ Четвърти изход)
И така нататък…
Точно това прави PBKDF2 с HMAC . Тук идва броят на итерациите. Той определя колко пъти трябва да преминем през този процес. OWASP в момента препоръчва a 310 000 итерации на HMAC-SHA-256 за сигурно хеширане на пароли. Това означава, че изходните данни трябва да се хешират отново и отново в този цикъл 310 000 пъти.
Целта на това е да забави хакерите, които се опитват да разберат пароли, но ще разгледаме това по-задълбочено по-късно.
В PBKDF2, паролата на потребителя действа като семе , докато солта функционира като текст . Така че първата итерация на PBKDF-HMAC-SHA-256 ще изглежда така:
HMAC = H (Парола ‖ H(Парола ‖ Сол))
Споменахме, че PBKDF2 има четири входа. Нека изберем някои стойности за тях:
- Паролата (P) — PASSWORD123
- Солта (S) - 12345678
- Брой итерации (c) — 310 000
- Получената дължина на ключа (dkLen) — 256 бита, което е 32 байта
Получената дължина на ключа и хеш функцията имат еднаква дължина (256 бита), което улеснява нещата за нас. Ако полученият ключ, който изискваме, трябва да бъде по-дълъг от дължината на хеша, ще трябва да извършим целия процес, който ще опишем за всеки от хеш блоковете. След това ще трябва да свържем всеки от тези отделни изходи заедно, за да получим крайния ключов изход от функцията.
Функцията PBKDF2 може да бъде написана така:
F (P, S, c, i) = U_1 XOR AND_2 XOR … XOR And_c
Където:
U_1 = PRF (P, S || INT (i)),
U_2 = PRF (P, U_1),
…
U_c = PRF (P, U{c-1}).
В нашия случай:
- U_x означава основната псевдослучайна функция. U_1 е резултатът от PRF (P, S || INT (i)).
- PRF е HMAC-SHA-256
- P е ПАРОЛА123
- S е 12345678
- INT (i) е 1, тъй като дължината на извлечения ключ и дължината на хеша са еднакви. Няма да се занимаваме да навлизаме в точната причина защо, но можете да я намерите сами в RFC .
- c е 310 000, защото броят на итерациите е 310 000.
Следователно:
IN1 = HMAC-SHA-256 (ПАРОЛА123, 12345678 || 1)
U_2 = HMAC-SHA-256 (ПАРОЛА123 || U_1)
U_3 = HMAC-SHA-256 (ПАРОЛА123 || U_2)
…
U_310 000 = HMAC-SHA-256 (ПАРОЛА123 ‖ U{310 000-1])
Тъй като има само един блок за обработка в нашия прост пример, нашият изход за нашият окончателен извлечен ключ е същият като U_310,000 . Ако имаше няколко блока, крайните резултати от всеки блок ще трябва да бъдат свързани заедно, за да се получи крайният ключ.
Нека просто кажем, че следният е 256-битовият ключ, защото никой не иска да премине през процеса 310 000 пъти:
bd4650a6091a9ec0efd4cee0551a8da15bca4a7766c7e5c56e676c646e8b1f0b
Как превръщането на паролите в ключове укрепва нашата сигурност?
Споменахме, че едно от основните приложения на KDF е превръщането на пароли и други слаби източници на ключов материал в силни ключове. Това е известно като разтягане на ключове . Но как разтягането на ключове прави нашите системи по-сигурни? Каква роля играят ключови функции за извеждане като PBKDF2 в него?
За да демонстрирате как базираните на парола функции за извличане на ключове могат да укрепят криптосистемите, нека сравним система, която не прилага такава със система, която го прави .
И в двата случая имаме потребител, Алис, който има слаба парола,Зайци192. Макар чеЗайци192определено е слаба парола, не е необичайно слаба. Много потребители биха използвали по подразбиране пароли, които са толкова прости, освен ако не са принудени да не го правят. Нашият тестер за пароли казва, че ще отнеме около две седмици, за да разбием това с компютър.
Ако PBKDF2 не се използва, нападателят вероятно ще използва a речникова атака за да преминете през най-вероятните комбинации от пароли, докато стигнат доЗайци192. След провеждане на атаката в продължение на две седмици, вероятно е така те ще разбият паролата и ще могат да получат пълен контрол върху акаунта на Алис .
Сега нека преминем през същото нещо със система, която внедрява PBKDF2 с HMAC-SHA-256, за да разтегне паролата в по-силен ключ. В тази система Алиса въвежда своята парола,Зайци192и системата го прекарва през многото повторения на хеширане. След това изплюва 256-битов хеш. Да кажем, че е нещо подобно:
ff2fcd3cc0fe4ab6cc18a17a643483588f744a6af664eba96cfe651dc58a69d5
Този път хакерът има две възможности, ако иска да получи достъп до системата:
Опит за разбиване на подобрената парола
Те могат да се опитат да разбият тази нова подобрена парола. Тази нова парола обаче е произволна и от еднообразно разпространение, което означава, че атаките в речника не биха били ефективни. Вместо това хакерът ще бъде заседнал с грубо форсиране, опитвайки всяка отделна комбинация от символи, докато в крайна сметка стигне до ключа. Тъй като е дълъг 256 бита, това ще им отнеме много време.
Нашите инструмент за тестване на силата на паролата изчислява, че ще са необходими „3760 септуагинтилиона години“, за да се разбие паролата . Това е много след топлинната смърт на Вселената, така че нашият хакер ще се отегчи много да чака толкова дълго. В този случай PBKDF2 би направило разбиването на паролата невъзможно.
Опит за разбиване на оригиналната парола
Другата възможност на нападателя е да опита да разбие оригиналната парола. Но сега, когато PBKDF2 е внедрен, това е напълно различна игра.
Ужасно несигурна система
При една ужасно несигурна система за пароли, когато някой въведе опит за парола, системата просто ще погледне в своята база данни и ще види дали опитът съвпада с паролата, която има записана. Това щеше да стане почти мигновено .
Само SHA-256
Значителна стъпка от това би било, ако базата данни съхранява само SHA-256 хеш на паролата, а не самата парола. В този случай, когато човек въведе паролата, системата първо ще я хешира, след което ще провери в своята база данни, за да види дали този хеш съответства на хеша, който има в записа.
Тъй като системата също трябва да хешира паролата, преди да я търси, това отнема малка част от секундата повече . Обърнете внимание, че това все още се счита за несигурно, но просто не толкова несигурно, колкото първата система за удостоверяване на парола.
Внедряване на PBKDF2
Сега нека сравним тези две предишни опции със система, която прилага PBKDF2. При тази система, когато човек въведе опит за парола, той не се хешира само веднъж през SHA-256, добавяйки това малко допълнително време.
Вместо това, както обсъдихме по-рано, PBKDF2 включва хеширане на паролата със солта, след това хеширане на този резултат с паролата, след това хеширане на този резултат с паролата и т.н.
Точният брой пъти зависи от брой итерации който е избран за изпълнение. Всяка допълнителна итерация отнема малко повече време. В нашия пример от по-горе имаше 310 000 итерации, което означава, че резултатът беше хеширан заедно с паролата отново и отново, общо 310 000 пъти.
Защо това е важно?
Поставете се на мястото на нападателя. Те се опитват да намерят правилната парола, като познаят възможните комбинации. При втората система за удостоверяване на паролата всяко предположение ще отнеме само малка част от секундата, защото ще трябва да изчислят SHA-256 хеш само веднъж.
С внедряване на PBKDF2, изпълняващо 310 000 итерации на HMAC-SHA-256, по същество ги принуждавате да вършат 310 000 пъти повече работа за всяко едно отгатване на парола . Това също повишава цената с кратно 310 000.
Резултатът от прилагането на PBKDF2 е, че става твърде скъпо да се разбият много пароли, които са били податливи на разбиване без него. Като прави значително по-трудно разбиването на паролите, PBKDF2 може да помогне за защитата на много потребители.
Всички тези допълнителни итерации на SHA-256 оказват влияние върху потребителите, но не е забележимо. Влизаме сравнително рядко и повечето от нас правят само няколко опита, преди да сме правили паролите си.
Дори ако PBKDF2 промени времето за влизане за потребител от почти мигновено до около секунда, това има незначителен ефект върху тях. Но усложняването на работата на хакера 310 000 пъти оказва огромно влияние върху тях. Този компромис го прави много полезно, защото печалбите за сигурност са огромни.
Какво е осоляване и каква роля играе в ключовите функции за извеждане (KDF)?
Сега, след като обяснихме как работят псевдослучайни функции като HMAC-SHA-256 в PBKDF2, нека разгледаме ролята на осоляването. Солта е несекретна стойност, която в крайна сметка се съхранява заедно с окончателния хеш на паролата.
Както видяхте, солта беше добавена като вход в първата итерация на функцията HMAC-SHA-256 на PBKDF2:
U_1 = HMAC-SHA-256 (ПАРОЛА123, 12345678 || 1)
В нашия пример солта беше 12345678.
За да разберем какво всъщност прави солта за нас, трябва да обсъдим как се съхраняват паролите и как могат да бъдат разбити.
Как се съхраняват паролите?
Ако си спомняте какво споменахме по-рано, организациите никога не трябва да съхраняват паролите на своите потребители. Вместо това системата трябва да съхранява хеша на паролата им. Системата работи малко по следния начин:
- Потребител въвежда своята парола, за да влезе.
- Системата незабавно хешира паролата и никога не я съхранява.
- След това системата търси в своята база данни, за да провери дали този хеш на паролата съвпада с хеша на паролата, който има във файла за този потребител. Ако двете съвпадат, на потребителя се разрешава влизане.
Предимството на тази система е, че хешовете на паролите не могат да се използват за директно нарушаване на потребителски акаунти. Ако една организация претърпи нарушение на данните, за хакерите е много по-трудно да компрометират потребителски акаунти, когато имат само хешове на пароли, за разлика от паролите в обикновен текст.
Нека ви дадем по-конкретен пример: Алис има акаунт в компания и нейната парола езаек9(направихме нейната парола още по-слаба от последния път, за да улесним работата на хакера).
Когато тя настройва акаунта си, компанията хешира въведената от нея парола с хеш функцията SHA-256 (това не е добра практика за сигурност, това е просто опростен пример) и запазва тази стойност в своята база данни, за да може да я провери парола в бъдеще.
Едно просто SHA-256 хеш зазаек9 би било:
7c848f9515f8d64b9e37f4459e5232b373746178c0129ddefe8c3315088db32e
Така че компанията щеше да има горния хеш в своята база данни и когато Алис отиде да влезе, тя щеше да въведезаек9в полето за парола. Компанията веднага ще го хешира, което ще доведе до същата стойност. След това ще сравни този резултат с хеша, който има в своята база данни. Тъй като двете съвпадат, това ще й даде достъп.
Сега, да кажем, че компанията е имала нарушение на данните и хакер е намерил потребителското име на Алис и парола хеш в пробива. Ако нападателят се опита да влезе с:
7c848f9515f8d64b9e37f4459e5232b373746178c0129ddefe8c3315088db32e
Системата на компанията веднага ще хешира стойността, в резултат на което :
ca32706cd89b61ba81c734630d09a7ec3982ca0b01e08084aebfed531b5ed61c
След това системата на компанията ще вземе тази стойност и ще я сравни с хеша, съхраняван в нейната база данни. Тъй като двете не съвпадат, на нападателя няма да бъде предоставен достъп.
Тъй като системите за удостоверяване са настроени по този начин, хешовете на паролите не позволяват на атакуващите да ги използват, за да получат директен достъп. Вместо това нападателите трябва да намерят някакъв начин да разберат оригиналната парола от хеша. Но едно от ключовите свойства на хеш функциите е, че те трябва да бъдат еднопосочен . Така че, ако е използвана силна хеш функция, не е възможно просто да превърнете хеша обратно в паролата.
Но това не означава, че хешовете на паролите са напълно безполезни за нападателите.
Представяме ви Rainbow таблици
За съжаление няма много дъги, включени в дъговите маси.
Единият вариант е да се построи дъгови маси . Тези таблици са конструирани чрез стартиране на общи пароли чрез хеш функции и след това съхраняване на резултатите в голяма таблица.
Относително, хеширането може да отнеме много време за работа на компютрите. Търсенето може да се направи много по-бързо. Това означава, че ако вече имате предварително изчислена дъгова таблица със съвпадащи пароли и хешове на пароли, можете да си спестите времето, необходимо за изчисляване на всички тези хешове.
Ако нападател се натъкне на нарушение на сигурността на данните, което включва хешове на пароли на потребители, той може да сравни тези хешове с хешовете на паролите в своята дъгова таблица.
Ако намерят съвпадения между хешовете от пробива на данни и тяхната дъгова таблица, те биха могли да потърсят съответната парола за тези потребители в своята дъгова таблица. Това им дава ефективен начин за намиране на пароли за потребители, които използват относително често срещани пароли.
Сега казахме, че е практично да се изчисляват дъгови таблици за относително често срещани пароли. Това е така, защото въпреки че дъговите таблици могат да ви спестят много време, има компромис – те изискват много повече място в паметта. Това ограничава колко голяма може да бъде дъговата таблица и затова те са ефективни само срещу по-често срещани комбинации от пароли.
Осоляването защитава потребителите
Да се върнем към Алис и нейната слаба парола,заек9.заек9е достатъчно проста, че много хакери биха я имали в своите предварително изчислени таблици на дъгата. Те може вече да знаят, че SHA-256 хеш зазаек9е:
7c848f9515f8d64b9e37f4459e5232b373746178c0129ddefe8c3315088db32e
Това означава, че когато компанията претърпи нарушение на данните и нейната база данни с хешове на пароли е компрометирана, хешът на паролата на Alice ще съвпадне с хеша в дъговата таблица на хакера. След това хакерът може да потърси съответната парола в дъговата таблица и те лесно могат да поемат нейния акаунт.
Един от начините за защита на потребителите от атаки на Rainbow Table е чрез осоляване. Нека отново да опростим нещата и да кажем това вместо просто хеширанезаек9с SHA-256 системата първо го добавя със сол и след това го хешира. Солта е несекретна стойност. Да кажем, че в този случай солта е осемцифрен низ 95056398 . Това ни дава:
Заек995056398
Когато поставите паролата плюс солта през SHA-256, получавате напълно различен хеш като резултат:
82ab7b8879960812cca5091215f9a7a6462f44a4c41b8c949eeec61577a27fb1
Как това променя нещата от гледна точка на потребителя?
Не става . Системата просто запазва солите заедно с хешовете на паролата. Всеки път, когато потребител въведе паролата си, за да влезе, системата извлича солта, добавя я към паролата и след това ги хешира заедно. След като двете бъдат хеширани, системата взема резултата и след това го сравнява с хеша на паролата във файла. Ако двете съвпадат, това дава достъп на потребителя.
От гледна точка на нападателя виждаме голяма разлика. Защо? Тъй като прави атаките на масата на дъгата невъзможни . Както казахме, дъговите маси ускоряват нещата за сметка на заемането на място. Колкото по-дълга и по-сложна е една парола, толкова по-голяма трябва да бъде дъговата таблица, за да може нейният хеш да бъде включен в таблицата.
Антъни Ферара направи някои от неговите изчисления блог :
- Парола от четири знака — 35 153 041 уникални комбинации, което ще изисква 913MB дъгова таблица. Всеки от нас може да съхранява това на компютрите си. Размерът е на филм с ниско качество.
- Парола от пет знака — 2 706 784 157 уникални комбинации, които биха изисквали дъгова таблица от 70 GB. Много телефони имат толкова много памет. Някои имат много повече.
- Парола от шест знака — 208 422 380 089 уникални комбинации, което ще изисква 5,4TB дъгова таблица. В зависимост от вашата страна вероятно можете да си купите твърд диск, по-голям от този за няколкостотин долара.
- Парола от седем знака — 16 048 523 266 853 уникални комбинации, което ще изисква 417TB дъгова таблица. На този етап излизаме извън обсега на един хакер, но много хакерски групи или национални държави лесно биха имали толкова много налично хранилище.
- Парола от осем знака — 1 235 736 291 547 681 уникални комбинации, което ще изисква 32PB дъгова таблица. Един петабайт (PB) е 1024 терабайта. Това е много място за съхранение. Противникът ще трябва да има изключително количество ресурси и невероятна решителност, за да изгради толкова голяма дъгова маса.
Дори при само 7 знака е невъзможно за повечето соло хакери да изградят дъгова таблица, която да може да отгатне всички възможни пароли в този диапазон . Сега, това не означава, че всяка парола, по-дълга от 8 знака, е безопасна - по-дългите пароли, които са често срещани, все още могат да бъдат в дъгови таблици.
Имайки предвид тези цифри, хешът зазаек9е много вероятно да бъде в дъговата таблица на хакерите. Хешът заЗаек995056398не е, защото това е дълга и много по-рядко срещана парола, и просто би струвало твърде много пари за съхраняване на необичайни пароли с такава дължина .
Концепцията зад това е, че добавянето на сол към паролата радикално разширява размера на дъговата таблица, от която хакерът би се нуждаел, за да съпостави хешовете на паролата . Дори няма значение дали хакерът знае солта, така че не е необходимо солта да е тайна стойност.
По този начин солта дава на потребителите със слаби пароли много повече защита, без потребителите всъщност да трябва да правят каквото и да било. Имайте предвид, че това не е препоръка да използвате слаби пароли, защото системата ще компенсира. Вместо това, това е практика на защита в дълбочина .
Каква роля играе броят на итерациите в ключовите деривационни функции (KDF)
Броят на итерациите играе друга жизненоважна роля в сигурността на ключовите функции за извличане (KDF). Позволява на внедрителя да посочи колко пъти ще бъдат хеширани парола и сол . Всяка допълнителна итерация на хеширане прави процеса на извличане на ключ малко по-дълъг и изисква малко повече изчислителна мощност.
Гениалността на PBKDF2 е, че итерациите могат да бъдат зададени на плъзгаща се скала. Само с няколко итерации алгоритъмът работи невероятно бързо. Колкото повече итерации задава имплементаторът, толкова по-дълго трябва да се изчисли ключът. OWASP в момента препоръчва 310 000 итерации на SHA-256 когато PBKDF2 се използва за целите на хеширането на пароли .
Ние увеличаваме броя на итерациите, за да забавим умишлено алгоритъма . Тъй като легитимните потребители трябва само да преминат през процеса най-много няколко пъти, това има ограничен ефект върху тях.
Това са хакерите, които управляват милиарди и милиарди предположения за пароли, които са засегнати значително. Тъй като те трябва да направят толкова много опити, за да разбият пароли, увеличаването на броя на итерациите с фактор 100 също увеличава разходите им 100 пъти. Коригирането на броя на итерациите нагоре може да направи невъзможно разбиването на много пароли, които биха били лесни за разбиване при по-малък брой.
Когато PBKDF2 беше пуснат за първи път, препоръката беше само задайте броя на итерациите на 1000 . Този брой обаче се е увеличил драстично през годините, тъй като технологията е станала по-мощна. Хакерите вече имат достъп до по-мощно оборудване, което би направило 1000 итерации тривиални.
Каква е дължината на извлечения ключ?
Въведената дължина на извлечения ключ позволява на внедрителя да посочи колко дълго ще бъде желаната продукция . Това е критично, когато функциите за извличане на ключове се използват за превръщане на пароли в силни ключове, тъй като дадена криптосистема ще се нуждае от ключ с определен размер.
Ако криптосистемата използва 128-битов AES за криптиране на симетричен ключ, изходът на функцията за извличане на ключ за AES трябва да бъде 128-битов. 256-битовият AES ще изисква 256-битов ключ и т.н.
Входната дължина на извлечения ключ на PBKDF2 и подобни KDF позволява на изпълнителите да задават дължината на ключа според нуждите на криптосистемата. Това е една от причините защо bcrypt е неподходящ за извличане на ключове от пароли. Това е схема за хеширане на парола, която не позволява на внедрителя да избере изходната дължина.
Когато се използва функция за извличане на ключове за хеширане на парола, не е необходим регулируем изход за дължината на ключа. Ето защо някои KDF могат да се използват както за извличане на ключове, така и за хеширане на пароли, но не всички схеми за хеширане на пароли са подходящи за извличане на ключове.
Какво е хеш-базирана функция за извличане на ключ (HKDF)?
The базирана на хеш функция за извличане на ключ (HKDF) може да вземе входен ключов материал (IKM) и да го превърне в силен изходен ключов материал (OKM). Той се основава на базирани на хеш кодове за удостоверяване на съобщения (HMAC) и е проектиран да бъде a бърз механизъм за производство на здрави ключове .
Функцията за извличане на ключ на базата на хеш (HKDF) постига това чрез подход за извличане след това за разширяване, който има две приложения:
- Екстракт — Това ни позволява да вземем несъвършени източници на първоначален ключов материал и да произведем силен изходен ключов материал от тях. Примерите за несъвършен ключов материал включват източници, които не са достатъчно произволни, и такива, които не идват от равномерно разпределение.
- Разширяване — Разширителният модул ни позволява да произвеждаме множество здрави ключове от един източник на здрав ключов материал.
Тези два модула ни позволяват да:
- Вземете източник на слаб материал и направете силен ключ от него.
- Вземете силен ключ и създайте няколко силни ключа от него.
- Вземете слаб източник на ключов материал и създайте множество силни ключове от него.
Способността да произвеждаме множество силни ключове е изключително важна за нашите криптосистеми, тъй като ключовете никога не трябва да се използват повторно за различни цели. Инструмент като HKDF ни дава лесен начин за създаване на отделни ключове за процеси като:
- Шифроване
- Удостоверяване
- Интегритет
- Опаковка на ключове
- Случайно генериране на битове
Трябва да използваме отделни ключове за всеки аспект на нашата криптосистема, защото това помага да се ограничи количеството щети, които могат да бъдат нанесени, ако нападателят успее да компрометира ключ. Ако нападател може да компрометира ключ, който контролира всичко, той може да унищожи сигурността на комуникационния канал. Те могат да прочетат всички съобщения и дори да се вмъкнат по средата на разговора и да издадат измамни съобщения.
Когато се използват отделни ключове за всяка цел, потенциалният ефект може да бъде по-малко сериозен. Ако нападател компрометира ключ, който контролира само криптирането, поверителността на комуникационния канал ще бъде нарушена, но целостта и автентичността на канала ще останат непокътнати. Все още е голям проблем, но не е толкова лош, колкото напълно компрометиран канал.
Както казахме, функцията за извличане на ключове, базирана на хеш, е проектирана да бъде бърза. Това го прави неподходящи за извличане на ключове от пароли или за съхраняване на пароли .
Ако HKDF беше внедрен в тези приложения, неговата скорост би означавала, че нападателят може да преминава през много повече опити за парола в секунда, отколкото би могъл със защитена схема за хеширане на пароли. Това би направило много по-лесно разбиването на пароли, поради което HKDF трябва да се прилага само за предназначението му.
Различните изисквания на функциите за извличане на ключове и схемите за хеширане на пароли
Сега, след като преминахме през PBKDF2 като пример за базирана на парола функция за извличане на ключове и покрихме всеки от важните елементи в детайли, можем да направим крачка назад и да обобщим нашите изисквания за всеки от разнообразните случаи на употреба.
За извличане на силни ключове от пароли:
- Искаме алгоритъм, който може да приема пароли като вход и да произвежда произволни и еднообразни ключове. Поставяне на входа чрез a голям брой итерации в HMAC функция помага за разтягане на ключове по този начин.
- Искаме да можем задайте дължината на получения ключ .
За съхранение на пароли:
- Искаме алгоритъмът да е бавен, за да направи работата на хакера много по-трудна. Ключовото разтягане чрез голям брой итерации помага да се постигне това .
- Искаме да направим атаките с дъгова маса непрактични. Това е причината осоляването е толкова важно .
За извличане на силни ключове от по-слаби източници на ключов материал, които не са пароли:
- Искаме да произвеждаме силни ключове с достатъчна ентропия от равномерно разпределение .
- Искаме да можем задайте желаната дължина на ключа .
- Тези по-слаби източници на ключов материал все още имат много повече ентропия, отколкото много пароли. В този сценарий също така не е необходимо да имате умишлено бавна функция, като в PBKDF. Вместо, ефективността е по-желателна .
За извличане на множество силни ключове от един източник на силен ключов материал:
- Всеки от тези ключове трябва да бъде силни и независими един от друг така че ако хакер компрометира един, това не води до компрометиране на всички ключове, използвани в други аспекти на криптосистемата.
- Искаме да можем задайте желаната дължина на ключа .
- Тъй като не са включени пароли и първоначалните ключове вече имат силен източник на ентропия, няма нужда от голям брой итерации за умишлено забавяне на нападателите. Още веднъж, желана е ефективност .
Общи функции и тяхното използване
Ето списък на някои от най-често използваните функции за извличане на ключове или хеширане на пароли:
- Argon2 — Тази функция беше победител в състезанието за хеширане на пароли. Аргон2 е KDF, който е проектиран да изисква интензивна памет. Това го прави подходящ както за хеширане на пароли, така и за извличане на ключ. Той приема парола и сол като първични входове, както и осем отделни вторични входа. Има няколко различни версии, всяка със своите специфични предимства:
- Аргон2d
- Аргон2и
- Аргон2ид
- сценарий — сценарий е друга функция за извличане на ключове, която може да се използва както за съхраняване на пароли, така и за извличане на ключове. Той също така е проектиран да изисква интензивно използване на паметта, за да направи кракването на пароли много по-скъпо за нападателите. Неговите входове включват парола, сол, фактор на разходите, фактор на размера на блока, фактор на паралелизиране, желаната дължина на ключа и няколко други параметъра.
- PBKDF2 — Вече обсъдихме PBKDF2 в дълбочина в тази статия. Само за да повторя, неговите входове включват парола, сол, брой итерации и извлечена дължина на ключа. Въпреки че може да се използва както за извличане на ключове, така и за хеширане на пароли, в наши дни се използва главно за хеширане на пароли, защото е доста стара функция. OWASP препоръчва 310 000 итерации на SHA-256 в PBKDF2, за да може неговите хешове на пароли да имат безопасна граница на сигурност.
- bcrypt — bcrypt е единствено схема за хеширане на пароли, а не KDF, която може да се използва и в двете приложения. Той включва сол и има брой повторения, който може да варира, за да го забави и да го направи по-устойчив на атаки. Изпълнителят обаче не може да коригира дължината на изходния ключ, което го прави неподходящ за извличане на ключове.
- HKDF — HKDF е ключова функция за извеждане. Въпреки това, той не трябва да се използва за извличане на ключове от пароли или за съхранение на пароли, защото е твърде бърз. Вместо това трябва да се използва за извличане на силни ключове от по-слаби входни ключови материали (не пароли), извличане на множество ключове от силен входен материал или и двете.