Šifrovanie v PHP. Šifrovanie, dešifrovanie údajov pomocou kľúča v PHP Šifrovacie a autentifikačné kľúče

  • Preklad
  • Návod

Od prekladateľa: v procese programovania nikdy nezabudnem, že som nebezpečne nekompetentný v kryptografii, a odporúčam každému, aby vychádzal z tejto práce (no, možno okrem vás a toho tamtoho pohodára). Tak či onak však v procese práce vznikajú problémy súvisiace s ochranou údajov, ktoré je potrebné riešiť. Preto vám dávam do pozornosti preklad článku od fínskeho vývojára Tima H, ktorý sa mi zdal celkom zaujímavý a užitočný.

Toto je rýchly návod, ako sa vyhnúť bežným nástrahám so symetrickým šifrovaním v PHP.

Zohľadníme prípad, keď sa údaje spracúvajú na strane servera (najmä na serveri dochádza k šifrovaniu a údaje je možné získať napríklad od klienta vo forme čistého textu, hesla atď.), čo je typický prípad pre PHP aplikácie.

Informácie v tejto príručke by sa nemali používať na vytváranie šifrovaných sieťových pripojení, ktoré majú zložitejšie požiadavky. V takýchto prípadoch musíte použiť špehovanie alebo TLS.

Prirodzene, tu uvedené odporúčania nie sú „jediným možným spôsobom“ ako zorganizovať šifrovanie v PHP. Účelom tejto príručky je pokúsiť sa ponechať menej priestoru na chyby a ťažké, nejednoznačné rozhodnutia.

Šifrovacie funkcie v PHP

Použite rozšírenia Mcrypt alebo OpenSSL.

Šifrovací algoritmus a spôsob jeho činnosti, jednorazový kód (inicializačný vektor)

Použite AES-256 v režime CTR s náhodným jednorazovým kódom ( približne. preklad: nonce). AES je štandard, takže môžete využívať funkcie ktoréhokoľvek z rozšírení – Mcrypt alebo OpenSSL.

Vždy vygenerujte nový jednorazový kód. V tomto prípade musíte použiť kryptograficky bezpečný zdroj náhodných čísel. Prečítajte si trochu viac o generovaní náhodných čísel nižšie. Jednorazový kód nie je tajný a možno ho spojiť so šifrovaným textom na prenos a následné dešifrovanie.

Jednorazový kód musí mať dĺžku 128 bitov (16 bajtov), ​​iba reťazec bajtov bez akéhokoľvek kódovania.

V rozšírení Mcrypt je AES známy ako Rijndael-128 ( približne. prekl.: napriek tomu, že hovoríme o AES-256, nejde o chybu. AES-256 != Rijndael-256). V OpenSSL, respektíve AES-256-CTR.

Príklad použitia Mcrypt:
Príklad OpenSSL:
Overte, či šifrovanie funguje správne pomocou testovacích vektorov ( približne. preklad: pre AES-256-CTR pozri odsek F.5.5 na strane 57).

Pre režim CTR existujú určité obmedzenia celkového objemu šifrovaných údajov. V praxi sa s tým možno nestretnete, no majte na pamäti, že jedným kľúčom by ste nemali zašifrovať viac ako 2^64 bajtov dát, bez ohľadu na to, či ide o jednu dlhú správu alebo veľa krátkych.

Režim CTR zostáva stabilný iba vtedy, ak nepoužívate rovnaký jednorazový kód s rovnakým kľúčom. Z tohto dôvodu je dôležité generovať jednorazové kódy pomocou kryptograficky silného zdroja náhodnosti. Okrem toho to znamená, že by ste nemali zašifrovať viac ako 2^64 správ jedným kľúčom. Keďže dĺžka jednorazového kódu je 128 bitov, limit na počet správ (a im zodpovedajúce jednorazové kódy) 2^128/2 je dôležitý z dôvodu Birthday Paradoxu ( približne. preklad:).

A pamätajte, že šifrovanie nezakryje skutočnosť, koľko údajov odosielate. Ako príklad extrémneho prípadu, ak zašifrujete správy obsahujúce iba „áno“ alebo „nie“, je zrejmé, že šifrovanie tieto informácie neskryje.

Autentifikácia údajov

