عوده للمواضيع <<

كيف تقوم البنوك الالكترونية والمواقع الحكومية بتشفير بياناتها بواسطة PHP



السلام عليكم ورحمة الله وبركاته



يوجد العديد من البنوك الالكترونية والمواقع الحكومية على الانترنت,هذه المواقع من أول وأهم الأشياء التى تهتم بها هى تأمين بيانات عملاءها او البيانات المخزنه بها.

انطلاقا من هذه المقدمه البسيطه سنتحدث عن الطريقه التى تستخدمها هذه المواقع فى تشفير وتأمين بيانها فى حالة كانت هذه المواقع مبرمجه بلغة PHP .

نبدأ على بركة الله .......

يوجد فى PHP مكتبات برمجية مدمجه يمكن استخدمها لتشفير البيانات بطريقه يصعب او بل من المستحيل كسرها ,هذه المكتبات تعتمد على لوغاريثميات تشفير معقده يصعب كسرها,وهنا لا أقصد بذلك الدوال العاديه مثل md5 وما شابهها,بل هنا أتحدث ما أهو أكبر من ذلك بكثير..........

ومكتبات التشفير المتاح استخدمها لتشفير البيانات فى PHP هى:





من أكثر المكتبات استخداما من المكتبات السابقه هى مكتبتى mcrypt و openssl ,ولان openssl غير متاحه للكل,فسوف أتحدث عن المكتبه الاكثر استخداما وهى مكتبة mcrypt


مكتبة mcrypt :هى مكتبة تشفير للبيانات موجوده تلقائيا فى php ,وهى من أشهر وأقوى مكتبات تشفير البيانات ,وتستخدمها معظم المواقع الحكومية والبنوك الالكترونية فى تشفير البيانات

دعونا نعرف التسلسل المطلوب منا لنتعلم استخدام مكتبة mcrypt:

1-تعريف المصطلحات المستخدمه فى علم التشفير cryptography
2-شرح دوال مكتبة mcrypt
3-مثال عملى لتشفير باسورد بmcrypt وتخزينها فى قاعدة البيانات
4-مثال عملى لعكس تشفير الباسورد المشفر واستخراج قيمته الاصلية
5-كلاس كاملة تستخدم فى تشفير وعكس تشفير البيانات بواسطة mcrypt



اولا:تعريف المصطلحات المستخدمه فى علم التشفير cryptography :
فى علم التشفير ,يوجد مصطلحات ومفاهيم مهمه ,لابد أن تعرفها وتفهمها حتى تستوعب كل ما يخص تشفير البيانات,وهذه المصطلحات هى كالاتى:

-Hashing:هو تحويل جملةاوكلمة إلى طول ثابت من الأرقام او الاحرف,هذه الحروف او الارقام تمثل الجملة او الكلمة,وتكون أقصر فى طولها من الجملة او الكلمة ,وتستخدم كدلاله للجملة او الكلمة الاصليه .
مثال:اذا أردنا عمل هاشنج hashing لكلمة advphp باستخدام دالة md5 ,فأن ستنتج الهاش الاتى :80ce67a823ca15b3b8c7b4c0ae055505
الهاش السابق يمثل كلمة advphp ,وهو طول ثابت(32)من حروف وأرقام يمثل الكلمة الاصلية
-salt:هو جملة عشوائيه من الحروف والارقام تضاف بجانب hash ,ليكون مميز,وليمنع التكرار فى حال كان هناك فى قاعدة البيانات أكثر من عضو لهم نفس الباسورد
مثال:فرضا ان لدينا العضو محمد وباسورد عضويته هو advphp ,ولدينا العضو أحمد,وباسورد عضويته هو advphp ,وفرضا اننا نريد جلب بيانات العضو محمد اعتمادا على باسورده,فى هذه الحاله سنجد ان هناك مشكلة ,وهو تكرار الباسورد للعضو أحمد ومحمد ,وهذا سيمنع جلب لبانات العضو محمد .

لذا,جاء salt ليضاف بجانب hash ليحل هذه المشكله ,والsalt يمكن توليده بأى داله تولد أرقام او أحرف عشوائيه مثل دالة crypt او uniqid

وأيضا من فوائد salt ,انه يجعل من عملية تخمين الباسورد المشفر أصعب,لانه يعطى احتماليات أكبر وأكثر تعقيدا ,فى حال أراد مخترق فك تشفير الباسورد.......

