php mcrypt को हटा दिया गया है, विकल्प क्या है?




encryption passwords (8)

phpseclib का शुद्ध-PHP कार्यान्वयन संगीतकार पैकेज के रूप में उपलब्ध phpseclib साथ मौजूद है और PHP 7.3 (मेरे द्वारा परीक्षण) पर काम करता है।

Phpseclib डॉक्स पर एक पृष्ठ है, जो मूल चर (सिफर, मोड, कुंजी आकार, बिट आकार) इनपुट करने के बाद नमूना कोड उत्पन्न करता है । यह रिज़ंडेल, ईसीबी, 256, 256 के लिए निम्न आउटपुट देता है:

mycrypt वाला एक कोड

$decoded = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, ENCRYPT_KEY, $term, MCRYPT_MODE_ECB);

पुस्तकालय के साथ इस तरह काम करता है

$rijndael = new \phpseclib\Crypt\Rijndael(\phpseclib\Crypt\Rijndael::MODE_ECB);
$rijndael->setKey(ENCRYPT_KEY);
$rijndael->setKeyLength(256);
$rijndael->disablePadding();
$rijndael->setBlockLength(256);

$decoded = $rijndael->decrypt($term);

* $term base64_decoded था

Mcrypt-extension को deprecated किया गया है जिसे PHP 7.2 में here पोस्ट की गई टिप्पणी के अनुसार हटा दिया जाएगा। इसलिए मैं पासवर्ड एन्क्रिप्ट करने का एक वैकल्पिक तरीका ढूंढ रहा हूं।

अभी मैं जैसे कुछ उपयोग कर रहा हूं

mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($key, true), $string, MCRYPT_MODE_CBC, $iv)

मुझे पासवर्ड एन्क्रिप्ट करने के लिए सबसे अच्छे / सबसे मज़बूत तरीके के लिए आपकी राय चाहिए, एन्क्रिप्टेड पासवर्ड बेशक PHP 7.xx द्वारा समर्थित होना चाहिए और इसे डीक्रिप्ट भी किया जाना चाहिए क्योंकि मेरे ग्राहक नया पासवर्ड जनरेट किए बिना अपने पासवर्ड को 'रिकवर' करने का विकल्प चाहते हैं। एक।


सक्रिय रूप से विकसित और बनाए रखने के लिए आपको mcrypt पर OpenSSL का उपयोग करना चाहिए। यह बेहतर सुरक्षा, स्थिरता और पोर्टेबिलिटी प्रदान करता है। दूसरे यह एईएस एन्क्रिप्शन / डिक्रिप्शन बहुत तेजी से करता है। यह डिफ़ॉल्ट रूप से PKCS7 पैडिंग का उपयोग करता है, लेकिन यदि आपको इसकी आवश्यकता है तो आप OPENSSL_ZERO_PADDING निर्दिष्ट कर सकते हैं। 32-बाइट बाइनरी कुंजी के साथ उपयोग करने के लिए, आप aes-256-cbc निर्दिष्ट कर सकते हैं जो MCRYPT_RIJNDAEL_128 तुलना में बहुत स्पष्ट है।

यहाँ Mcrypt का उपयोग कर कोड उदाहरण है:

McCS में PKCS7 पैडिंग के साथ लिखा गया गैर-सूचीबद्ध AES-256-CBC एन्क्रिप्शन लाइब्रेरी।

/**
 * This library is unsafe because it does not MAC after encrypting
 */
class UnsafeMcryptAES
{
    const CIPHER = MCRYPT_RIJNDAEL_128;

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = mcrypt_get_iv_size(self::CIPHER);
        $iv = mcrypt_create_iv($ivsize, MCRYPT_DEV_URANDOM);

        // Add PKCS7 Padding
        $block = mcrypt_get_block_size(self::CIPHER);
        $pad = $block - (mb_strlen($message, '8bit') % $block, '8bit');
        $message .= str_repeat(chr($pad), $pad);