Vždy skontrolujte pravosť a integritu údajov.
Ak to chcete urobiť, použite MAC po zašifrovaní. Tie. Najprv sa zašifrujú údaje a potom sa z výsledného šifrového textu prevezme HMAC-SHA-256 vrátane samotného šifrovaného textu a jednorazového kódu.

Pri dešifrovaní najprv skontrolujte HMAC pomocou porovnávacieho algoritmu, ktorý je odolný voči útokom načasovania. Neporovnávajte priamo $user_submitted_mac a $calculated_mac pomocou porovnávacích operátorov == alebo ===. Ešte lepšie je použiť "HMAC double check".

Ak je kontrola HMAC úspešná, dešifrovanie možno vykonať bezpečne. Ak HMAC nie je vhodný, okamžite ho vypnite.

Šifrovacie a autentifikačné kľúče

V ideálnom prípade použite kľúče odvodené z kryptograficky silného zdroja náhodnosti. AES-256 vyžaduje 32 bajtov náhodných dát ("surový" reťazec - sekvencia bitov bez použitia akéhokoľvek kódovania).

Ak aplikácia beží pod verziou PHP pod 5.5, ktorá nemá vstavanú implementáciu PBKDF2, potom budete musieť použiť vlastnú implementáciu v PHP, ktorej príklad nájdete tu: https://defuse. ca/php-pbkdf2.htm. Uvedomte si, že spoliehanie sa na vlastnú implementáciu nemusí vyriešiť kľúč správne, ako to robí vstavaná funkcia hash_pbkdf2().

Na šifrovanie a autentifikáciu nepoužívajte rovnaký kľúč. Ako je uvedené vyššie, 32 bajtov je potrebných pre šifrovací kľúč a 32 bajtov pre autentifikačný kľúč (HMAC). Pomocou PBKDF2 môžete z hesla odobrať 64 bajtov a použiť povedzme prvých 32 bajtov ako šifrovací kľúč a zvyšných 32 bajtov ako autentifikačný kľúč.

Ak sú vaše heslá uložené v súbore, napríklad ako reťazec HEX, nekódujte ich pred ich odovzdaním do šifrovacích funkcií. Namiesto toho použite PBKDF2 na prevod HEX kódovaných kľúčov priamo na vysokokvalitný šifrovací alebo autentifikačný kľúč. Alebo použite SHA-256 bez dodatočného výstupného kódovania (iba 32 bajtový reťazec) na hashovanie hesiel. Používanie bežného hashovania hesiel poskytuje dostatok entropie. Ďalšie podrobnosti sú uvedené v nasledujúcich odsekoch.

Natiahnutie kľúča

Po prvé, mali by ste sa vyhnúť používaniu kľúčov s nízkou entropiou. Ale napriek tomu, ak potrebujete použiť napríklad používateľské heslá, musíte určite použiť PBKDF2 s veľkým počtom iterácií, aby ste maximalizovali bezpečnosť kľúča.

Jedným z parametrov PBKDF2 je počet iterácií hashovania. A čím je vyššia, tým väčšiu bezpečnosť kľúča môžete počítať. Ak váš kód beží na 64-bitovej platforme, použite SHA-512 ako hashovací algoritmus pre PBKDF2. Pre 32-bitovú platformu použite SHA-256.

V online aplikáciách však nie je možné použiť relatívne vysoký počet iterácií kvôli riziku DoS útoku. Kľúčová kvalita teda nebude taká vysoká ako v offline aplikáciách, ktoré si môžu dovoliť veľké množstvo iterácií bez takéhoto rizika. Pre online aplikácie sa spravidla vyberá taký počet iterácií hashovania, aby PBKDF2 netrvalo viac ako 100 ms.

V prípade, že môžete použiť heslá s vysokou entropiou, nie je potrebné ich naťahovať ako pri heslách s nízkou entropiou. Napríklad, ak vytvoríte "encryption_master_key" a "auth_master_key" pomocou /dev/urandom, potom PBKDF2 vôbec nepotrebujete. Len sa uistite, že používate kľúče ako sekvencie bitov bez akéhokoľvek kódovania.

