PHP एईएस एन्क्रिप्ट/डिक्रिप्ट




encryption cryptography (5)

यदि आप कोड की 15 लाइनों में हल करने योग्य कुछ के लिए भारी निर्भरता का उपयोग नहीं करना चाहते हैं , तो ओपनएसएसएल कार्यों में निर्मित का उपयोग करें। अधिकांश PHP इंस्टॉलेशन ओपनएसएसएल के साथ आते हैं, जो PHP में तेज़, संगत और सुरक्षित एईएस एन्क्रिप्शन प्रदान करता है। खैर, यह तब तक सुरक्षित है जब तक आप सर्वोत्तम प्रथाओं का पालन कर रहे हों।

निम्नलिखित कोड:

  • सीबीसी मोड में एईएस 256 का उपयोग करता है
  • अन्य एईएस कार्यान्वयन के साथ संगत है, लेकिन mcrypt नहीं है , क्योंकि mcrypt PKCS # 7 के बजाय PKCS # 5 का उपयोग करता है।
  • SHA256 का उपयोग करके प्रदत्त पासवर्ड से एक कुंजी उत्पन्न करता है
  • अखंडता जांच के लिए एन्क्रिप्टेड डेटा का एक एचएमएसी हैश उत्पन्न करता है
  • प्रत्येक संदेश के लिए एक यादृच्छिक चतुर्थ उत्पन्न करता है
  • चतुर्थ (16 बाइट्स) और हैश (32 बाइट्स) को सिफरटेक्स्ट में प्रीपेड करता है
  • बहुत सुरक्षित होना चाहिए

चतुर्थ एक सार्वजनिक जानकारी है और प्रत्येक संदेश के लिए यादृच्छिक होने की आवश्यकता है। हैश यह सुनिश्चित करता है कि डेटा में छेड़छाड़ नहीं हुई है।

function encrypt($plaintext, $password) {
    $method = "AES-256-CBC";
    $key = hash('sha256', $password, true);
    $iv = openssl_random_pseudo_bytes(16);

    $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
    $hash = hash_hmac('sha256', $ciphertext, $key, true);

    return $iv . $hash . $ciphertext;
}

function decrypt($ivHashCiphertext, $password) {
    $method = "AES-256-CBC";
    $iv = substr($ivHashCiphertext, 0, 16);
    $hash = substr($ivHashCiphertext, 16, 32);
    $ciphertext = substr($ivHashCiphertext, 48);
    $key = hash('sha256', $password, true);

    if (hash_hmac('sha256', $ciphertext, $key, true) !== $hash) return null;

    return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
}

उपयोग:

$encrypted = encrypt('Plaintext string.', 'password'); // this yields a binary string

echo decrypt($encrypted, 'password');
// decrypt($encrypted, 'wrong password') === null

मुझे PHP में एन / डीकोडिंग तारों के लिए एक उदाहरण मिला। सबसे पहले यह बहुत अच्छा लग रहा है लेकिन यह काम नहीं करेगा :-(

क्या कोई जानता है कि परेशानी क्या है?

$Pass = "Passwort";
$Clear = "Klartext";

$crypted = fnEncrypt($Clear, $Pass);
echo "Encrypted: ".$crypted."</br>";

$newClear = fnDecrypt($crypted, $Pass);
echo "Decrypted: ".$newClear."</br>";

function fnEncrypt($sValue, $sSecretKey) {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, $sDecrypted, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));
}

function fnDecrypt($sValue, $sSecretKey) {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sEncrypted), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}

परिणाम है:

एन्क्रिप्टेड: boKRNTYYNp7AiOvY1CidqsAn9wX4ufz/D9XrpjAOPk8=

—‚(ÑÁ ^ yË~F'¸®Ó–í œð2Á_B‰Â— : —‚(ÑÁ ^ yË~F'¸®Ó–í œð2Á_B‰Â—


यदि आप MCRYPT_RIJNDAEL_128 का उपयोग कर रहे हैं, तो rtrim($output, "\0\3") आज़माएं। यदि स्ट्रिंग की लंबाई 16 से कम है, तो डिक्रिप्ट फ़ंक्शन 16 वर्णों की लंबाई के साथ एक स्ट्रिंग लौटाएगा, अंत में 03 जोड़ देगा।

आप आसानी से यह जांच सकते हैं, उदाहरण के लिए कोशिश कर रहा है:

$string = "TheString";
$decrypted_string = decrypt_function($stirng, $key);

echo bin2hex($decrypted_string)."=".bin2hex("TheString");

जानकारी के लिए MCRYPT_MODE_ECB IV (प्रारंभिक वेक्टर) का उपयोग नहीं करता है। ईसीबी मोड आपके संदेश को ब्लॉक में विभाजित करता है और प्रत्येक ब्लॉक अलग से एन्क्रिप्ट किया जाता है। मैं वास्तव में इसकी सिफारिश नहीं की है

प्रत्येक संदेश अद्वितीय बनाने के लिए सीबीसी मोड IV का उपयोग करता है। सीबीसी की सिफारिश की जाती है और ईसीबी के बजाय इस्तेमाल किया जाना चाहिए।

उदाहरण :

<?php
$password = "myPassword_!";
$messageClear = "Secret message";

// 32 byte binary blob
$aes256Key = hash("SHA256", $password, true);

// for good entropy (for MCRYPT_RAND)
srand((double) microtime() * 1000000);
// generate random iv
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);