        $ciphertext = mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128,
            $key,
            $message,
            MCRYPT_MODE_CBC,
            $iv
        );

        return $iv . $ciphertext;
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = mcrypt_get_iv_size(self::CIPHER);
        $iv = mb_substr($message, 0, $ivsize, '8bit');
        $ciphertext = mb_substr($message, $ivsize, null, '8bit');

        $plaintext = mcrypt_decrypt(
            MCRYPT_RIJNDAEL_128,
            $key,
            $ciphertext,
            MCRYPT_MODE_CBC,
            $iv
        );

        $len = mb_strlen($plaintext, '8bit');
        $pad = ord($plaintext[$len - 1]);
        if ($pad <= 0 || $pad > $block) {
            // Padding error!
            return false;
        }
        return mb_substr($plaintext, 0, $len - $pad, '8bit');
    }
}

और यहाँ OpenSSL का उपयोग करके लिखा गया संस्करण है:

/**
 * This library is unsafe because it does not MAC after encrypting
 */
class UnsafeOpensslAES
{
    const METHOD = 'aes-256-cbc';

    public static function encrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = openssl_random_pseudo_bytes($ivsize);

        $ciphertext = openssl_encrypt(
            $message,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );

        return $iv . $ciphertext;
    }

    public static function decrypt($message, $key)
    {
        if (mb_strlen($key, '8bit') !== 32) {
            throw new Exception("Needs a 256-bit key!");
        }
        $ivsize = openssl_cipher_iv_length(self::METHOD);
        $iv = mb_substr($message, 0, $ivsize, '8bit');
        $ciphertext = mb_substr($message, $ivsize, null, '8bit');

        return openssl_decrypt(
            $ciphertext,
            self::METHOD,
            $key,
            OPENSSL_RAW_DATA,
            $iv
        );
    }
}

स्रोत: यदि आप अपने PHP कोड में शब्द MCRYPT टाइप कर रहे हैं, तो आप इसे गलत कर रहे हैं


जैसा कि @rqLizard द्वारा सुझाया गया है, आप इसके बजाय openssl_decrypt उपयोग कर सकते हैं openssl_encrypt / openssl_decrypt PHP फ़ंक्शंस, जो AES (द एडवांस्ड एन्क्रिप्शन स्टैंडर्ड) को लागू करने के लिए एक बेहतर विकल्प प्रदान करता है जिसे openssl_decrypt एन्क्रिप्शन भी कहा जाता है।

निम्नलिखित स्कॉट की टिप्पणी के अनुसार php.net पर :

यदि आप 2015 में एन्क्रिप्ट / एन्क्रिप्ट डेटा के लिए कोड लिख रहे हैं, तो आपको openssl_encrypt() और openssl_decrypt() उपयोग करना चाहिए। अंतर्निहित लाइब्रेरी ( libmcrypt ) को 2007 के बाद से छोड़ दिया गया है, और ओपनएसएसएल (जो आधुनिक प्रोसेसर पर AES-NI लाभ उठाता है और कैश-टाइमिंग सुरक्षित है) की तुलना में कहीं अधिक खराब प्रदर्शन करता है।

इसके अलावा, MCRYPT_RIJNDAEL_256 AES-256 , यह MCRYPT_RIJNDAEL_256 ब्लॉक सिफर का एक अलग संस्करण है। यदि आप mcrypt में AES-256 चाहते हैं, तो आपको 32-बाइट कुंजी के साथ MCRYPT_RIJNDAEL_128 का उपयोग MCRYPT_RIJNDAEL_128 । ओपनएसएसएल यह अधिक स्पष्ट करता है कि आप किस मोड का उपयोग कर रहे हैं (यानी aes-128-cbc बनाम aes-128-cbc aes-256-ctr aes-128-cbc )।

OpenSSL भी mcrypt के NULL बाइट पैडिंग के बजाय CBC मोड के साथ PKCS7 पैडिंग का उपयोग करता है। इस प्रकार, mcrypt, OpenSSL की तुलना में आपके कोड को गद्दी के हमले के लिए असुरक्षित बनाने की अधिक संभावना है।

