दो-तरफ़ा एन्क्रिप्शन: मुझे पासवर्ड संग्रहीत करने की आवश्यकता है जिसे पुनर्प्राप्त किया जा सकता है


174

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

मुझे क्या जानना चाहिए:

  1. मैं PHP में पासवर्ड कैसे एन्क्रिप्ट और डिक्रिप्ट कर सकता हूं?

  2. पासवर्ड को एन्क्रिप्ट करने के लिए सबसे सुरक्षित एल्गोरिदम क्या है?

  3. मैं निजी कुंजी कहां संग्रहीत करूं?

  4. निजी कुंजी संग्रहीत करने के बजाय, क्या उपयोगकर्ताओं को निजी कुंजी दर्ज करने के लिए किसी भी समय पासवर्ड की आवश्यकता होती है, जिसे उन्हें डिक्रिप्ट किए गए पासवर्ड की आवश्यकता होती है? (इस एप्लिकेशन के उपयोगकर्ताओं पर भरोसा किया जा सकता है)

  5. पासवर्ड किन तरीकों से चोरी और डिक्रिप्ट किया जा सकता है? मुझे क्या पता होना चाहिए?


1
नोट: Libsodium अब> = 7.2 के लिए PHP कोर में संकलित की गई है। यह "गो टू" समाधान होगा क्योंकि यह mcrypt के विपरीत आधुनिक तरीकों से भरा हुआ है जिसे अपदस्थ माना जाता है और हटा दिया गया है।
वृत्ति

जवाबों:


212

निजी तौर पर, मैं mcryptदूसरों की तरह इस्तेमाल करूंगा । लेकिन नोट करने के लिए बहुत कुछ है ...

  1. मैं PHP में पासवर्ड कैसे एन्क्रिप्ट और डिक्रिप्ट कर सकता हूं?

    एक मजबूत वर्ग के लिए नीचे देखें जो आपके लिए हर चीज़ का ध्यान रखता है:

  2. पासवर्ड को एन्क्रिप्ट करने के लिए सबसे सुरक्षित एल्गोरिदम क्या है?

    सबसे सुरक्षित ? उनमे से कोई भी। यदि आप एन्क्रिप्ट करने जा रहे हैं तो सबसे सुरक्षित तरीका है सूचना प्रकटीकरण भेद्यता (XSS, दूरस्थ समावेशन, आदि) से बचाव करना। यदि यह बाहर हो जाता है, तो हमलावर अंततः एन्क्रिप्शन को क्रैक कर सकता है (कोई एन्क्रिप्शन कुंजी के बिना 100% अन-रिवर्सिबल है - जैसा कि @NullUserException बताते हैं कि यह पूरी तरह से सच नहीं है। कुछ एन्क्रिप्शन योजनाएं हैं जो कि वनटाइमपैड को क्रैक करना असंभव हैं )। ।

  3. मैं निजी कुंजी कहां संग्रहीत करूं?

    मैं क्या करूँगा 3 कुंजी का उपयोग करें। एक उपयोगकर्ता की आपूर्ति की है, एक आवेदन विशिष्ट है और दूसरा उपयोगकर्ता विशिष्ट (एक नमक की तरह) है। एप्लिकेशन विशिष्ट कुंजी कहीं भी संग्रहीत की जा सकती है (वेब-रूट के बाहर एक कॉन्फ़िगरेशन फ़ाइल में, एक पर्यावरण चर में, आदि)। उपयोगकर्ता विशिष्ट एक एन्क्रिप्टेड पासवर्ड के बगल में db में एक कॉलम में संग्रहीत किया जाएगा। आपूर्ति की गई उपयोगकर्ता को संग्रहीत नहीं किया जाएगा। फिर, आप ऐसा कुछ करेंगे:

    $key = $userKey . $serverKey . $userSuppliedKey;

    वहाँ लाभ यह है कि किसी भी 2 कीज़ को डेटा से समझौता किए बिना समझौता किया जा सकता है। यदि कोई SQL इंजेक्शन हमला होता है, तो वे प्राप्त कर सकते हैं $userKey, लेकिन अन्य नहीं। 2. यदि कोई स्थानीय सर्वर शोषण है, तो वे मिल सकते हैं $userKeyऔर $serverKeyतीसरे नहीं $userSuppliedKey। यदि वे उपयोगकर्ता को रिंच के साथ हराते हैं, तो वे प्राप्त कर सकते हैं $userSuppliedKey, लेकिन अन्य 2 नहीं (लेकिन फिर से, यदि उपयोगकर्ता रिंच के साथ पीटा जाता है, तो आप वैसे भी बहुत देर हो चुके हैं)।

  4. निजी कुंजी संग्रहीत करने के बजाय, क्या उपयोगकर्ताओं को निजी कुंजी दर्ज करने के लिए किसी भी समय पासवर्ड की आवश्यकता होती है, जिसे उन्हें डिक्रिप्ट किए गए पासवर्ड की आवश्यकता होती है? (इस एप्लिकेशन के उपयोगकर्ताओं पर भरोसा किया जा सकता है)

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

  5. पासवर्ड किन तरीकों से चोरी और डिक्रिप्ट किया जा सकता है? मुझे क्या पता होना चाहिए?

    आपके सिस्टम के किसी भी प्रकार का समझौता उन्हें एन्क्रिप्टेड डेटा को देखने देगा। यदि वे कोड को इंजेक्ट कर सकते हैं या आपके फाइल सिस्टम में आ सकते हैं, तो वे डिक्रिप्टेड डेटा देख सकते हैं (क्योंकि वे उन फ़ाइलों को संपादित कर सकते हैं जो डेटा को डिक्रिप्ट कर सकते हैं)। रीप्ले या MITM हमले के किसी भी रूप में उन्हें शामिल कुंजियों तक पूरी पहुंच मिलेगी। कच्चे HTTP ट्रैफ़िक को सूँघने से भी उन्हें चाबी मिलेगी।

    सभी ट्रैफ़िक के लिए SSL का उपयोग करें। और सुनिश्चित करें कि सर्वर पर किसी भी प्रकार की कमजोरियां (CSRF, XSS, SQL इंजेक्शन, विशेषाधिकार वृद्धि, रिमोट कोड निष्पादन, आदि) नहीं हैं।