Navyše s PBKDF2 nie je ťažké získať šifrovacie aj autentifikačné kľúče z jedného hlavného hesla (stačí použiť malý počet iterácií alebo dokonca jedno). To je užitočné, ak máte iba jedno „hlavné heslo“ používané na šifrovanie aj autentifikáciu.

Ukladanie a správa kľúčov

Najlepšie je použiť samostatné vyhradené zariadenie na ukladanie kľúčov (HSM).

Ak to nie je možné, potom na skomplikovanie útoku je možné použiť šifrovanie súboru kľúča alebo konfiguračného súboru (v ktorom sú uložené skutočné šifrovacie/overovacie kľúče) pomocou kľúča uloženého na samostatnom mieste (mimo domovského adresára alebo koreňového adresára lokality) . Môžete napríklad použiť premennú prostredia Apache v httpd.conf na uloženie kľúča potrebného na dešifrovanie skutočného súboru kľúčov:
SetEnv keyfile_key crypto_strong_high_entropy_key # K tejto premennej môžete pristupovať v PHP pomocou $_SERVER["keyfile_key"] # Zvyšok konfigurácie
Teraz, ak sú ohrozené súbory v koreňovom adresári lokality a nižšie, vrátane súborov s kľúčmi (napríklad ak dôjde k úniku zálohy), zašifrované údaje zostanú v bezpečí, pretože kľúč uložený v premennej prostredia nebol kompromitovaný. Je dôležité si zapamätať, že súbory httpd.conf by sa mali zálohovať oddelene, a nie kompromitovať premennú keyfile_key napríklad cez výstup phpinfo().

Ak namiesto konfiguračného parametra použijete súbor, je možné zorganizovať striedanie kľúčov. V najhoršom prípade, ak protivník získal vaše šifrovacie a autentifikačné kľúče bez povšimnutia, rotácia kľúčov v určitých intervaloch môže obmedziť jeho prístup (za predpokladu, že nemôže získať nové kľúče). Táto technika pomôže znížiť poškodenie, pretože nepriateľ nebude môcť používať kompromitované kľúče donekonečna.

Kompresia údajov

Vo všeobecnosti by ste nemali komprimovať zdrojový text pred jeho zašifrovaním. To môže poskytnúť nepriateľovi ďalší nástroj na analýzu.

Ak napríklad uložíte údaje o relácii v šifrovaných súboroch cookie, z ktorých niektoré sú poskytnuté používateľom a niektoré predstavujú tajné informácie, protivník sa môže dozvedieť ďalšie informácie o tajomstve tak, že ako bežný používateľ odošle niektoré špeciálne vytvorené údaje a meranie, ako sa mení dĺžka výsledných šifrových textov.

Text je komprimovaný efektívnejšie, ak existujú opakujúce sa oblasti. Manipuláciou s používateľskými údajmi ich môžete vybrať tak, aby sa čiastočne zhodovali s tajnými údajmi. Čím väčšia zhoda, tým menší je výstupný šifrový text. Tento typ útoku sa nazýva ZLOČIN.

Ak nemáte nutkavú potrebu komprimovať dáta, nekomprimujte ich.

Serverové prostredie

Vo všeobecnosti by ste nemali hostiť aplikácie citlivé na bezpečnosť na zdieľanom serveri. Napríklad na zdieľanom hostingu, kde má protivník prístup k virtuálnemu stroju na rovnakom fyzickom serveri ako vy.

Existujú rôzne dôvody, ktoré robia zdieľané servery pochybným miestom na hosťovanie aplikácií kritických z hľadiska bezpečnosti. Nedávno boli napríklad preukázané útoky medzi virtuálnymi servermi: eprint.iacr.org/2014/248.pdf. Toto je dobrá pripomienka, že útočné techniky sa nezhoršujú, ale skôr sa časom zdokonaľujú a zdokonaľujú. S takýmito nástrahami treba vždy počítať.

Odborná konzultácia

V neposlednom rade sa poraďte s odborníkom, aby skontroloval váš bezpečnostný kód.

(PHP 4, PHP 5, PHP 7)

crypt — Jednosmerné hashovanie reťazcov

POZOR

Táto funkcia nie je (zatiaľ) binárne bezpečná!

Popis

krypta (reťazec $str [, reťazec $soľ]): reťazec