अंत में, यदि आप अपने सिफरटेक्स्ट (एनक्रिप्ट तब मैक) को प्रमाणित नहीं कर रहे हैं, तो आप इसे गलत कर रहे हैं।

आगे की पढाई:

कोड उदाहरण

उदाहरण 1

PHP 7.1+ के लिए GCM मोड उदाहरण में AES प्रमाणित एन्क्रिप्शन

<?php
//$key should have been previously generated in a cryptographically safe way, like openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$cipher = "aes-128-gcm";
if (in_array($cipher, openssl_get_cipher_methods()))
{
    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($ivlen);
    $ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv, $tag);
    //store $cipher, $iv, and $tag for decryption later
    $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, $options=0, $iv, $tag);
    echo $original_plaintext."\n";
}
?>

उदाहरण # 2

PHP 5.6+ के लिए एईएस प्रमाणित एन्क्रिप्शन उदाहरण

<?php
//$key previously generated safely, ie: openssl_random_pseudo_bytes
$plaintext = "message to be encrypted";
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );

//decrypt later....
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
if (hash_equals($hmac, $calcmac))//PHP 5.6+ timing attack safe comparison
{
    echo $original_plaintext."\n";
}
?>

उदाहरण # 3

उपरोक्त उदाहरणों के आधार पर, मैंने निम्नलिखित कोड को बदल दिया है जिसका उद्देश्य उपयोगकर्ता के सत्र आईडी को एन्क्रिप्ट करना है:

class Session {

  /**
   * Encrypts the session ID and returns it as a base 64 encoded string.
   *
   * @param $session_id
   * @return string
   */
  public function encrypt($session_id) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Encrypt the session ID.
    $encrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $session_id, MCRYPT_MODE_CBC, $iv);
    // Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($encrypt);
    // Return it.
    return $encryptedSessionId;
  }

  /**
   * Decrypts a base 64 encoded encrypted session ID back to its original form.
   *
   * @param $encryptedSessionId
   * @return string
   */
  public function decrypt($encryptedSessionId) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId);
    // Decrypt the string.
    $decryptedSessionId = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $decoded, MCRYPT_MODE_CBC, $iv);
    // Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, "\0");
    // Return it.
    return $session_id;
  }

  public function _getIv() {
    return md5($this->_getSalt());
  }

  public function _getSalt() {
    return md5($this->drupal->drupalGetHashSalt());
  }

}

में:

class Session {

  const SESS_CIPHER = 'aes-128-cbc';

  /**
   * Encrypts the session ID and returns it as a base 64 encoded string.
   *
   * @param $session_id
   * @return string
   */
  public function encrypt($session_id) {
    // Get the MD5 hash salt as a key.
    $key = $this->_getSalt();
    // For an easy iv, MD5 the salt again.
    $iv = $this->_getIv();
    // Encrypt the session ID.
    $ciphertext = openssl_encrypt($session_id, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    // Base 64 encode the encrypted session ID.
    $encryptedSessionId = base64_encode($ciphertext);
    // Return it.
    return $encryptedSessionId;
  }

  /**
   * Decrypts a base 64 encoded encrypted session ID back to its original form.
   *
   * @param $encryptedSessionId
   * @return string
   */
  public function decrypt($encryptedSessionId) {
    // Get the Drupal hash salt as a key.
    $key = $this->_getSalt();
    // Get the iv.
    $iv = $this->_getIv();
    // Decode the encrypted session ID from base 64.
    $decoded = base64_decode($encryptedSessionId, TRUE);
    // Decrypt the string.
    $decryptedSessionId = openssl_decrypt($decoded, self::SESS_CIPHER, $key, $options=OPENSSL_RAW_DATA, $iv);
    // Trim the whitespace from the end.
    $session_id = rtrim($decryptedSessionId, '\0');
    // Return it.
    return $session_id;
  }

  public function _getIv() {
    $ivlen = openssl_cipher_iv_length(self::SESS_CIPHER);
    return substr(md5($this->_getSalt()), 0, $ivlen);
  }

  public function _getSalt() {
    return $this->drupal->drupalGetHashSalt();
  }

}

स्पष्ट करने के लिए, उपरोक्त परिवर्तन एक सही रूपांतरण नहीं है क्योंकि दो एन्क्रिप्शन एक अलग ब्लॉक आकार और एक अलग एन्क्रिप्टेड डेटा का उपयोग करते हैं। इसके अतिरिक्त, डिफ़ॉल्ट पैडिंग अलग है, MCRYPT_RIJNDAEL केवल गैर-मानक नल पैडिंग का समर्थन करता है। @zaph

अतिरिक्त नोट्स (@ zaph टिप्पणियों से):