$crypted = fnEncrypt($messageClear, $aes256Key);

$newClear = fnDecrypt($crypted, $aes256Key);

echo
"IV:        <code>".$iv."</code><br/>".
"Encrypred: <code>".$crypted."</code><br/>".
"Decrypred: <code>".$newClear."</code><br/>";

function fnEncrypt($sValue, $sSecretKey) {
    global $iv;
    return rtrim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, $sValue, MCRYPT_MODE_CBC, $iv)), "\0\3");
}

function fnDecrypt($sValue, $sSecretKey) {
    global $iv;
    return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sValue), MCRYPT_MODE_CBC, $iv), "\0\3");
}

आपको प्रत्येक संदेश को डीकोड करने के लिए IV को स्टॉक करना होगा (IV गुप्त नहीं हैं)। प्रत्येक संदेश अद्वितीय है क्योंकि प्रत्येक संदेश में एक अद्वितीय IV है।


कृपया एक मौजूदा सुरक्षित PHP एन्क्रिप्शन लाइब्रेरी का उपयोग करें

आमतौर पर अपने स्वयं के क्रिप्टोग्राफी लिखना एक बुरा विचार है जब तक कि आपको अन्य लोगों की क्रिप्टोग्राफी कार्यान्वयन को तोड़ने का अनुभव न हो।

यहां कोई भी उदाहरण सिफरटेक्स्ट को प्रमाणित नहीं करता है , जो उन्हें बिट-रीराइटिंग हमलों के लिए कमजोर छोड़ देता है।

यदि आप libsodium एक्सटेंशन इंस्टॉल कर सकते हैं, तो libsodium भी बेहतर है

<?php
// PECL libsodium 0.2.1 and newer

/**
 * Encrypt a message
 * 
 * @param string $message - message to encrypt
 * @param string $key - encryption key
 * @return string
 */
function safeEncrypt($message, $key)
{
    $nonce = \Sodium\randombytes_buf(
        \Sodium\CRYPTO_SECRETBOX_NONCEBYTES
    );

    return base64_encode(
        $nonce.
        \Sodium\crypto_secretbox(
            $message,
            $nonce,
            $key
        )
    );
}

/**
 * Decrypt a message
 * 
 * @param string $encrypted - message encrypted with safeEncrypt()
 * @param string $key - encryption key
 * @return string
 */
function safeDecrypt($encrypted, $key)
{   
    $decoded = base64_decode($encrypted);
    $nonce = mb_substr($decoded, 0, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($decoded, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');

    return \Sodium\crypto_secretbox_open(
        $ciphertext,
        $nonce,
        $key
    );
}    

फिर इसका परीक्षण करने के लिए:

<?php
// This refers to the previous code block.
require "safeCrypto.php"; 

// Do this once then store it somehow:
$key = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_KEYBYTES);
$message = 'We are all living in a yellow submarine';

$ciphertext = safeEncrypt($message, $key);
$plaintext = safeDecrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

इसका उपयोग किसी भी परिस्थिति में किया जा सकता है जहां आप क्लाइंट को डेटा पास कर रहे हैं (उदाहरण के लिए सर्वर-साइड स्टोरेज, एन्क्रिप्टेड यूआरएल पैरामीटर इत्यादि के बिना सत्रों के लिए एन्क्रिप्टेड कुकीज़) निश्चित रूप से उच्च स्तर की निश्चितता के साथ कि अंतिम उपयोगकर्ता समझदार या विश्वसनीय रूप से छेड़छाड़ नहीं कर सकता इसके साथ।

चूंकि libsodium क्रॉस-प्लेटफ़ॉर्म है , इसलिए यह PHP से संवाद करने में आसान बनाता है, जैसे जावा एप्लेट या मूल मोबाइल ऐप्स।

नोट: यदि आपको विशेष रूप से अपने ऐप में libsodium द्वारा संचालित एन्क्रिप्टेड कुकीज़ जोड़ने की आवश्यकता है, तो मेरे नियोक्ता पैरागोन इनिशिएटिव एंटरप्राइजेज Halite नामक लाइब्रेरी विकसित कर Halite जो यह सब आपके लिए करता है।


एईएस एन्क्रिप्शन के साथ ध्यान देने के लिए कुछ महत्वपूर्ण चीजें:

  1. एन्क्रिप्शन कुंजी के रूप में सादा पाठ का कभी भी उपयोग न करें। हमेशा सादा पाठ कुंजी हैश और फिर एन्क्रिप्शन के लिए उपयोग करें।
  2. एन्क्रिप्शन और डिक्रिप्शन के लिए हमेशा यादृच्छिक चतुर्थ (प्रारंभिक वेक्टर) का उपयोग करें। सही यादृच्छिकता महत्वपूर्ण है।
  3. जैसा ऊपर बताया गया है, ecb मोड का उपयोग न करें, इसके बजाय CBC उपयोग करें।






encryption-symmetric