महत्वपूर्ण : जब तक आपके पास एक बहुत ही विशेष उपयोग-मामला है, पासवर्ड एन्क्रिप्ट न करें, इसके बजाय पासवर्ड हैशिंग एल्गोरिथ्म का उपयोग करें। जब कोई कहता है कि वे अपने पासवर्ड को सर्वर-साइड एप्लिकेशन में एन्क्रिप्ट करते हैं, तो वे या तो बिना सूचना के हैं या वे एक खतरनाक सिस्टम डिज़ाइन का वर्णन कर रहे हैं। सुरक्षित रूप से भंडारण पासवर्ड एन्क्रिप्शन से एक पूरी तरह से अलग समस्या है।
सूचित रहें। सुरक्षित सिस्टम डिजाइन करें।
PHP में पोर्टेबल डेटा एन्क्रिप्शन
यदि आप PHP 5.4 या नए का उपयोग कर रहे हैं और स्वयं क्रिप्टोग्राफी मॉड्यूल नहीं लिखना चाहते हैं, तो मैं एक मौजूदा लाइब्रेरी का उपयोग करने की सलाह देता हूं जो प्रमाणित एन्क्रिप्शन प्रदान करता है । मैंने जो लाइब्रेरी कनेक्ट की है, वह केवल उसी पर निर्भर करती है, जो PHP प्रदान करता है और कुछ मुट्ठी भर सुरक्षा शोधकर्ताओं द्वारा समय-समय पर समीक्षा की जाती है। (खुद शामिल हैं।)
यदि आपके पोर्टेबिलिटी लक्ष्य PECL एक्सटेंशन की आवश्यकता को नहीं रोकते हैं, तो libsodium को किसी भी चीज़ पर अत्यधिक अनुशंसित किया जाता है जिसे आप PHP में लिख सकते हैं।
अद्यतन (2016-06-12): आप अब PECL एक्सटेंशन स्थापित किए बिना ही सोडियम_कामपेट का उपयोग कर सकते हैं और समान क्रिप्टोकरंसी ऑफर का उपयोग कर सकते हैं ।
यदि आप क्रिप्टोग्राफी इंजीनियरिंग में अपना हाथ आजमाना चाहते हैं, तो पढ़ें।
सबसे पहले, आपको अनधिकृत एन्क्रिप्शन और क्रिप्टोग्राफिक डूम सिद्धांत के खतरों को जानने के लिए समय निकालना चाहिए ।
- एन्क्रिप्ट किए गए डेटा को अभी भी एक दुर्भावनापूर्ण उपयोगकर्ता द्वारा छेड़छाड़ किया जा सकता है।
- एन्क्रिप्ट किए गए डेटा का प्रमाणीकरण छेड़छाड़ को रोकता है।
- अनएन्क्रिप्टेड डेटा को प्रमाणित करने से छेड़छाड़ को रोका नहीं जा सकता है।
एन्क्रिप्शन और डिक्रिप्शन
PHP में एन्क्रिप्शन वास्तव में सरल है (हम उपयोग करने जा रहे हैं openssl_encrypt()
और openssl_decrypt()
एक बार जब आप अपनी जानकारी को एन्क्रिप्ट करने के तरीके के बारे में कुछ निर्णय लेते हैं, तो openssl_get_cipher_methods()
अपने सिस्टम पर समर्थित तरीकों की सूची के लिए परामर्श करें । सबसे अच्छा विकल्प सीटीआर मोड में एईएस है :
aes-128-ctr
aes-192-ctr
aes-256-ctr
वर्तमान में यह मानने का कोई कारण नहीं है कि एईएस कुंजी आकार के बारे में चिंता करने के लिए एक महत्वपूर्ण मुद्दा है (बड़ा शायद बेहतर नहीं है, 256-बिट मोड में खराब की-शेड्यूलिंग के कारण)।
ध्यान दें: हम उपयोग नहीं कर रहे हैं mcrypt
क्योंकि यह परित्याग है और इसमें अप्रकाशित कीड़े हैं जो सुरक्षा-प्रभावित हो सकते हैं। इन कारणों के कारण, मैं अन्य PHP डेवलपर्स को भी इससे बचने के लिए प्रोत्साहित करता हूं।
OpenSSL का उपयोग करके सरल एन्क्रिप्शन / डिक्रिप्शन रैपर
class UnsafeCrypto
{
const METHOD = 'aes-256-ctr';
/**
* Encrypts (but does not authenticate) a message
*
* @param string $message - plaintext message
* @param string $key - encryption key (raw binary expected)
* @param boolean $encode - set to TRUE to return a base64-encoded
* @return string (raw binary)
*/
public static function encrypt($message, $key, $encode = false)
{
$nonceSize = openssl_cipher_iv_length(self::METHOD);
$nonce = openssl_random_pseudo_bytes($nonceSize);
$ciphertext = openssl_encrypt(
$message,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$nonce
);
// Now let's pack the IV and the ciphertext together
// Naively, we can just concatenate
if ($encode) {
return base64_encode($nonce.$ciphertext);
}
return $nonce.$ciphertext;
}
/**
* Decrypts (but does not verify) a message
*
* @param string $message - ciphertext message
* @param string $key - encryption key (raw binary expected)
* @param boolean $encoded - are we expecting an encoded string?
* @return string
*/
public static function decrypt($message, $key, $encoded = false)
{
if ($encoded) {
$message = base64_decode($message, true);
if ($message === false) {
throw new Exception('Encryption failure');
}
}
$nonceSize = openssl_cipher_iv_length(self::METHOD);
$nonce = mb_substr($message, 0, $nonceSize, '8bit');
$ciphertext = mb_substr($message, $nonceSize, null, '8bit');
$plaintext = openssl_decrypt(
$ciphertext,
self::METHOD,
$key,
OPENSSL_RAW_DATA,
$nonce
);
return $plaintext;
}
}
उपयोग उदाहरण
$message = 'Ready your ammunition; we attack at dawn.';
$key = hex2bin('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f');
$encrypted = UnsafeCrypto::encrypt($message, $key);
$decrypted = UnsafeCrypto::decrypt($encrypted, $key);
var_dump($encrypted, $decrypted);
डेमो : https://3v4l.org/jl7qR
उपरोक्त सरल क्रिप्टो लाइब्रेरी अभी भी उपयोग करने के लिए सुरक्षित नहीं है। हमें डिक्रिप्ट को प्रमाणित करने और डिक्रिप्ट करने से पहले उन्हें सत्यापित करने की आवश्यकता है ।
नोट : डिफ़ॉल्ट रूप से, UnsafeCrypto::encrypt()
एक कच्चा बाइनरी स्ट्रिंग लौटाएगा। यदि आप इसे बाइनरी-सुरक्षित प्रारूप (बेस 64-एन्कोडेड) में संग्रहीत करना चाहते हैं, तो इसे इस तरह से कॉल करें:
$message = 'Ready your ammunition; we attack at dawn.';
$key = hex2bin('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f');
$encrypted = UnsafeCrypto::encrypt($message, $key, true);
$decrypted = UnsafeCrypto::decrypt($encrypted, $key, true);
var_dump($encrypted, $decrypted);
डेमो : http://3v4l.org/f5K93
सरल प्रमाणीकरण आवरण
class SaferCrypto extends UnsafeCrypto
{
const HASH_ALGO = 'sha256';
/**
* Encrypts then MACs a message
*
* @param string $message - plaintext message
* @param string $key - encryption key (raw binary expected)
* @param boolean $encode - set to TRUE to return a base64-encoded string
* @return string (raw binary)
*/
public static function encrypt($message, $key, $encode = false)
{
list($encKey, $authKey) = self::splitKeys($key);
// Pass to UnsafeCrypto::encrypt
$ciphertext = parent::encrypt($message, $encKey);
// Calculate a MAC of the IV and ciphertext
$mac = hash_hmac(self::HASH_ALGO, $ciphertext, $authKey, true);
if ($encode) {
return base64_encode($mac.$ciphertext);
}
// Prepend MAC to the ciphertext and return to caller
return $mac.$ciphertext;
}
/**
* Decrypts a message (after verifying integrity)
*
* @param string $message - ciphertext message
* @param string $key - encryption key (raw binary expected)
* @param boolean $encoded - are we expecting an encoded string?
* @return string (raw binary)
*/
public static function decrypt($message, $key, $encoded = false)
{
list($encKey, $authKey) = self::splitKeys($key);
if ($encoded) {
$message = base64_decode($message, true);
if ($message === false) {
throw new Exception('Encryption failure');
}
}
// Hash Size -- in case HASH_ALGO is changed
$hs = mb_strlen(hash(self::HASH_ALGO, '', true), '8bit');
$mac = mb_substr($message, 0, $hs, '8bit');
$ciphertext = mb_substr($message, $hs, null, '8bit');
$calculated = hash_hmac(
self::HASH_ALGO,
$ciphertext,
$authKey,
true
);
if (!self::hashEquals($mac, $calculated)) {
throw new Exception('Encryption failure');
}
// Pass to UnsafeCrypto::decrypt
$plaintext = parent::decrypt($ciphertext, $encKey);
return $plaintext;
}
/**
* Splits a key into two separate keys; one for encryption
* and the other for authenticaiton
*
* @param string $masterKey (raw binary)
* @return array (two raw binary strings)
*/
protected static function splitKeys($masterKey)
{
// You really want to implement HKDF here instead!
return [
hash_hmac(self::HASH_ALGO, 'ENCRYPTION', $masterKey, true),
hash_hmac(self::HASH_ALGO, 'AUTHENTICATION', $masterKey, true)
];
}
/**
* Compare two strings without leaking timing information
*
* @param string $a
* @param string $b
* @ref https://paragonie.com/b/WS1DLx6BnpsdaVQW
* @return boolean
*/
protected static function hashEquals($a, $b)
{
if (function_exists('hash_equals')) {
return hash_equals($a, $b);
}
$nonce = openssl_random_pseudo_bytes(32);
return hash_hmac(self::HASH_ALGO, $a, $nonce) === hash_hmac(self::HASH_ALGO, $b, $nonce);
}
}
उपयोग उदाहरण
$message = 'Ready your ammunition; we attack at dawn.';
$key = hex2bin('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f');
$encrypted = SaferCrypto::encrypt($message, $key);
$decrypted = SaferCrypto::decrypt($encrypted, $key);
var_dump($encrypted, $decrypted);
डेमो : कच्चा बाइनरी , बेस 64-एनकोडेड
यदि कोई इस SaferCrypto
पुस्तकालय का उत्पादन वातावरण में उपयोग करना चाहता है, या आपकी स्वयं की अवधारणाओं को लागू करना है, तो मैं दृढ़ता से आपके निवासी क्रिप्टोग्राफ़रों तक पहुंचने से पहले आपको एक दूसरी राय देने की सलाह देता हूं। वे आपको उन गलतियों के बारे में बता पाएंगे, जिनके बारे में मुझे पता भी नहीं होगा।
एक प्रतिष्ठित क्रिप्टोग्राफी लाइब्रेरी का उपयोग करके आप बहुत बेहतर होंगे ।