  • Rijndael 128 ( MCRYPT_RIJNDAEL_128 ) AES के बराबर है, हालाँकि Rijndael 256 ( MCRYPT_RIJNDAEL_256 ) AES-256 नहीं है क्योंकि 256 256-बिट्स के ब्लॉक आकार को निर्दिष्ट करता है, जबकि AES का केवल एक ब्लॉक आकार होता है: 128-बिट्स। तो मूल रूप से 256-बिट्स ( MCRYPT_RIJNDAEL_256 ) के ब्लॉक आकार वाले MCRYPT_RIJNDAEL_256 को गलती से mcrypt डेवलपर्स द्वारा विकल्पों के कारण नाम दिया गया है। @zaph
  • 256 के ब्लॉक आकार के साथ रिजेंडेल 128-बिट्स के ब्लॉक आकार की तुलना में कम सुरक्षित हो सकता है क्योंकि बाद में बहुत अधिक समीक्षाएँ और उपयोग हुए हैं। दूसरे, इंटरऑपरेबिलिटी इसमें बाधा है, जबकि एईएस आमतौर पर उपलब्ध है, जहां 256-बिट्स के ब्लॉक आकार के साथ रिजेंडेल नहीं है।
  • Rijndael के लिए अलग-अलग ब्लॉक आकार के साथ एन्क्रिप्शन अलग एन्क्रिप्टेड डेटा का उत्पादन करता है।

    उदाहरण के लिए, MCRYPT_RIJNDAEL_256 ( AES-256 समतुल्य नहीं), 256-बिट्स के आकार के साथ रिजिन्डेल ब्लॉक सिफर के एक भिन्न प्रकार को परिभाषित करता है और कुंजी में पास के आधार पर एक कुंजी का आकार होता है, जहां aes-256-cbc एक ब्लॉक आकार के साथ Rijndael है 256-बिट्स के एक महत्वपूर्ण आकार के साथ 128-बिट्स। इसलिए वे विभिन्न ब्लॉक आकारों का उपयोग कर रहे हैं जो पूरी तरह से अलग एन्क्रिप्टेड डेटा का उत्पादन करते हैं क्योंकि mcrypt ब्लॉक आकार को निर्दिष्ट करने के लिए नंबर का उपयोग करता है, जहां OpenSSL ने कुंजी आकार निर्दिष्ट करने के लिए संख्या का उपयोग किया था (AES में केवल एक ब्लॉक आकार 128-बिट्स है)। तो मूल रूप से एईएस 128-बिट्स के ब्लॉक आकार और 128, 192 और 256 बिट्स के प्रमुख आकारों के साथ रिजेंडेल है। इसलिए एईएस का उपयोग करना बेहतर है, जिसे ओपनएसएसएल में रिजंडेल 128 कहा जाता है।


आपको openssl_encrypt फ़ंक्शन का उपयोग करना चाहिए।


आप phpseclib pollyfill पैकेज का उपयोग कर सकते हैं। आप rijndael 256 के साथ एन्क्रिप्ट / डिक्रिप्ट के लिए खुले ssl या libsodium का उपयोग नहीं कर सकते। एक और मुद्दा, आपको किसी भी कोड को बदलने की आवश्यकता नहीं है।


मैं अपनी क्रिप्टो वस्तु का अनुवाद करने में सक्षम था