crypt() vráti hašovaný reťazec pomocou štandardného algoritmu založeného na Unixe DES alebo alternatívnych algoritmov, ktoré môžu byť v systéme dostupné.

Parameter soľ je voliteľný. však crypt() vytvára slabý hash bez soli. PHP 5.6 alebo novší spôsobí chybu E_NOTICE bez toho. Uistite sa, že špecifikujete dostatočne silnú soľ pre lepšiu bezpečnosť.

heslo_hash() používa silný hash, generuje silnú soľ a automaticky aplikuje správne kolá. heslo_hash() je jednoduchý crypt() wrapper a kompatibilný s existujúcimi hodnotami hash hesiel. Použitie heslo_hash() povzbudzuje sa.

Niektoré operačné systémy podporujú viac ako jeden typ hash. V skutočnosti je niekedy štandardný algoritmus založený na DES nahradený algoritmom založeným na MD5. Typ hash sa spúšťa argumentom salt. Pred verziou 5.3 by PHP určovalo dostupné algoritmy v čase inštalácie na základe systémového crypt(). Ak nie je poskytnutá žiadna soľ, PHP automaticky vygeneruje buď štandardnú dvojznakovú (DES) soľ, alebo dvanásťznakovú ( MD5), v závislosti od dostupnosti MD5 crypt(). PHP nastaví konštantu s názvom CRYPT_SALT_LENGTHčo označuje najdlhšiu platnú soľ povolenú dostupnými hashmi.

Štandardné založené na DES crypt() vráti soľ ako prvé dva znaky výstupu. Používa tiež iba prvých osem znakov str , takže dlhšie reťazce, ktoré začínajú rovnakými ôsmimi znakmi, vygenerujú rovnaký výsledok (keď sa použije rovnaká soľ).

V systémoch, kde funkcia crypt() podporuje viacero typov hash, sú nasledujúce konštanty nastavené na 0 alebo 1 v závislosti od toho, či je daný typ dostupný:

  • CRYPT_STD_DES- Štandardný hash založený na DES s dvojznakovou soľou z abecedy "./0-9A-Za-z". Použitie neplatných znakov v soli spôsobí zlyhanie crypt().
  • CRYPT_EXT_DES- Rozšírený hash založený na DES. „Soľ“ je 9-znakový reťazec pozostávajúci z podčiarknutia, za ktorým nasledujú 4 bajty počtu iterácií a 4 bajty soli. Tieto sú zakódované ako tlačiteľné znaky, 6 bitov na znak, najmenej významný znak ako prvý. Hodnoty 0 až 63 sú zakódované ako "./0-9A-Za-z". Použitie neplatných znakov v soli spôsobí zlyhanie crypt().
  • CRYPT_MD5- MD5 hašovanie s dvanásťznakovou soľou začínajúcou $1$
  • CRYPT_BLOWFISH- Blowfish hash so soľou takto: "$2a$", "$2x$" alebo "$2y$", dvojciferný parameter ceny, "$" a 22 znakov z abecedy "./0-9A- Za-z". Použitie znakov mimo tohto rozsahu v soli spôsobí, že crypt() vráti reťazec nulovej dĺžky. Dvojciferný parameter ceny je 2-základný logaritmus počtu iterácií pre základný hašovací algoritmus založený na Blowfish a musí byť v rozsahu 04-31, hodnoty mimo tohto rozsahu spôsobia zlyhanie crypt(). Verzie PHP staršie ako 5.3.7 podporujú len "$2a$" ako predponu soli: PHP 5.3.7 zaviedlo nové predpony na opravu bezpečnostnej slabiny v implementácii Blowfish. Úplné podrobnosti o bezpečnostnej oprave nájdete v časti, ale aby sme to zhrnuli, vývojári, ktorí sa zameriavajú iba na PHP 5.3.7 a novšie, by mali namiesto "$2a$" použiť "$2y$".
  • CRYPT_SHA256- SHA-256 hash so šestnástimi znakmi soli s predponou $5$. Ak reťazec soli začína reťazcom „rounds=
  • CRYPT_SHA512- SHA-512 hash so šestnásťznakovou soľou s predponou $6$. Ak reťazec soli začína reťazcom „rounds= $", číselná hodnota N sa používa na označenie, koľkokrát sa má vykonať hašovacia slučka, podobne ako parameter cost na Blowfish. Predvolený počet kôl je 5000, minimum je 1000 a maximum 999 999 999. Akýkoľvek výber N mimo tohto rozsahu bude skrátený na najbližší limit.

