PHP’de Güvenlik: Şifreleme (password_hash – password_verify) | Mustafa Zahid EFE
Merhabalar, Bu dersimde PHP'de şifrelemeden biraz bahsedeceğim. Genel olarak kullanıcıların şifreleri gibi hassas bilgileri saklarken md5 kullanıyoruz. Tek yönlü bir şifreleme algoritması olduğu güveniyoruz ve kullanıyoruz ama videoda da bahsettiğim gibi her zaman tam olarak güvenli olmuyor. Aslında bilgisayarda her zaman bir tam güvenlikten söz etmek çok zordur, burada benim bahsetmek istediğim şey sadece md5'ten daha güvenli bir şekilde işlem yapabileceğimiz. Şifreleme işlemini biraz daha güvenli yapabilmek için password_hash fonksiyonunu kullanacağız. Bu fonksiyon da aynı şekilde tek yönlü bir şekilde içerisine girdiğimiz veriyi şifreliyor. Bunun yanı sıra şifreleme için kullanacağımız işlem maliyetini belirtebiliyoruz. Bu işlem maliyeti de bizi bruteforce saldırılardan biraz daha fazla koruyor. Şu an tam olarak ifade edemediğimi düşünüyorum. Videoyu izleyerek bu olayı daha rahat bir şekilde anlayabilirsiniz. Bu yazıda sadece kullanımlarından bahsedeceğim. Öncelikle şifreleme işlemi için password_hash fonksiyonundan bahsedeyim. Daha sonra da nasıl şifrelerle doğrulama yapabileceğimizden bahsedeceğim. Password_hash fonksiyonumuz 3 parametre alıyor. Detaylı bilgileri php.net üzerindeki ilgili sayfadan inceleyebilirsiniz. http://nl1.php.net/manual/en/function.password-hash.php 3 parametremizi biraz açalım. Birinci parametremiz şifrelenecek verimiz. Buraya direkt olarak şifrelemek istediğimiz verimizi yazıyoruz. İkinci parametremiz kullanacağımız şifreleme algoritması. Şu an için bu parametreye sadece iki değer verebiliyoruz ve yine şu an için bu iki değer de aynı. Değerlerimizden biri PASSWORD_BCRYPT, bu parametreyi verdiğimiz zaman CRYPT_BLOWFISH algoritması kullanılarak verilerimiz şifreleniyor. İkinci değerimiz de PASSWORD_DEFAULT. Şu an için başka bir şifreleme algoritması PHP'de mevcut olmadığı için PASSWORD_DEFAULT değeri de CRYPT_BLOWFISH algoritmasını kullanıyor. Adından da anlaşılacağı gibi bu değerimiz zaten varsayılan değer. Bu değerin varoluş sebebi de ilerleyen zamanlarda PHP'de yeni ve daha güçlü bir şifreleme algoritması geliştirilirse bu algoritmayı kullanmayı sağlamak. Özellikle PASSWORD_BCRYPT kullanmak istiyorsanız bir şey diyemem ama aksi durumlarda PASSWORD_DEFAULT kullanmanızı tavsiye ederim. Son parametremizi de inceleyelim ve bu fonksiyonu bitirelim. Son parametremiz ayarlar parametresi ve dizi olarak değer alıyor. Burada iki tane ayarımız var, bunlar salt ve cost. Salt ayarı PHP 7.0'dan sonra önerilmemeye başlıyor. Bu yüzden bununla ilgilenmeyeceğiz. Şimdilik tek kullanacağımız ayar cost ayarı. Buna processing cost da diyebiliriz. Yani yapacağımız işlemin maliyeti. Buraya ne kadar büyük bir değer verirseniz şifreleme için o kadar çok kaynak harcanıyor bu da az önce bahsettiğim gibi bruteforce saldırılarından korunmanızı sağlıyor. Bu ayar için benim genel olarak kullandığım değer 12 siz daha düşük veya bilgisayarınızın gücü yeterse daha yüksek değerler verebilirsiniz. Yalnız unutmamanız gereken bir mesele var, buraya ne kadar büyük bir değer verirseniz şifreleme işleminiz o kadar uzun sürecektir. Örnek olarak cost ayarına 10 yazdığınız zaman şifreleme işlemini 8 saniyede yapıyorsa 12 yazdığınız zaman 12 saniyede yapacaktır (Verilen zaman değerleri tamamen temsilidir). Evet şimdi hemen örnek bir fonksiyon kullanımına ve sonucuna bakalım. Bu fonksiyon bize örnekte gördüğünüz gibi veriler döndürüyor. Başlangıçtaki $2y$ ifadesi kullandığımız şifreleme algoritmasını temsil ediyor. daha sonraki 12$ kısmı ise kullandığımız cost ayarını temsil ediyor. Şifrelerin doğruluğunu test ederken kullanacağımız password_verify fonksiyonu da zaten bunlara bakarak işlem yapıyor. Bu değerler olmasaydı eğer password_verify hangi şifreli veriyi hangi algoritmayla şifrelediğimizi bilemeyecek ve hepsini teker teker denemek zorunda kalacaktı ki bu da son derece saçma bir durum olurdu. Şimdi devam edelim. Bu şekilde şifreli verimizi elde ettikten sonra şimdi de bu şifremizi nasıl kontrol ettirebileceğimize bakalım. Şifrenin doğruluğunu kontrol etmek için de password_verify fonksiyonunu kullanacağız. Bu fonksiyonumuz da iki parametre alıyor. Birinci parametremiz doğruluğu test edilecek verimiz, ikinci parametremiz ise şifrelenmiş verimiz. Hemen bir örnek verelim. Burada gördüğünüz gibi kontrol edilecek verimiz için yanlış bir değer verirsek password_verify fonksiyonundan false dönüyor, eğer doğru şifreyi verirsek birinci parametresine bu durumda da true dönüyor.
Bazen şifrelenmiş veriyi değişkenlerden almak yerine direkt olarak string halinde vermek isteyebilirsiniz. Böyle durumlarda şifrelenmiş veriyi çift tırnaklar yerine tek tırnaklar içinde yazmanız gerekmektedir. Çünkü çift tırnak kullandığınız zaman şifreniz içerisinde $ karakteri geçtiği için şifrenizin bir bölümüne bir değişkenmiş gibi muamele edilecektir ve bu da doğal olarak doğru şifre girmiş olsanız bile false dönmesine sebep olacaktır.
Bu şekilde password_hash ve password_verify fonksiyonları ile daha güvenli bir şifreleme sağlayabilirsiniz. Bu yazımda anlatacaklarım bu kadar, eğer bir yanlışım, eksik anlattığım bir şey veya herhangi bir sorun varsa bunu Youtube üzerinden veya buradan yorumlar yoluyla iletebilirsiniz. Herkese iyi çalışmalar dilerim, görüşmek üzere.
Önceki Gönderi PHP’de Güvenlik: XSS’ten Korunmak (Cross Site Scripting)
Sonraki Gönderi PHP’de Güvenlik: Klasör Listeleme
Mehmet Ali Kayrak
6 November, 2016 @ 16:06 Yanıtla
Bi şifreleme için 8-12 saniye çok çok büyük bir süre. Hemde küçük, büyük bütün sistemler için büyük bir süre. Siz bunu kullanıyor musunuz ?
6 November, 2016 @ 16:10 Yanıtla
"(Verilen zaman değerleri tamamen temsilidir)" şeklinde bir ibare koydum oraya :) ve evet, kullanıyorum ama projeye göre yeri ve zamanıysa eğer kullanıyorum. Amacım sadece md5'ten farklı ve daha güvenli yöntemler olduğunu da göstermek.
6 November, 2016 @ 19:16 Yanıtla
Peki yeri ve zamanı olduğunu nasıl anlayabiliriz. Sormak istediğim aslında tam olarak bu.
6 November, 2016 @ 19:21 Yanıtla
Sitenize yaklasik kac kisinin girecegini tahmin edersiniz az cok. Ne kadar giris islemi yapilacak ? Bu yaptigimiz islem sunucunun ne kadar kaynagini tuketiyor, max kac kisi ayni anda giris yaparsa sunucu coker gibi sorulari sorun, sunucunuzun bilgilerini ve yaziliminizin harcadigi kaynaklara vs. bir goz atin. Daha sonra kullanmaniz durumunda cok problem cikmayacaksa kullanabilirsiniz. Bunun yerine ikili sifreleme de kullanabilirsiniz. Mesela sha1(md5()) gibi. Ama illa bunu kullanacagim diyorsaniz cost degerini biraz dusurup kullanabilirsiniz mesela. 12 yerine 10 yazarsiniz. Kendi projemden ornek vereyim, su an calistigim projede sadece yonetici girisi var, uyeler icin kayit ve giris sistemleri mevcut degil, ben bu durumda formumu da guvence altinda tutmak kaydiyla cost 12 vererek yonetici giris islemleri yapiyorum. Siz de projenizi inceleyin, benimki gibi sadece yonetici girisi varsa eger, uye girisi falan yoksa kullanabilirsiniz mesela. Ama ilk basta belirttigim gibi sunucunuzun ozellikleri ve sizin scriptinizin kullandigi kaynaklara bakmaniz en saglikli sonucu verecektir.
Mehmet Ali Kayrak için bir cevap yazın Cevabı iptal et