-key:المفتاح هو قيمة المتغير التى ترفق لجملة غيرمشفره لتوليد جمله مشفره او فك تشفير هذه الجمله,وسمى بالمفتاح,لانه قيمة هذا المتغير هى المفتاح التى بواسطتها ستقوم بتشفير الجملة,وأيضا هى المفتاح الذى سيفك هذا التشفير
مثال:فلنفرض ان لدينا باسورد اسمه advphp_pass ,وله مفتاح اسمه since2001 ,وعند دمج هذا المفاح الثابت لهذا الباسورد لانتاج باسورد مشفر سيخزن فى قاعدة البيانات,هذا المفتاح لابد ان تملك قيمته حتى تستطيع ارجاع هذا الباسورد المشفر لقيمته الاصليه,ومن هنا جاءت أهمية المفتاح .

-cipher:الشفره,وهى طريقة تشفير البيانات,او اللوغاريثميه التى تستخدم لتشفير البيانات,وفى علم التشفير cryptography,لوغاريثميات تشفير البيانات متعدده ومختلفه وسأذكر أشهر وأهم اللوغاريثميات لتشفير البيانات ,وهى كالاتى:
1-RIJNDAEL:الأشهر والأكثر استخداما,ويوجد نوعان من هذه اللوغاريثميه 128,256
2-BLOWFISH
3-RSA:وهى اختصار لجملة RIVEST-SHAMIR-ADLEMAN وهم مؤلفى هذه اللوغاريثميه
4-DES:وهى اختصار ل Data Encryption Standard




-initialization vector :واختصاره IV ,وهو متجه بداية التشفير,عباره عن جمله عشوائيه يتم توليدها بجانب المفتاح المشفر لمنع تكرار التشفير ولتصعيب كسر الشفره,

-CBC:وهى اختصار لجملة cipher block chaining ,ويقصد بها تكسير الشفره الناتجه لاجزاء وربط كل جزء ب initialization vector خاص بها,ويتم ربطهم فى النهايه سويا,لتنتج الكلمة المشفره المطلوبه,والغرض منها أيضا من الأساليب التى تضيف صعوبة لعملية فك التشفير او كسره.


بهيك ,نكون انتهينا من فهم المصطلحات المطلوب فهمها فى علم التشفير .......


ثانيا:شرح دوال مكتبة mcrypt :
يوجد فى مكتبة mcrypt دوال كثيره ومتعدده,سأشرح أهمهما ,والتى سنستخدمها فى برمجياتنا.....

1-()mcrypt_create_iv :تقوم هذه الداله بإنتاج initialization vector من مصدر عشوائى
الصيغه العامه:

mcrypt_create_iv(size in bytes,source of generation of random number)


حيث:
size in bytes :حجم IV
source of generation : المصدر او الملف الذى سيولد IV


2-()mcrypt_get_iv_size : العوده بحجم IV المطلوب

الصيغه العامه:
mcrypt_get_iv_size(cipher,mode)

حيث:
cipher:هو طريقة التشفير وقد تكون MCRYPT_RIJNDAEL_128 ,MCRYPT_RIJNDAEL_256,MCRYPT_BLOWFISH
mode:وهو اعداد التشفير وقد يكون MCRYPT_MODE_CBC

الان نأخذ مثال عملى لاستخدام الدالتين السابقتين:
$iv = mcrypt_create_iv(
mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC),
MCRYPT_DEV_URANDOM
);

echo $iv;


والنتيجه كما بالصوره للIV الناتج :




3-()mcrypt_encrypt:وهى الدالة التى تقوم بتشفير النص
الصيغه العامه:
mcrypt_encrypt(cipher,key,data,mode)

حيث:
-cipher:هو طريقة التشفير
-key:المفتاح المطلوب ارفاقه
-data:النص المطلوب تشفيره
-mode:وهو اعداد طريقة التشفير

مثال عملى:
$key='advphpkey2010';
$string='arab coders project';
mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
hash('sha256', $key, true),
$string,
MCRYPT_MODE_CBC,
$iv
)



4-()mcrypt_decrypt:وهى دالة فك تشفير النص المشفر
الصيغه العامه:
mcrypt_decrypt(cipher,key,data,mode)


مثال عملى:
mcrypt_decrypt(
MCRYPT_RIJNDAEL_256,
hash('sha256', $key, true),
substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)),
MCRYPT_MODE_CBC,
$iv
)




وبهيك انتهينا من شرح أهم دوال مكتبة mcrypt ..........




ثالثا:مثال عملى لتشفير باسورد بmcrypt وتخزينها فى قاعدة البيانات

الكود:
$key = 'advphp';
$string = 'arab coders project'; // note the spaces
$iv = mcrypt_create_iv(
mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC),
MCRYPT_DEV_URANDOM
);

$encrypted = base64_encode(
$iv .
mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
hash('sha256', $key, true),
$string,
MCRYPT_MODE_CBC,
$iv
)
);



قم بتخزين قمية متغير encrypted$ فى قاعدة البيانات ليخزن الباسورد مشفرا



رابعا:مثال عملى لعكس تشفير الباسورد المشفر السابق واستخراج قيمته الاصلية