Od PHP 5.3.0 PHP obsahuje svoju vlastnú implementáciu a použije ju, ak systému chýba podpora pre jeden alebo viac algoritmov.

Parametre

Reťazec, ktorý sa má hašovať.

Pozor

Pomocou CRYPT_BLOWFISH algoritmu, bude mať za následok skrátenie parametra str na maximálnu dĺžku 72 znakov.

Voliteľný reťazec soli, na ktorom je hašovanie založené. Ak nie je uvedené, správanie je definované implementáciou algoritmu a môže viesť k neočakávaným výsledkom.

Návratové hodnoty

Vráti hašovaný reťazec alebo reťazec, ktorý je kratší ako 13 znakov a je zaručené, že sa bude líšiť od soli pri zlyhaní.

POZOR

Pri overovaní hesiel by sa mala použiť funkcia porovnávania reťazcov, ktorá nie je citlivá na útoky načasovania crypt() na predtým známy hash. Poskytuje PHP 5.6 a novší hash_equals() pre tento účel.

Denník zmien

Verzia Popis
5.6.5 Keď je reťazec zlyhania "*0" uvedený ako soľ, "*1" sa teraz vráti kvôli konzistencii s inými implementáciami kryptov. Pred touto verziou PHP 5.6 nesprávne vracalo DES hash.
5.6.0 Ak vynecháte soľ, zvýšte bezpečnostné varovanie E_NOTICE.
5.5.21 Keď je reťazec zlyhania "*0" uvedený ako soľ, "*1" sa teraz vráti kvôli konzistencii s inými implementáciami kryptov. Pred touto verziou PHP 5.5 (a staršie vetvy) nesprávne vracalo DES hash.
5.3.7 Pridané 2 x $ a $ 2 r $ Režimy Blowfish na riešenie potenciálnych útokov s vysokým bitom.
5.3.2 Pridané krypty SHA-256 a SHA-512 založené na implementácii Ulricha Dreppera.
5.3.2 Opravené správanie Blowfish pri neplatných kolách, aby sa vrátil reťazec „zlyhanie“ („*0“ alebo „*1“) namiesto toho, aby sa vrátilo späť na DES.
5.3.0 PHP teraz obsahuje vlastnú implementáciu pre algoritmy MD5 crypt, Standard DES, Extended DES a Blowfish a použije to, ak systému chýba podpora jedného alebo viacerých algoritmov.

Príklady

Príklad #1 crypt() príklady

$hashed_password = crypt("mojeheslo"); // nechať soľ automaticky vygenerovať

/* Všetky výsledky crypt() by ste mali odovzdať ako soľ na porovnanie a
heslo, aby sa predišlo problémom pri použití rôznych hashovacích algoritmov. (Ako
vyššie sa píše, že štandardné hašovanie hesla založené na DES používa 2-znakovú soľ,
ale hašovanie založené na MD5 používa 12.) */
if (hash_equals ($hashed_password , crypt ($user_input , $hashed_password ))) (
echo "Heslo overené!" ;
}
?>

Príklad #2 Použitie crypt() s htpasswd

// Nastavte heslo
$password = "moje heslo" ;

// Získajte hash, pričom soľ bude automaticky generovaná
$hash = crypt($heslo);
?>

Príklad č. 3 Použitie crypt() s rôznymi typmi hash

/* Tieto soli sú len príklady a nemali by byť použité doslovne vo vašom kóde.
Pre každé heslo by ste mali vygenerovať odlišnú, správne naformátovanú soľ.
*/
if (CRYPT_STD_DES == 1) (
echo "Štandardné DES: ". krypta ("rasmuslerdorf" , "rl" ) . "\n" ;
}

if (CRYPT_EXT_DES == 1 ) (
echo "Rozšírené DES: ". krypta ("rasmuslerdorf" , "_J9..rasm" ) . "\n" ;
}