संपादित करें: यहाँ एक मजबूत एन्क्रिप्शन विधि का PHP वर्ग कार्यान्वयन है:

/**
 * 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 (!hash_equals(hash_hmac('sha512', $enc, $macKey, true), $mac)) {
             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);
    }
}

ध्यान दें कि मैं PHP 5.6 में जोड़े गए फ़ंक्शन का उपयोग कर रहा हूं hash_equals:। यदि आप 5.6 से कम पर हैं, तो आप इस विकल्प फ़ंक्शन का उपयोग कर सकते हैं जो दोहरे एचएमएसी सत्यापन का उपयोग करके समय-सुरक्षित तुलना फ़ंक्शन को लागू करता है :

function hash_equals($a, $b) {
    $key = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    return hash_hmac('sha512', $a, $key) === hash_hmac('sha512', $b, $key);
}

उपयोग:

$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);

ध्यान दें कि मैंने $e2दूसरी बार आपको विभिन्न उदाहरण दिखाने के लिए उपयोग किया था फिर भी डेटा को ठीक से डिक्रिप्ट करेगा।

अब, यह कैसे काम करता है / इसे किसी अन्य समाधान पर क्यों उपयोग किया जाता है:

  1. चांबियाँ

    • चाबियाँ सीधे उपयोग नहीं की जाती हैं। इसके बजाय, कुंजी को एक मानक PBKDF2 व्युत्पत्ति द्वारा बढ़ाया जाता है।

    • एन्क्रिप्शन के लिए उपयोग की जाने वाली कुंजी पाठ के हर एन्क्रिप्ट किए गए ब्लॉक के लिए अद्वितीय है। इसलिए आपूर्ति की गई कुंजी "मास्टर कुंजी" बन जाती है। इसलिए यह वर्ग सिफर और ऑर्टिकल कीज़ के लिए मुख्य रोटेशन प्रदान करता है।

    • महत्वपूर्ण नोट , $roundsपैरामीटर पर्याप्त शक्ति की सच्ची यादृच्छिक कुंजियों के लिए कॉन्फ़िगर किया गया है (न्यूनतम पर क्रिप्टोग्राफिक रूप से सुरक्षित यादृच्छिक के 128 बिट्स)। यदि आप पासवर्ड, या गैर-यादृच्छिक कुंजी (या कम यादृच्छिक तो CS यादृच्छिक के 128 बिट्स) का उपयोग करने जा रहे हैं, तो आपको इस पैरामीटर को बढ़ाना होगा । मैं पासवर्ड के लिए न्यूनतम 10000 का सुझाव दूंगा (जितना अधिक आप खर्च कर सकते हैं, उतना बेहतर होगा, लेकिन यह रनटाइम को जोड़ देगा) ...

  2. डेटा अखंडता

    • अपडेट किया गया संस्करण ENCRYPT-THEN-MAC का उपयोग करता है, जो एन्क्रिप्टेड डेटा की प्रामाणिकता सुनिश्चित करने के लिए एक बेहतर तरीका है।
  3. एन्क्रिप्शन:

    • यह वास्तव में एन्क्रिप्शन का प्रदर्शन करने के लिए mcrypt का उपयोग करता है। मैं MCRYPT_BLOWFISHया तो MCRYPT_RIJNDAEL_128साइफर्स और MCRYPT_MODE_CBCमोड के लिए उपयोग करने का सुझाव दूंगा । यह पर्याप्त मजबूत है, और अभी भी काफी तेज है (एक एन्क्रिप्शन और डिक्रिप्शन चक्र मेरी मशीन पर लगभग 1/2 सेकंड लेता है)।

अब, पहली सूची से बिंदु 3 के रूप में, जो आपको देता है वह इस तरह से एक फ़ंक्शन है:

function makeKey($userKey, $serverKey, $userSuppliedKey) {
    $key = hash_hmac('sha512', $userKey, $serverKey);
    $key = hash_hmac('sha512', $key, $userSuppliedKey);
    return $key;
}

आप इसे makeKey()फंक्शन में स्ट्रेच कर सकते हैं , लेकिन चूंकि यह बाद में स्ट्रेच होने वाला है, इसलिए ऐसा करने के लिए वास्तव में बहुत बड़ी बात नहीं है।

जहाँ तक भंडारण आकार की बात है, यह सादे पाठ पर निर्भर करता है। ब्लोफिश 8 बाइट ब्लॉक आकार का उपयोग करता है, इसलिए आपके पास होगा:

  • नमक के लिए 16 बाइट्स
  • एचएएमएसी के लिए 64 बाइट्स
  • डेटा की लंबाई
  • पैडिंग ताकि डेटा लंबाई% 8 == 0 हो

तो 16 वर्ण डेटा स्रोत के लिए, एन्क्रिप्ट किए जाने वाले डेटा के 16 वर्ण होंगे। तो इसका मतलब है कि वास्तविक एन्क्रिप्टेड डेटा का आकार पैडिंग के कारण 16 बाइट्स है। फिर नमक के लिए 16 बाइट्स और एचएमएसी के लिए 64 बाइट्स जोड़ें और कुल संग्रहीत आकार 96 बाइट्स है। तो वहाँ सबसे अच्छा एक 80 चरित्र उपरि है, और सबसे खराब एक 87 चरित्र उपरि ...

मुझे आशा है कि वह मदद करेंगे...

नोट: १२/११/१२: मैंने सिर्फ बेहतर व्युत्पन्न कुंजियों का उपयोग करके और बेहतर तरीके से मैक जेनरेशन का उपयोग करते हुए इस वर्ग को बेहतर एन्क्रिप्शन विधि से अपडेट किया है ...


3
किसी को समझ में नहीं आता है कि इसका क्या मतलब है "ब्रेक"। वर्ग पर @IRC अच्छा काम, यह बहुत अच्छा कोड लानत है।
jcolebrand

1
निम्नलिखित गलत है। कोई विचार क्यों? $ x = नया एन्क्रिप्शन (MCRYPT_BlOWFISH, MCRYPT_MODE_CBC); $ परीक्षण = $ x-> एन्क्रिप्ट ("परीक्षण", "ए"); गूंज var_dump ($ x-> डिक्रिप्ट ($ परीक्षण, "ए"));
तरंग दैर्ध्य

2
ओह और फिर से डिक्रिप्ट फ़ंक्शन में मदद -64करने के लिए दोनों को बदल रहा है -128(ताकि आप प्राप्त करें $enc = substr($data, 128, -128)और$mac = substr($data, -128);
cosmorogers

4
@ircmaxell कोड को अंतिम बार संशोधित किए जाने के बाद से यह काफी समय हो गया है, इसलिए मैं सोच रहा हूं कि क्या यह अद्यतित है। मुझे वित्तीय अनुप्रयोग के लिए कुछ इसी तरह का उपयोग करने की आवश्यकता है और यह अच्छा होगा यदि आप इस वर्ग के साथ ठीक कर दें :-)
nt.bas

2
चेतावनी! Mcrypt एक्सटेंशन अब लगभग एक दशक के लिए छोड़ दिया गया है, और उपयोग करने के लिए काफी जटिल भी था। इसलिए इसे ओपनएसएसएल के पक्ष में पदावनत किया गया है, जहां इसे कोर से हटाकर पीएसईसीएल में पीएचपी 7.2 में रखा जाएगा। th1.php.net/manual/en/migration71.deprecated.php
वी

15

मैं PHP में पासवर्ड कैसे एन्क्रिप्ट और डिक्रिप्ट कर सकता हूं? कई एन्क्रिप्शन एल्गोरिदम में से एक को लागू करके। (या कई पुस्तकालयों में से एक का उपयोग करके)

पासवर्ड को एन्क्रिप्ट करने के लिए सबसे सुरक्षित एल्गोरिदम क्या है? विभिन्न एल्गोरिदम के टन हैं, जिनमें से कोई भी 100% सुरक्षित नहीं है। लेकिन उनमें से कई वाणिज्य और यहां तक ​​कि सैन्य उद्देश्यों के लिए पर्याप्त सुरक्षित हैं

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

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

किन तरीकों से पासवर्ड चोरी और डिक्रिप्ट किया जा सकता है? मुझे क्या पता होना चाहिए? यह इस्तेमाल किए गए एल्गोरिदम पर निर्भर करता है। हालाँकि, हमेशा सुनिश्चित करें कि आप उपयोगकर्ता से या उससे अनएन्क्रिप्टेड पासवर्ड न भेजें। या तो इसे क्लाइंट साइड पर एन्क्रिप्ट / डिक्रिप्ट करें, या सर्वर और क्लाइंट के बीच कनेक्शन को सुरक्षित करने के लिए https (या उपयोगकर्ता अन्य क्रिप्टोग्राफ़िक का उपयोग करें)।

हालाँकि, अगर आप सभी की जरूरत है एन्क्रिप्टेड तरीके से पासवर्ड स्टोर करने के लिए, मैं आपको एक सरल XOR सिफर का उपयोग करने का सुझाव दूंगा। इस एल्गोरिथ्म के साथ मुख्य समस्या यह है कि इसे आवृत्ति विश्लेषण द्वारा आसानी से तोड़ा जा सकता है। हालाँकि, आम तौर पर पासवर्ड अंग्रेजी पाठ के लंबे पैराग्राफ से नहीं बने होते हैं, मुझे नहीं लगता कि आपको इसके बारे में चिंता करनी चाहिए। XOR सिफर के साथ दूसरी समस्या यह है कि यदि आपके पास एन्क्रिप्टेड और डिक्रिप्टेड दोनों रूपों में एक संदेश है, तो आप आसानी से उस पासवर्ड का पता लगा सकते हैं जिसके साथ यह एन्क्रिप्ट किया गया था। फिर से, आपके मामले में एक बड़ी समस्या नहीं है क्योंकि यह केवल उस उपयोगकर्ता को प्रभावित करता है जो पहले से ही अन्य तरीकों से समझौता कर रहा था।


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

वैसे यह एक समस्या है। निजी कुंजी को टेक्स्ट फ़ाइल में संग्रहीत किया जा सकता है और फिर ऐप पर चिपका दिया जा सकता है। कुंजी सर्वर पर भी संग्रहीत की जा सकती है लेकिन इस मामले में इसे अभी भी कुछ अन्य एन्क्रिप्शन एल्गोरिथ्म जैसे XOR के साथ एन्क्रिप्ट किया जाना चाहिए। इस मामले में XOR का उपयोग करना काफी सुरक्षित है क्योंकि केवल एक पासवर्ड-संदेश जोड़ी है और संदेश काफी यादृच्छिक है इसलिए आवृत्ति विश्लेषण ठंड का उपयोग नहीं किया जाना चाहिए।
इवान

4
मैं निश्चित रूप से एन्क्रिप्शन एल्गोरिथम को स्वयं लागू करने की अनुशंसा नहीं करूंगा, बहुत अधिक संभावित नुकसान हैं और मौजूदा पुस्तकालयों का परीक्षण और विश्लेषण कई लोगों द्वारा किया गया है।
लांग एर्स

XOR के साथ मुख्य समस्या यह है कि अगर कोई आपके एप्लिकेशन डेटा को चुराता है और उपयोगकर्ता के पासवर्ड में से केवल एक को जानता है, तो वे उस उपयोगकर्ता के लिए अन्य सभी पासवर्ड को डिक्रिप्ट कर सकते हैं।
लांग एर्स

1
@ इवान: हाँ, लेकिन यह उन मामलों में से एक है जब मुझे लगता है कि DIY वास्तव में बहुत बुरा है जब तक आप वास्तव में क्रिप्टोग्राफी को नहीं समझते हैं। मजबूत सिफर मौजूद हैं, उनका उपयोग क्यों नहीं किया जाता है?
ircmaxell

13
  1. मैकक्रिप्ट ( http://www.php.net/manual/en/intro.mcrypt.php ) के बाद आप जो PHP फ़ंक्शन कर रहे हैं ।

मैनुअल से उदाहरण इस उदाहरण के लिए थोड़ा संपादित किया गया है):

<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$pass = "PasswordHere";
echo strlen($pass) . "\n";

$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $pass, MCRYPT_MODE_ECB, $iv);
echo strlen($crypttext) . "\n";
?>

आप अपने पासवर्ड को डिक्रिप्ट करने के लिए mcrypt_decrypt का उपयोग करेंगे ।

  1. सबसे अच्छा एल्गोरिथ्म बल्कि व्यक्तिपरक है - 5 लोगों से पूछें, 5 उत्तर प्राप्त करें। व्यक्तिगत रूप से यदि डिफ़ॉल्ट (ब्लोफ़िश) आपके लिए पर्याप्त नहीं है, तो आपको संभवतः बड़ी समस्याएं हैं!

  2. यह देखते हुए कि यह PHP द्वारा एन्क्रिप्ट करने के लिए आवश्यक है - सुनिश्चित नहीं है कि आप इसे कहीं भी छिपा सकते हैं - इस पर टिप्पणियों का स्वागत करते हैं। मानक PHP सर्वोत्तम कोडिंग अभ्यास पाठ्यक्रम के लागू होते हैं!

  3. यह देखते हुए कि एन्क्रिप्शन कुंजी आपके कोड में वैसे भी होगी, यह निश्चित नहीं है कि आप क्या हासिल करेंगे, बशर्ते आपका शेष आवेदन सुरक्षित हो।

  4. जाहिर है, अगर एन्क्रिप्टेड पासवर्ड और एन्क्रिप्शन कुंजी चोरी हो जाती है, तो गेम खत्म।

मैंने अपने उत्तर पर एक सवार रखा - मैं एक PHP क्रिप्टो विशेषज्ञ नहीं हूं, लेकिन, मुझे लगता है कि मैंने जो उत्तर दिया है वह मानक अभ्यास है - मैं अन्य टिप्पणियों का स्वागत कर सकता हूं।


$pass = $text। मुझे लगता है कि उन्होंने इस प्रश्न को पूरा करने के लिए बदल दिया, और दूसरी घटना पर ध्यान नहीं दिया।
हैदरए

3
ध्यान देने योग्य दो बातें। सबसे पहले, MCRYPT_MODE_ECBएक IV का उपयोग नहीं करता है। दूसरा, अगर यह हुआ, तो आपको IV को स्टोर करना होगा क्योंकि आप इसके बिना डेटा को डिक्रिप्ट नहीं कर सकते ...
ircmaxell

"सबसे अच्छा एल्गोरिथ्म बल्कि व्यक्तिपरक है - 5 लोगों से पूछें, 5 उत्तर प्राप्त करें। व्यक्तिगत रूप से यदि डिफ़ॉल्ट (ब्लोफ़िश) आपके लिए पर्याप्त नहीं है, तो आपको संभवतः बड़ी समस्याएं हैं!" यह पूरी तरह से गलत है। कोई भी क्रिप्टोकरंसी विशेषज्ञ अधिक-से-कम सहमत होंगे। gist.github.com/tqbf/be58d2d39690c3b366ad जो विशेष रूप से ब्लोफिश को बाहर करता है
स्कॉट आर्किस्ज़ेस्की

6

बहुत सारे उपयोगकर्ताओं ने mcrypt का उपयोग करने का सुझाव दिया है ... जो कि सही है, लेकिन मैं इसे आसानी से संग्रहीत और स्थानांतरित करने के लिए एक कदम आगे जाना पसंद करता हूं (जैसा कि कभी-कभी एन्क्रिप्ट किए गए मान उन्हें कर्ल, या json जैसी अन्य तकनीकों का उपयोग करने के लिए भेजने के लिए कठिन बना सकते हैं) ।

आपके द्वारा सफलतापूर्वक mcrypt का उपयोग करके एन्क्रिप्ट किए जाने के बाद, इसे base64_encode के माध्यम से चलाएं और फिर इसे हेक्स कोड में परिवर्तित करें। एक बार हेक्स कोड में विभिन्न तरीकों से स्थानांतरण करना आसान है।

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $unencrypted);
$encrypted = $ua."||||".$iv;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$encrypted = base64_encode($encrypted);
$encrypted = array_shift(unpack('H*', $encrypted));

और दूसरी तरफ:

$encrypted = pack('H*', $encrypted);
$encrypted = base64_decode($encrypted);
list($encrypted,$iv) = explode("||||",$encrypted,2);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$unencrypted = mdecrypt_generic($td, $encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);


2
अच्छी तरह से - यह 2011 में था: पी
ब्रैडली

5

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

सार्वजनिक कुंजी

  1. OpenSSL विस्तार, विशेष रूप से openssl_public_encryptऔरopenssl_private_decrypt
  2. यह सीधे आरएसए होगा, यह मानते हुए कि आपके पासवर्ड कुंजी आकार में फिट होंगे - पैडिंग, अन्यथा आपको एक सममित परत की आवश्यकता है
  3. प्रत्येक उपयोगकर्ता के लिए दोनों कुंजी स्टोर करें, निजी कुंजी का पासफ़्रेज़ उनका एप्लिकेशन पासवर्ड है

सममित

  1. Mcrypt एक्सटेंशन
  2. AES-256 शायद एक सुरक्षित दांव है, लेकिन यह अपने आप में एक SO प्रश्न हो सकता है
  3. आप नहीं करते - यह उनका एप्लिकेशन पासवर्ड होगा

दोनों

4। हां - उपयोगकर्ताओं को हर बार अपना आवेदन पासवर्ड दर्ज करना होगा, लेकिन सत्र में इसे संग्रहीत करने से अन्य मुद्दे उठेंगे

5

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

Mcrypt से बचें, सावधान रहें openssl_private_decrypt()
स्कॉट आर्किसेवस्की

2

मैंने ऐसा कुछ करने की कोशिश की, लेकिन कृपया ध्यान दें कि मैं क्रिप्टोग्राफर नहीं हूं और न ही मैं phpकिसी प्रोग्रामिंग भाषा के बारे में गहराई से जानकारी रखता हूं । यह सिर्फ एक विचार है। मेरा विचार keyकुछ फ़ाइल में संग्रहीत करना है database(या मैन्युअल रूप से दर्ज करना है) जिसे (स्थान) आसानी से भविष्यवाणी नहीं की जा सकती है (और किसी दिन कुछ भी डिक्रिप्ट किया जाएगा, अवधारणा डिक्रिप्शन समय को लंबा करना है) और संवेदनशील जानकारी को एन्क्रिप्ट करना है।

$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH , MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "evenifyouaccessmydatabaseyouwillneverfindmyemail";
$text = "myemail@domain.com";
echo "Key : ".$key."<br/>";
echo "Text : ".$text . "<br/>";
echo "Md5 : ".md5($text). "<br/>";
echo "Sha1 : ".sha1($text). "<br/>";



$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH , $key, $text, MCRYPT_MODE_ECB, $iv);
echo "Crypted Data : ".$crypttext."<br>";

$base64 = base64_encode($crypttext);
echo "Encoded Data : ".$base64."<br/>";
$decode =  base64_decode($base64);


$decryptdata = mcrypt_decrypt(MCRYPT_BLOWFISH , $key, $crypttext, MCRYPT_MODE_ECB, $iv);

echo "Decoded Data : ".ereg_replace("?", null ,  $decryptdata); 
//event if i add '?' to the sting to the text it works, I don't know why.

कृपया ध्यान दें कि यह सिर्फ एक अवधारणा है। इस कोड पर कोई सुधार अत्यधिक प्रशंसनीय होगा।


2

पासवर्ड एक हार्डवेयर डिवाइस के लिए हैं, इसलिए हैश के खिलाफ जांच करना सवाल से बाहर है

एह? मुझे समझ नहीं आ रहा है। क्या आपका बस यही मतलब है कि पासवर्ड रिकवर होना चाहिए?

जैसा कि दूसरों ने कहा है, mcrypt एक्सटेंशन बहुत सारे क्रिप्टोग्राफ़िक कार्यों तक पहुँच प्रदान करता है - हालाँकि आप अपने उपयोगकर्ताओं को अपने सभी अंडे एक ही टोकरी में रखने के लिए आमंत्रित कर रहे हैं - एक जो संभावित रूप से हमलावरों के लिए एक लक्ष्य होगा - और यदि आपको पता भी नहीं है समस्या को हल करना कैसे शुरू करें, तो आप अपने उपयोगकर्ताओं को एक काम कर रहे हैं। आप यह समझने की स्थिति में नहीं हैं कि डेटा की सुरक्षा कैसे करें।

अधिकांश सुरक्षा भेद्यताएँ इस बारे में आती हैं कि अंतर्निहित एल्गोरिथ्म त्रुटिपूर्ण या असुरक्षित है - लेकिन अनुप्रयोग कोड के भीतर एल्गोरिथ्म का उपयोग करने के तरीके की समस्याओं के कारण।

यह कहते हुए कि, एक यथोचित सुरक्षित प्रणाली का निर्माण संभव है।

आपको केवल असममित एन्क्रिप्शन पर विचार करना चाहिए यदि आपके पास उपयोगकर्ता के लिए एक सुरक्षित संदेश बनाने की आवश्यकता है जो दूसरे (विशिष्ट) उपयोगकर्ता द्वारा पठनीय है। कारण यह है कि इसकी कम्प्यूटेशनल रूप से महंगा है। यदि आप उपयोगकर्ताओं को केवल अपना डेटा दर्ज करने और पुनः प्राप्त करने के लिए एक रिपॉजिटरी प्रदान करना चाहते हैं, तो सममित एन्क्रिप्शन पर्याप्त है।

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


1

Password_hash और password_verify का उपयोग करें

<?php
/**
 * In this case, we want to increase the default cost for BCRYPT to 12.
 * Note that we also switched to BCRYPT, which will always be 60 characters.
 */
$options = [
    'cost' => 12,
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>

और डिक्रिप्ट करने के लिए:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}
?>
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.