$data = base64_decode($encrypted);
$iv = substr($data, 0, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC));

$decrypted = rtrim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_256,
hash('sha256', $key, true),
substr($data, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC)),
MCRYPT_MODE_CBC,
$iv
),
"\0"
);



خامسا:كلاس كاملة تستخدم فى تشفير وعكس تشفير البيانات بواسطة mcrypt

/**
* A class to handle secure encryption and decryption of arbitrary data
*
* Note that this is not just straight encryption. It also has a few other
* features in it to make the encrypted data far more secure. Note that any
* other implementations used to decrypt data will have to do the same exact
* operations.
*
* Security Benefits:
*
* - Uses Key stretching
* - Hides the Initialization Vector
* - Does HMAC verification of source data
*
*/
class Encryption {

/**
* @var string $cipher The mcrypt cipher to use for this instance
*/
protected $cipher = '';

/**
* @var int $mode The mcrypt cipher mode to use
*/
protected $mode = '';

/**
* @var int $rounds The number of rounds to feed into PBKDF2 for key generation
*/
protected $rounds = 100;

/**
* Constructor!
*
* @param string $cipher The MCRYPT_* cypher to use for this instance
* @param int $mode The MCRYPT_MODE_* mode to use for this instance
* @param int $rounds The number of PBKDF2 rounds to do on the key
*/
public function __construct($cipher, $mode, $rounds = 100) {
$this->cipher = $cipher;
$this->mode = $mode;
$this->rounds = (int) $rounds;
}

/**
* Decrypt the data with the provided key
*
* @param string $data The encrypted datat to decrypt
* @param string $key The key to use for decryption
*
* @returns string|false The returned string if decryption is successful
* false if it is not
*/
public function decrypt($data, $key) {
$salt = substr($data, 0, 128);
$enc = substr($data, 128, -64);
$mac = substr($data, -64);

list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

if ($mac !== hash_hmac('sha512', $enc, $macKey, true)) {
return false;
}

$dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv);

$data = $this->unpad($dec);

return $data;
}

/**
* Encrypt the supplied data using the supplied key
*
* @param string $data The data to encrypt
* @param string $key The key to encrypt with
*
* @returns string The encrypted data
*/
public function encrypt($data, $key) {
$salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

$data = $this->pad($data);

$enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv);

$mac = hash_hmac('sha512', $enc, $macKey, true);
return $salt . $enc . $mac;
}

/**
* Generates a set of keys given a random salt and a master key
*
* @param string $salt A random string to change the keys each encryption
* @param string $key The supplied key to encrypt with
*
* @returns array An array of keys (a cipher key, a mac key, and a IV)
*/
protected function getKeys($salt, $key) {
$ivSize = mcrypt_get_iv_size($this->cipher, $this->mode);
$keySize = mcrypt_get_key_size($this->cipher, $this->mode);
$length = 2 * $keySize + $ivSize;

$key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);

$cipherKey = substr($key, 0, $keySize);
$macKey = substr($key, $keySize, $keySize);
$iv = substr($key, 2 * $keySize);
return array($cipherKey, $macKey, $iv);
}

/**
* Stretch the key using the PBKDF2 algorithm
*
* @see http://en.wikipedia.org/wiki/PBKDF2
*
* @param string $algo The algorithm to use
* @param string $key The key to stretch
* @param string $salt A random salt
* @param int $rounds The number of rounds to derive
* @param int $length The length of the output key
*
* @returns string The derived key.
*/
protected function pbkdf2($algo, $key, $salt, $rounds, $length) {
$size = strlen(hash($algo, '', true));
$len = ceil($length / $size);
$result = '';
for ($i = 1; $i <= $len; $i++) {
$tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
$res = $tmp;
for ($j = 1; $j < $rounds; $j++) {
$tmp = hash_hmac($algo, $tmp, $key, true);
$res ^= $tmp;
}
$result .= $res;
}
return substr($result, 0, $length);
}

protected function pad($data) {
$length = mcrypt_get_block_size($this->cipher, $this->mode);
$padAmount = $length - strlen($data) % $length;
if ($padAmount == 0) {
$padAmount = $length;
}
return $data . str_repeat(chr($padAmount), $padAmount);
}

protected function unpad($data) {
$length = mcrypt_get_block_size($this->cipher, $this->mode);
$last = ord($data[strlen($data) - 1]);
if ($last > $length) return false;
if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {
return false;
}
return substr($data, 0, -1 * $last);
}
}



الاستخدام:

للتشفير:

$e = new Encryption(MCRYPT_BlOWFISH, MCRYPT_MODE_CBC);
$encryptedData = $e->encrypt($data, 'key');



لفك التشفير:
$e2 = new Encryption(MCRYPT_BlOWFISH, MCRYPT_MODE_CBC);
$data = $e2->decrypt($encryptedData, 'key');