if (CRYPT_MD5 == 1) (
echo "MD5: ". krypta ("rasmuslerdorf" , "$1$rasmusle$" ) . "\n" ;
}

if (CRYPT_BLOWFISH == 1 ) (
echo "Blowfish: ". crypt("rasmuslerdorf", "$2a$07$použite hlúpu strunu na soľ$"). "\n" ;
}

if (CRYPT_SHA256 == 1 ) (
echo "SHA-256: ". crypt("rasmuslerdorf", "$5$koly=5000$použite nejakú hlúpu strunu na soľ$"). "\n" ;
}

if (CRYPT_SHA512 == 1 ) (
echo "SHA-512: ". crypt("rasmuslerdorf", "$6$koly=5000$použite nejakú hlúpu strunu na soľ$"). "\n" ;
}
?>

Akékoľvek informácie môžu byť šifrované alebo dešifrované, vrátane použitia PHP. Tento jazyk má mnoho možností šifrovania údajov, od jednoduchých až po zložité.

Pozrime sa na základné metódy šifrovania

základ 64- umožňuje šifrovať a dešifrovať údaje pomocou algoritmu MIME base64. Nepoužíva kľúče a často sa používa na skrytie odkazov v PHP.

Príklady:
//zašifrovať text
$text = "Odkaz";
echo base64_encode($text); //Produkuje: PGEgaHJlZj0iIyI+0KHRgdGL0LvQutCwPC9hPg==
//dešifrovanie
echo base64_decode("PGEgaHJlZj0iIyI+0KHRgdGL0LvQutCwPC9hPg==");
?>

Ako vidíte, najprv sme použili operáciu base64_encode a dostali sme šifru: PGEgaHJlZj0iIyI+0KHRgdGL0LvQutCwPC9hPg== a potom ho nahradili do base64_decode a získali odkaz späť.

md5- umožňuje jednostranne hašovať údaje. To znamená, že na rozdiel od base64 ich už nebudete môcť dešifrovať späť. md5 sa často používa na ukladanie hesiel v databáze, ale v poslednej dobe je možné šifrovanú kombináciu md5 ľahko nájsť v dešifrovacích tabuľkách, ktoré láskavo poskytujú mnohé stránky a algoritmy. Preto na ukladanie hesiel md5 je lepšie nahradiť algoritmy Blowfish.

Príklad:

//zašifrovať text
echo md5("kombinácia");
?>

Šifrovanie kľúča

A posledný príklad šifrovania/dešifrovania, o ktorom som chcel hovoriť, používa kľúč (ako heslo). To znamená, že odošlete jedinečný kľúč do funkcie šifrovania a kód sa zašifruje spolu s ním. Na dešifrovanie musíte funkcii poskytnúť zašifrovaný kód a kľúč, ktorý poznáte len vy. Príklad použitia funkcií v spodnej časti kódu.

function __encode($text, $key) (



$enc_text=base64_encode(mcrypt_generic($td,$iv.$text));
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $enc_text; ))
funkcia strToHex($string) (
$hex="";
pre ($i=0; $i< strlen($string); $i++) { $hex .= dechex(ord($string[$i])); }
return $hex; )
function __decode($text, $key) (
$td = mcrypt_module_open("tripledes", "", "cfb", "");
$iv_size = mcrypt_enc_get_iv_size($td);
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
if (mcrypt_generic_init ($td, $key, $iv) != -1) (
$decode_text = substr(mdecrypt_generic($td, base64_decode($text)),$iv_size);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $decode_text; ))
funkcia hexToStr($hex) (
$string="";
pre ($i=0; $i< strlen($hex)-1; $i+=2) { $string .= chr(hexdec($hex[$i].$hex[$i+1])); }
return $string; )

$str = "Busy, ktoré je potrebné zašifrovať!
Podľa kľúča";
$code = strToHex(__encode($str, "My#key-do-36-simvolov"));
echo "Šifrovaný kód: ".$code."
";

$str = __decode(hexToStr($code), "My#key-do-36-simvolov");
echo "Dešifrovaný kód: ".$str."
";
?>

Obsah HTML môžete šifrovať. Dĺžka kľúča nesmie byť väčšia ako 36 znakov.

Túto metódu možno použiť na zašifrovanie niektorých údajov a ich umiestnenie do súboru txt alebo databázy a ich prijatie pomocou dešifrovania pomocou kľúča.