  • पुराने डेटा को डिक्रिप्ट करने के लिए mcrypt के साथ php की कॉपी प्राप्त करें। मैं http://php.net/get/php-7.1.12.tar.gz/from/a/mirror , इसे संकलित किया, फिर एक्सट्रीम / mcrypt एक्सटेंशन (कॉन्फ़िगर; मेक; इनस्टॉल;) को जोड़ा। मुझे लगता है कि मुझे php.ini पर एक्स्टेंशन = mcrypt.so लाइन को भी जोड़ना था। सभी अनएन्क्रिप्टेड डेटा के साथ डेटा के मध्यवर्ती संस्करण बनाने के लिए स्क्रिप्ट की एक श्रृंखला।

  • Opensl के लिए एक सार्वजनिक और निजी कुंजी बनाएँ

    openssl genrsa -des3 -out pkey.pem 2048
    (set a password)
    openssl rsa -in pkey.pem -out pkey-pub.pem -outform PEM -pubout
  • एन्क्रिप्ट करने के लिए (सार्वजनिक कुंजी का उपयोग करके) Opensl_seal का उपयोग करें। मैंने जो कुछ पढ़ा है, उससे RSA कुंजी का उपयोग करके खुलता है .sl_encrypt कुंजी लंबाई से 11 बाइट्स तक सीमित है ( http://php.net/manual/en/function.openssl-public-encrypt.php थॉमस हॉर्स्टन की टिप्पणी)

    $pubKey = openssl_get_publickey(file_get_contents('./pkey-pub.pem'));
    openssl_seal($pwd, $sealed, $ekeys, [ $pubKey ]);
    $encryptedPassword = base64_encode($sealed);
    $key = base64_encode($ekeys[0]);

आप शायद कच्चे बाइनरी को स्टोर कर सकते हैं।

  • डिक्रिप्ट (निजी कुंजी का उपयोग करके)

    $passphrase="passphrase here";
    $privKey = openssl_get_privatekey(file_get_contents('./pkey.pem'), $passphrase);
    // I base64_decode() from my db columns
    openssl_open($encryptedPassword, $plain, $key, $privKey);
    echo "<h3>Password=$plain</h3>";

PS आप खाली स्ट्रिंग को एन्क्रिप्ट नहीं कर सकते ("")

PPS यह पासवर्ड डेटाबेस के लिए है उपयोगकर्ता सत्यापन के लिए नहीं।


जैसा कि बताया गया है, आपको अपने उपयोगकर्ताओं के पासवर्ड को एक प्रारूप में संग्रहीत नहीं करना चाहिए जो कि डिक्रिप्टेबल हो। प्रतिवर्ती एन्क्रिप्शन अपने उपयोगकर्ताओं के पासवर्ड का पता लगाने के लिए हैकर्स के लिए एक आसान मार्ग प्रदान करता है, जो आपके उपयोगकर्ताओं के खातों को अन्य साइटों पर डालने के लिए जोखिम में है, क्या उन्हें उसी पासवर्ड का उपयोग करना चाहिए।

PHP यादृच्छिक-नमकीन, एक-तरफ़ा हैश एन्क्रिप्शन - password_hash() और password_verify() लिए शक्तिशाली कार्यों की एक जोड़ी प्रदान करता है। क्योंकि हैश स्वचालित रूप से यादृच्छिक-नमकीन है, पासवर्ड को रिवर्स-इंजीनियर करने के लिए हैकर्स के पास पासवर्ड हैश की precompiled तालिकाओं का उपयोग करने का कोई तरीका नहीं है। PASSWORD_DEFAULT विकल्प सेट करें और PHP के भावी संस्करण स्वचालित रूप से आपके कोड को अपडेट करने के लिए बिना पासवर्ड हैश उत्पन्न करने के लिए मजबूत एल्गोरिदम का उपयोग करेंगे।


उदाहरण के लिए प्रत्येक mcrypt से पहले बस @ उपयोग करें:

@mcrypt_module_open,
@mcrypt_get_block_size,
@mcrypt_generic_init
@mcrypt_generic
@mcrypt_generic_deinit

यह फ़ंक्शन mcrypt_module_open हटाए गए त्रुटि को हटा देगा और काम करेगा।





mcrypt