Minulla on tällä hetkellä harjoitusprojekti työn alla, jossa tarkoituksena olisi suojata mahdollisimman hyvin tietokantaan kaikki henkilökohtainen ei-julkinen tieto.
Nyt pysähdyin vain miettimään, mikä olisi paras keino sijoittaa turvallisesti itse salausluokan avain? Suoraan luokan yhteyteen..?
Sijoita "perusavaimet" esim. vastaavasti kuin tietokantasi tunnukset (webbirootin ulkopuolelle jne. ettei niitä kukaan asiaton taho pääse lukemaan). Sitten jatko riippuu paljolti siitä miten sovelluksen tulee toimia. Onko kryptauksessa käytetty avain johdettu perusavaimen lisäksi esim. käyttäjän salasanasta/käyttäjänimestä tjms. käyttäjäkohtaisesta materiaalista?
Ja jos mahdollista (etkä halua tehdä tätä itse mielenkiinnosta alusta asti), niin käytä valmiita kirjastoja hoitamaan salaus (ja muu salaukseen liittyvä operointi). Ettei tule kämmiä toteutukseen liittyvissä asioissa.
Harjoituksen vuoksi tein salausluokan toki itse. Mcrypt tarjosi suoraan paketista lähes kaiken tarvitun. Ainut lisuke periaatteessa on URL-yhteensopiva base64 enkoodaus, jonka avulla saa luotua mm. turvallisen sähköpostitoimisen salasananpalautusmekanismin.
Salausavaimeen en lisännyt mitään käyttäjäkohtaista, sillä ajatuksena on, että esim. salatun sähköpostiosoitteen saisi tietokannasta vedettyä selkokieliseksi palvelimella sähköpostinlähetystä varten.
Ylimääräiset kikkailut itse avaimen kanssa tuntuvat siinä mielessä turhalta, että jos mikä tahansa suorittava skripta pääsee kuitenkin käsiksi tiedostoon, joka sisältää salasanat, pääsisi mahdollinen hyökkääjäkin sinne käsiksi esim. vähemmän turvallisen upload-skriptan tmv. kautta. Kai tuo webbirootin ulkopuolelle sijoittaminen lienee se ainut asia, mitä järkevällä vaivalla voinee tehdä?
Laitan vielä tähän pienen listan mitä voi käyttää lähtökohtana kun implementoit symmetristä salausta:
Käytä AES:ia, 128-bittinen avain on hyvä vaihtoehto. Luo avaimet satunnaislukugeneraattorilla. Jos tarpeellista, huolehdi avaimien kierrätyksestä (vaihdat avaimia tarpeen mukaan).
Käytä AES:ia CBC-moodissa.
Tätä varten tarvitset vahvan satunnaislukugeneraattorin (/dev/urandom tjms) kun luot IV:itä. Tällä samaisella satunnaislukugeneraattorilla voit luoda kryptaus- ja autentikointiavaimet.
Autentikoi salattu materiaali kokonaisuudessaan HMAC-SHA-256:lla, ns. "Encrypt-then-MAC". HMACin tulee kattaa IV jne. mikä tahansa muu operaatioon liittyvä tieto, esim. mahdolliset versiotieto, aikaleimat... Käytä HMACin kanssa omaa avainta (ei siis samaa kuin kryptatessa). Salausta purkaessa HMACeja tulee verrata "vakioajan ottavalla vertailulla", eli "constant-time string comparison", jotta et vuoda aikainformaatiota HMACissa olevien tavujen suhteen.
Avaimista huomiona, että tämä mitä yllä kuvasin, pätee "yhden suunnan" salaukseen. Jos olisi tilanne missä dataa lähetetään esim. kahden eri pisteen välillä salattuina molempiin suuntiin, niin omat avaimet tulisi olla käytössä A->B ja B->A.
Sellainen on kanssa hyvä tiedostaa, vaikka se ei käytännössä ongelmaksi tuleekaan, että CBC-moodissa älä salaa dataa samalla avaimella enempää kuin luokkaa 2^32 blokkia (AES:n blokkikoko on 128 bittiä).
Ja vielä tällaisena yleisenä huomiona, poista avaimiin liittyvä data jne. aina muistista heti kun et kyseistä muuttujaa enää tarvitse.
kayttaja-1634 kirjoitti:
Ylimääräiset kikkailut itse avaimen kanssa tuntuvat siinä mielessä turhalta, että jos mikä tahansa suorittava skripta pääsee kuitenkin käsiksi tiedostoon, joka sisältää salasanat, pääsisi mahdollinen hyökkääjäkin sinne käsiksi esim. vähemmän turvallisen upload-skriptan tmv. kautta. Kai tuo webbirootin ulkopuolelle sijoittaminen lienee se ainut asia, mitä järkevällä vaivalla voinee tehdä?
Tuo on hieman kinkkistä. Jos avaimeen vaaditaan esim. käyttäjän salasana, niin hyökkääjä ei tätä välttämättä tiedä tai edes saa haltuunsa (aktiivisenkaan hyökkäyksen aikana), vaikka hän pystyisi ajamaan omaa php-koodiaan palvelimellasi. Miinuksena sitten tietysti että sinäkään et pääse käsiksi tähän dataan (datan saa saataville vain käyttäjän kirjautumisen yhteydessä tjms).
Tällä hetkellä minulla on tuossa salauksessa käytössä Twofish 256-bittisellä satunnaisella avaimella CBC-modella ja randomit kiskon mcrypt_dev_urandomista. Tämän nykyisen systeemin idea olisikin lähinnä toimia ainakin nykyisellään vain sähköpostiosoitteen suojaamisessa tietokantaan ja ne tulisi aina tarvittaessa palauttaa palvelimella selkokieliseen muotoon. Tässä ei tiettävästi siis pitäisi olla uhkaa esim. tuosta aikavertailusta.
Toinen käyttötarkoitus oli tosiaan luoda mm. salasananuusimis ja aktivointilinkkejä sähköpostiin. Tässä ajattelin hyödyntää useita eri käyttäjää yksilöiviä tietoja -- myös salausavaimessa. Pitäisi estää kaikenlaisten välihyökkäystenkin toteutuminen.
Kiitos noista muistakin vinkeistä -- ei ole aiemmin osunut silmään esimerkiksi tuo aikavertailuheikkous.
kayttaja-1634 kirjoitti:
Tällä hetkellä minulla on tuossa salauksessa käytössä Twofish 256-bittisellä satunnaisella avaimella CBC-modella ja randomit kiskon mcrypt_dev_urandomista. Tämän nykyisen systeemin idea olisikin lähinnä toimia ainakin nykyisellään vain sähköpostiosoitteen suojaamisessa tietokantaan ja ne tulisi aina tarvittaessa palauttaa palvelimella selkokieliseen muotoon. Tässä ei tiettävästi siis pitäisi olla uhkaa esim. tuosta aikavertailusta.
Vaikka Twofishissä ei varmastikaan mitään vikaa ole, suosittelen silti pysymään standardissa eli AES:issa (ellei jotain painavaa syytä ole tehdä toisin).
Tuosta "aikavuodosta" ei välttämättä suoranaisesti ole haittaa kuvaamassasi tapauksessa, mutta kannattaa koittaa kartoittaa kaikki mahdolliset ja miksei mahdottomatkin skenaariot mihin hyökkääjä voi pyrkiä. Ja jos tuosta aikavuodosta tulee ongelma jossain tällaisessa tilanteessa, on se silloin syytä eliminoida. Pääpiirteittäin se tulisi eliminoida ainakin silloin, kun dataa otetaan vastaan ulkopuolelta järjestelmään (esim. MAC:in tarkistus). Mutta sekin on muistettava, että vaikka hyökkääjä ei speksauksen mukaan pääsisikään syöttämään dataansa järjestelmääsi, niin näin voi silti käydä jos joku toinen osa järjestelmästäsi pettää tjms.
kayttaja-1634 kirjoitti:
Toinen käyttötarkoitus oli tosiaan luoda mm. salasananuusimis ja aktivointilinkkejä sähköpostiin. Tässä ajattelin hyödyntää useita eri käyttäjää yksilöiviä tietoja -- myös salausavaimessa. Pitäisi estää kaikenlaisten välihyökkäystenkin toteutuminen.
En ole ihan varma mitä tarkoitit "välihyökkäyksillä", mutta uskoisin että tuollaisessa tilanteessa et tarvitse salausta lainkaan. Luot ihan vaan satunnaislukugeneraattorilla esim. 128 bittiä dataa ja tämä toimii aktivointiparametrina?
kayttaja-1634 kirjoitti:
Kiitos noista muistakin vinkeistä -- ei ole aiemmin osunut silmään esimerkiksi tuo aikavertailuheikkous.
Eipä kestä, nuo ovat sellaisia juttuja mitkä menevät helposti metsään jos esim. php.net:in dokumentaatiota seuraamalla hommia hoitaa. Ehkä tuon voisi katsoa olevan samaa sarjaa "Schneierin lain" kanssa (ts. melko harva itse keksii tuollaista merkkijonovertailun ongelmaa pohtia tai tiedostaa):
Anyone, from the most clueless amateur to the best cryptographer, can create an algorithm that he himself can't break.
Aihe on jo aika vanha, joten et voi enää vastata siihen.