Bu yazıda PHP şifreleme ve çözme yöntemlerini, hangi fonksiyonlar ile basit bir şekilde hem şifreleme hem de şifrelenmiş verilerin çözülmesinin yapılabileceğini ele alacağız.
Web siteleri içerisinde bazı veriler, özel
bilgiler şifrelenerek kullanılması gerekir. Kullanıcı girişi,
parolalar, e-ticaret gibi uygulamalar içerisinde şifreleme sıklıkla
kullanılır. Özel olarak şifreleme algoritmaları yazılabildiği
gibi PHP içerisinde hazır şifreleme fonksiyonları ile güvenlik
açıkları önemli ölçüde giderilebilir.
Bunlardan geriye dönüşü olmayan şifreleme fonksiyonları olduğu gibi şifreleme çözme (encrypt decrypt) işlemini yapan farklı tipte fonksiyonlarda bulunmakta. Bu makalede PHP güvenlik önlemleri için kullanılan bazı şifreleme ve şifre çözme fonksiyonlarının kullanımını göreceğiz.
PHP
Encrypt Decrypt Fonksiyonları
Veri güvenliği amacıyla belirli kurallar çerçevesinde verileri şifreleyen ve bu şifrelenen verileri çözen fonksiyonlardır. Gerekirse anahtar belirlenir ve bu anahtar üzerinden şifreleme gerçekleştirilir. Bu konunun en altında, bahsettiğim PHP şifreleme ve çözme fonksiyonlarının birleşimi olan ve daha güçlü şifreler üretmemize imkan sağlayan “encrypt_decrypt” isminde örnek bir fonksiyon yer almakta.
PHP openssl_encrypt ve openssl_decrypt
Fonksiyonları
Bilgileri belirtilen şifreleme yöntemi ve anahtar değeri ile
şifreler ve bu değerler doğrultusunda şifrelemiş olduğu veriyi
eski haline döndürür.
PHP openssl_encrypt ve openssl_decrypt kullanımı aşağıdaki gibidir. Dördüncü parametre “false” değeri girilir ise base64 tipinde şifreleme yapılacağı belirtilmiş olur.
$string = 'denemeYazi';
$encrypt_method = 'AES-256-CBC'; //sifreleme yontemi
$secret_key = '11*_33'; //sifreleme anahtari
$secret_iv = '22-=**_'; //gerekli sifreleme baslama vektoru
$key = hash('sha256', $secret_key); //anahtar hast fonksiyonu ile sha256 algoritmasi ile sifreleniyor
$iv = substr(hash('sha256', $secret_iv), 0, 16);
$sifrelendi = openssl_encrypt($string,$encrypt_method, $key, false, $iv);
echo $sifrelendi; //V55yt+eoXX8GE4/dhlda6Q==
echo '
';
$sifre_cozuldu = openssl_decrypt($sifrelendi,$encrypt_method, $key, false, $iv);
echo $sifre_cozuldu; //denemeYazi
PHP Base64 Fonksiyonu
Base64 fonksiyonu verileri base64 tipine dönüştürme ve çözme işlemini yapar. Veri güvenliği için kullanılabilir. PHP base64 fonksiyonu kullanımı aşağıdaki gibidir.
$sifrelendi = base64_encode($string);
echo $sifrelendi; //ZGVuZW1lWWF6aQ==
echo '
';
$sifre_cozuldu = base64_decode($sifrelendi);
echo $sifre_cozuldu; //denemeYazi
PHP gzcompress ve gzuncompress Fonksiyonu
PHP veri sıkıştırma, yazı sıkıştırma ve sıkıştırılan veriyi geriye döndürme işlemini yapan fonksiyonlardır. Dosya sıkıştırma da olduğu gibi verilerin boyutlarını küçültür. Veri güvenliği için de kullanılabilmektedir. PHP gzcompress ve gzuncompress fonksiyonu kullanımı aşağıdaki gibidir.
$string = 'denemeYazi';
$sifrelendi = gzcompress($string);
echo $sifrelendi;
echo '
';
$sifre_cozuldu = gzuncompress($sifrelendi);
echo $sifre_cozuldu; //denemeYazi
PHP serialize ve unserialize Fonksiyonu
Düz metin veya dizi tipindeki bir nesneyi kurallı string türünde
bir yapıya dönüştürmek için kullanılan fonksiyonlardır. Bir
diziyi serialize fonksiyonundan geçirip veritabanında saklayabilir,
veritabanından veriyi çekip unserialize fonksiyonundan geçirip
dizi haline getirerek kullanabiliriz.
Kısaca kendisine gelen değeri değiştirip eski haline getirebiliyor olmasından dolayı şifreleme için de yarar sağlar. Kullanımı aşağıdaki gibidir.
$string = 'denemeYazi';
$sifrelendi = serialize($string);
echo $sifrelendi; //s:10:"denemeYazi";
echo '
';
$sifre_cozuldu = unserialize($sifrelendi);
echo $sifre_cozuldu; //denemeYazi
PHP diziyi veritabanına kaydetme işlemi için de kullanılabilecek PHP serialize ve unserialize kullanımı aşağıdaki gibidir.
$dizi = array('birinci deger',1 => array('bir', 'iki'), 'ucuncu deger');
$sifrelendi = serialize($dizi);
echo $sifrelendi; //a:3:{i:0;s:13:"birinci deger";i:1;a:2:{i:0;s:3:"bir";i:1;s:3:"iki";}i:2;s:12:"ucuncu deger";}
echo '
';
$sifre_cozuldu = unserialize($sifrelendi);
print_r($sifre_cozuldu); //Array ( [0] => birinci deger [1] => Array ( [0] => bir [1] => iki ) [2] => ucuncu deger )
PHP urlencode ve urldecode Fonksiyonu
Post yapılırken veya url üzerinden veri taşıma işlemi
yapılırken adres satırında veriler düzenlenmiş halleriyle
taşınır. Böylelikle karakter sorunu olmaz, veriler adres
satırında sorunsuz bir şekilde barınır.
Bu yöntem ile PHP cookie kullanımı esnasında çerez içeriğinde veri saklamak için de kullanılabilir. Urlencode ile karakter sorunu olmaksızın veriyi url formatta saklanabilecek hale dönüştürür, urldecode ile bu düzenlenmiş veriyi eski haline getirebiliriz.
Bir değeri dönüştürüp sonrasında eski haline getirme işlemi yapılabildiğinden dolayı urlencode ve urldocode fonksiyonlarını şifreleme için kullanabiliriz. Kullanımı aşağıdaki gibidir.
$string = 'deneme Yazısı';
$sifrelendi = urlencode($string);
echo $sifrelendi; //deneme+Yaz%C4%B1s%C4%B1
echo '
';
$sifre_cozuldu = urldecode($sifrelendi);
print_r($sifre_cozuldu); //deneme Yazısı
Yukarıdaki fonksiyonları kullanarak karışık bir PHP şifreleme fonksiyonu oluşturalım. Böylelikle çok daha güçlü şifrelenmiş veriler oluşturulabilir.
$string = 'deneme Yazısı';
function encrypt_decrypt($action, $string) {
$output = false;
$encrypt_method = 'AES-256-CBC'; //sifreleme yontemi
$secret_key = '13456'; //sifreleme anahtari
$secret_iv = '**445'; //gerekli sifreleme baslama vektoru
$key = hash('sha256', $secret_key); //anahtar hast fonksiyonu ile sha256 algoritmasi ile sifreleniyor
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if( $action == 'encrypt' ) {
$output = urlencode(serialize(base64_encode(gzcompress(openssl_encrypt($string,$encrypt_method, $key, 0, $iv)))));
}
else if( $action == 'decrypt' ){
$output = openssl_decrypt(gzuncompress(base64_decode(unserialize(urldecode($string)))),$encrypt_method, $key, 0, $iv);
}
return $output;
}
$sifrelendi = encrypt_decrypt('encrypt',$string); //metin sifrelendi - encrypt
echo $sifrelendi; //s%3A44%3A%22eJwrLzFwLjOq9PEsizLwTitOTS3Jy80LtLUFAGr5CIs%3D%22%3B
echo '
--------------------------
';
$cozuldu = encrypt_decrypt('decrypt',$sifrelendi); //metin eski haline getirildi - decrypt
echo $cozuldu; //deneme Yazısı
Sadece
Şifreleme Yapan Fonksiyonlar
Tek yönlü şifreleme yapan, geri dönüşü olmayan, şifre çözme işlemi yapmayan fonksiyonlardır.
PHP md5 Fonksiyonu
Tek taraflı metin şifreleme fonksiyonudur. Şifrelenecek olan metin fonksiyon içerisine parametre olarak verildiğinde md5 fonksiyonu bize 32 haneli şifrelenmiş bir veri döndürecektir.
Şifrelenmiş veri geriye döndürülemez yani decode edilemez. Ancak md5 ile şifrelenmiş veriler kırılabilir. Bu yüzden kullanıcı şifre verisi gibi önemli veriler md5 ile şifrelenecek ise şifrelenmeden önce bu veriler kolay bir şekilde oluşturulmamalı.
Ayrıca md5 fonksiyonu gibi daha başka şifreleme yöntemleri de bulunmakta. Bu şifreleme yöntemleri harmanlanarak daha güçlü bir şifreleme sistemi oluşturulabilir. PHP md5 fonksiyonu kullanımı aşağıdaki gibidir.
$degisken = 'şifrelenecek metin';
echo md5($degisken);
//çıktı: 0c66f5682ca9a81fbddf771ea4290f92
PHP sha1 Fonksiyonu
Sha1 fonksiyonu da md5 fonksiyonu gibi tek taraflı PHP metin şifreleme fonksiyonlarından biridir. Şifrelenecek metin sha1 fonksiyonu içerisine parametre olarak gönderilir ve geriye şifrelenmiş metni döndürür. PHP sha1 fonksiyonu kullanımı aşağıdaki gibidir.
$degisken = 'şifrelenecek metin';
echo sha1($degisken);
//çıktı: 05de89eea34ee8a43f54486edfb46c7fcc8b5465
PHP hash Fonksiyonu
Hash fonksiyonu kullanımı ile parametre olarak seçilen şifreleme algoritması üzerinden verinin şifrelenmesi sağlanır. 3 parametre alır, ilk parametre şifreleme algoritması, ikinci parametre şifrelenecek veri, üçüncü parametre varsayılan olarak “false” değerindedir. True değeri ile karışık binary format üzerinden veri döner.
hash_algos() fonksiyonu ile hash fonksiyonunda kullanılabilecek algoritmaları görebiliriz.
print_r(hash_algos());
/*
Array
(
[0] => md2
[1] => md4
[2] => md5
[3] => sha1
[4] => sha224
[5] => sha256
[6] => sha384
[7] => sha512/224
[8] => sha512/256
[9] => sha512
[10] => sha3-224
[11] => sha3-256
[12] => sha3-384
[13] => sha3-512
[14] => ripemd128
[15] => ripemd160
[16] => ripemd256
[17] => ripemd320
[18] => whirlpool
[19] => tiger128,3
[20] => tiger160,3
[21] => tiger192,3
[22] => tiger128,4
[23] => tiger160,4
[24] => tiger192,4
[25] => snefru
[26] => snefru256
[27] => gost
[28] => gost-crypto
[29] => adler32
[30] => crc32
[31] => crc32b
[32] => fnv132
[33] => fnv1a32
[34] => fnv164
[35] => fnv1a64
[36] => joaat
[37] => haval128,3
[38] => haval160,3
[39] => haval192,3
[40] => haval224,3
[41] => haval256,3
[42] => haval128,4
[43] => haval160,4
[44] => haval192,4
[45] => haval224,4
[46] => haval256,4
[47] => haval128,5
[48] => haval160,5
[49] => haval192,5
[50] => haval224,5
[51] => haval256,5
)
*/
Hash fonksiyonu ile sha256 algoritması ile veri şifreleme aşağıdaki gibidir.
$string = 'deneme Yazısı';
echo hash('sha256',$string); //b88327d849d9d6fd75eb5d886feda5fd7d82f9604ea5c0037ce71138c5ffec25
PHP Crc32 Fonksiyonu
Crc yöntemi veri aktarımı veya saklanması
sırasında verilerin doğruluğunu kontrol edilmesidir. Crc32
fonksiyonu bu yöntem doğrultusunda verileri dönüştürür ve
geriye kısa boyutlu sayısal bir değer döndürür.
PHP veri güvenliği amacıyla verileri dönüştürme ve şifreleme için kullanılabilir ancak tek başına kullanılması güvenlik için yetersizdir. Crc32 fonksiyonu kullanımı aşağıdaki gibidir.
$string = 'deneme Yazısı';
echo crc32($string); //1283012827
PHP Crypt Fonksiyonu
PHP tek yönlü şifreleme yapan fonksiyonlardan biridir. İki parametre alır. İlk parametre şifrelenecek veri, ikinci parametre şifreleme algoritmasıdır. İkinci parametre kullanılmazsa sistemin varsayılan şifreleme algoritması üzerinden çalışır ve her çalıştığında rastgele 34 karakterlik şifreleme sonucu üretir, kullanılır ise sabit şifreleme sonucu üretir. PHP crypt fonksiyonu kullanımı aşağıdaki gibidir.
error_reporting(0);
$string = 'deneme Yazısı';
echo crypt($string).'
'; //$1$r1WEEmTY$GT08TxuVagWLDYbiOAoTa0
echo crypt($string).'
'; //$1$JZpbKF6r$4xjSOnTjN0635vXSwpMs41
if (CRYPT_STD_DES){
echo 'Standart DES Sifreleme: '.crypt($string, 'my')."
"; //mycSY7bYOGt9c
}
if (CRYPT_EXT_DES){
echo 'Gelismis DES Sifreleme: '.crypt($string, '_my..aman')."
"; //my..aman.vptMFPATHo
}
if (CRYPT_MD5){
echo 'MD5 Sifreleme: '.crypt($string, '$1$myaman$')."
"; //$1$myaman$WVV7q3rizAfD2y89ODNwG.
}
if (CRYPT_BLOWFISH) {
echo 'Blowfish Sifreleme: '.crypt($string, '$2a$07$muhammedyamanforsalt$')."
"; //$2a$09$mucahittopal.commucahe3JjKHHhZXG7aou/wuFa7luGy0kIt3s2
}
PHP Password_hash Fonksiyonu
PHP güvenli şifre oluşturma yöntemlerinden biridir ve hatta PHP tarafından önerilen şifreleme tekniğidir. Password_hash fonksiyonu ile bir metin şifrelendiğinde her zaman rastgele farklı bir sonuç üretilecektir. Sonuç her defasında değişse bile girilen değer ile şifrelenmiş metnin kıyaslanmasını password_verify fonksiyonu ile yapabileceğiz.
Password_hash
fonksiyonu ile şifreleme şu anda 4 farklı algoritma ile
yapılabilir. İleride bu algoritma sayısı artabilir.
- PASSWORD_DEFAULT – Varsayılan olarak bcrypt algoritmasını kullanır. Şifrelenen veri 60 karakter uzunluğunda olur. Ancak ileride yeni algoritmalar eklenebileceğinden varsayılan şifreleme algoritması değiştirilebilir. Bu yüzden veritabanında şifrelenen verinin saklanması durumunda bu ihtimali düşünerek veritabanı ayarlaması yapılması tavsiye edilir.
- PASSWORD_BCRYPT – CRYPT_BLOWFISH algritması üzerinden şifreleme yapılır. Crypt() fonksiyonu ile uyumludur ve bu şifrelemeye uygun şifreler üretilebilir. 60 karakter uzunluğunda şifrelenmiş veri türetir.
- PASSWORD_ARGON2I – Argon2i algoritmasını kullanır.
- PASSWORD_ARGON2ID – Argon2id algoritmasını kullanır.
3 parametre alır. İlk parametre şifrelenecek metin, ikinci parametre algoritma tipi, üçüncü parametre şifreleme işlemini yaparken ki işlemcinin yapacağı uğraşı seviyesidir. Yani metni şifrelemek için daha fazla uğraşmış ve şifrenin zorluğunu arttırmış oluyoruz. Ancak sunucunun performansına göre çıktı üretme süresi artabilir. Varsayılan değer 10‘dur ve 4 ile 31 arasında değer alabilir. PHP password_hash kullanımı aşağıdaki şekildedir.
$string = 'denemeSifre';
$sifrelendi = password_hash($string);
$sifrelendi = password_hash($string,PASSWORD_DEFAULT); //yukarıdaki kullanımla aynıdır
$sifrelendi = password_hash($string,PASSWORD_BCRYPT);
$ayar = [
'cost' => 4
];
$sifrelendi = password_hash($string,PASSWORD_BCRYPT, $ayar);
/*
Şifreleme sonucunda aynı metinden aşağıdaki gibi şifrelenmiş sonuçlar çıkacaktır:
$2y$10$n4rKgp1H14peIo4N9dbSRuIILDCloVzl3FlQGOjS7fS1tXkaBX2C.
$2y$10$T6cAV27Jn20moMI/ESnqjeMUJOOY5KziPY/NKA0fwZd421C8Bkc8G
$2y$10$Wd0aKitx3K5rlcTrjE22cepxwYECHImaOAyZut.rEHpdhOWcTw6kW
*/
$sifrelendi = password_hash($string,PASSWORD_ARGON2I); //$argon2i$v=19$m=1024,t=2,p=2$b0lVTDVhcHB2M1J3bzJtdg$4sk4DiIq6Sb8qsA+iaGj/tAI/oxC/UqC+xCWfZZMujM
Password_hash fonksiyonu ile şifrelenen veriyi kontrol etmek için password_verify() fonksiyonu kullanılır.
if (password_verify("denemeSifre", '$2y$10$lSaWeZJuHYKSTb/4.H6s2udov5xF7i3DWN26q4jeFUV/CWTJee5JS')){
echo 'dogru';
}else{
echo 'yanlis';
}
Şifrelenmiş veri ile ilgili bilgileri password_get_info() fonksiyonu ile dizi halinde öğrenebiliriz.
echo '';
print_r(password_get_info('$2y$04$UO.xr9XO.51VOT2DQLvLROJILSS/Z2Ku1owc3TmN4XdMl6s7UDrkS'));
echo '
';
/*
Array
(
[algo] => 1
[algoName] => bcrypt
[options] => Array
(
[cost] => 4
)
)
*/