Samozrejme, každý kód sa dá dešifrovať/hacknúť a toto nie je výnimkou, preto používajte silné metódy šifrovania.

Jednou zo základných právd kryptografie je, že by ste v tejto oblasti nemali nič vymýšľať, pokiaľ nie ste profesionál. Čiastočne je to pravda, pretože všetko najlepšie bolo už dávno vynájdené, trpené a desaťročia používané v oblasti informačných technológií. Druhou stranou pravdy je, že k rozvoju určitej oblasti poznania dochádza len s neustálym prílevom nových nápadov a originálnych riešení do nej.

Z pochopiteľných dôvodov sa nezameriame na gigantov priemyselnej kryptografie ako AES, ale vrhneme sa takpovediac do vlastného kryptografického výskumu s blackjackom a radosťou.

Čiastočne preto, že je to zaujímavé, sčasti preto, že modelovaním niečoho vlastného a porovnaním s uznávanými štandardmi jasne vidíte kontrast, efektívne riešenia a úplné opomenutia a chápete, o čo sa môžete snažiť, aby ste zvýšili efektivitu.

Ale už dosť vody.

Povedzme, že naša webová aplikácia je napísaná v PHP, potrebuje reverzibilné šifrovanie a veríme, že dokážeme napísať vlastný šifrovací systém.

Napíšme teda náš vlastný reverzibilný šifrovací systém so súkromnými a verejnými kľúčmi, ktorý bude mať nasledujúce vlastnosti viac-menej bezpečného šifrovacieho algoritmu:

  1. Prítomnosť symbolov šumu v konečnej šifre.
  2. Informácie v každom kanáli odosielateľa budú zašifrované pomocou súkromného kľúča a funkcia zhody bude pre každý kľúč jedinečná.
  3. Každá správa dostane súhrnný kód – jedinečný kód, ktorý je funkciou súkromného kľúča a pôvodnej správy. Je to potrebné na dosiahnutie jedinečnosti funkcie párovania „zdrojového symbolu“.<=>kódovaný symbol“ nielen pre kanál „Odosielateľ – príjemca“, ale aj pre každú jednotlivú správu.

    Aj keď si teda predstavíme, že korešpondencia zakódovaných a pôvodných symbolov pre konkrétnu správu sa stala známou pomocou kryptografickej analýzy, napríklad frekvenčnej analýzy, nedáva to žiadne preferencie pri štúdiu inej správy.

  4. Aby sa frekvenčná analýza skomplikovala, zakódujeme každý počiatočný symbol správy dvoma šifrovými symbolmi.
Takže, čo sa stalo.

V skutočnosti môžete vidieť konečný výsledok

Trieda SymCoder zahŕňa metódy šifrovania a dešifrovania.

Šifrovanie sa vykonáva metódou code(), ktorá berie ako vstup pôvodnú správu.

Tu správa z vygenerovanej tabuľky korešpondencie v tab_coded vytvorí zašifrovanú správu, rozriedenú pozdĺž okrajov a vnútri so symbolmi šumu.

Mimochodom, symboly šumu sú jedinečné pre každý cieľový kanál odosielateľa, pretože sa generujú pomocou kľúča kanála, ale nie sú jedinečné pre správy. Symboly používané na šifrovanie v code_symbols sú niektoré interpunkčné znamienka a symboly ako %, @ atď.

Pre každý kódovaný symbol existujú dva symboly z code_symbols, z pochopiteľných dôvodov, že ich je niekoľkonásobne menej ako kódovaných symbolov.

Tabuľka korešpondencie create_tab_coded je vytvorená pomocou prekladu hash kľúča správy do poľa s počtom prvkov rovným počtu prvkov v poli symbolov kódu. Počiatočná pozícia pre prechod dvojznakových kódov je tiež vždy iná a je spojená s kanálovým kľúčom. To umožňuje mať istotu, že algoritmus na prechádzanie zakódovaných symbolov a priraďovanie kódových symbolov k nim bude vždy (alebo je zaručené, že bude často) odlišný.

Napríklad správa „ahoj svet“, keď je zakódovaná, vyzerá takto:

Digest-a00bf11d-&?==&!&?.@.@=!=-.?&1.#&?=:.:.1%!&-%@&@%~&1^#=?%% .!%+.?.~=?..&?%&&:%~.#%@&1&1.#=?.#.?.!&1==&=.-=!

A tu je rovnaká správa, znova zakódovaná:

Digest-a00bf11d-=:.?=:&!.?.1&-=:=?.?.=.?.!&=%!=-%@=!%~.=^#.1%%. !%+=:.~.@..==%&&1%~.1%@=?.@.!&=.!&@=:&1.==:=!.1&:

Je vidieť, že súhrn tej istej správy je rovnaký, ale šifra sa mení - symboly šumu sa pridávajú v ľubovoľnej zhode a v ľubovoľnom poradí pre každé nové šifrovanie.

Správy majú redundanciu, ktorá sa znižuje so zvyšujúcou sa hlasitosťou správy, až 10 % šumu (u najkratších správ dosahuje šum 90 % alebo viac percent), minimálna dĺžka zašifrovanej správy je 116 znakov. Jednou z nevýhod tejto metódy šifrovania je, že kódované správy sú minimálne zdvojené.

Dekódovanie spočíva v spätnom preklade tvaru „kódový symbol“ - pôvodný symbol so šumom vystrihnutým zo správy. Čo by mohlo byť kľúčom? V podstate akýkoľvek reťazec, ktorý je jedinečný pre každý pár cieľ-prijímač.

Napríklad, ak vytvárate messenger so šifrovaním správ, potom najjednoduchšia verzia súkromného kľúča môže byť md5($user_id_1. $soľ. $user_id_2), potom bude kľúč jedinečný pre každý kanál správ.

Povedzme, že si potrebujete vymieňať dáta medzi dvoma servermi. Na ochranu údajov pred odpočúvaním prevádzky sú údaje šifrované. Napríklad prenos akcií v rámci botnetu. Toto v podstate nie je šifrovanie, ale nazýva sa to kódovanie a na dekódovanie takéhoto kódu sa používajú známe funkcie.

Ako ďalší príklad pseudošifrovania uvediem príklad „šifrovania“ hesiel v databáze jedného CMS – tam heslá nie sú šifrované v md5() alebo , ale jednoducho kódované cez base64. Tie. Keď dôjde k úniku databázy, pre hackera nebude ťažké dešifrovať všetky heslá pomocou vstavanej funkcie PHP base64_decode().

Musíme prenášať údaje bez obáv, že niekto bude schopný zachytiť text a dešifrovať ho. PHP má populárny balík na šifrovanie údajov s názvom Mcrypt, ktorý poskytuje obojsmerné šifrovanie (to znamená skutočné šifrovanie a dešifrovanie údajov).

Mcrypt verzia 2.4.7 podporuje nasledujúce symetrické šifrovacie algoritmy: Blowfish, RC2, Safer-sk64 xtea, Cast-256, RC4, Safer-sk128, DES, RC4-iv, Serpent, Enigma, Rijndael-128, Threeway, Rijndael-192 , TripleDES, LOKI97, Rijndael-256, Twofish, Panama, Saferplus atď. Ďalšie podrobnosti o každom algoritme sú napísané na Wikipédii.

Keďže sa používa symetrické šifrovanie, kľúč musí byť známy obom stranám a musí byť uchovaný v tajnosti.

Príklad šifrovania a dešifrovania reťazca

mcrypt_module_open("des", "", "ecb", "")
Táto funkcia otvorí modul algoritmu a použitý režim. V tomto príklade je algoritmus DES v režime ECB.

$kľúč = substr($kľúč, 0, mcrypt_enc_get_key_size($td));
Maximálna veľkosť kľúča sa musí získať volaním funkcie mcrypt_enc_get_key_size() a každá hodnota menšia ako táto bude správna.

$s = mcrypt_generic($td, $zdroj);
Pri šifrovaní sú údaje vyplnené nula bajtov, aby sa zabezpečilo, že údaje budú dlhé n*bloky. Veľkosť bloku je určená algoritmom (pre DES je veľkosť bloku 64 bitov). Preto sa pri dešifrovaní môže na konci riadku objaviť „\0“, čo je odstránené funkciou trim()