Enkripsi dua arah: Saya perlu menyimpan kata sandi yang dapat diambil

174

Saya membuat aplikasi yang akan menyimpan kata sandi, yang dapat diambil dan dilihat pengguna. Kata sandi untuk perangkat perangkat keras, jadi memeriksa hash tidak perlu dilakukan.

Yang perlu saya ketahui adalah:

  1. Bagaimana cara mengenkripsi dan mendekripsi kata sandi dalam PHP?

  2. Algoritma apa yang paling aman untuk mengenkripsi kata sandi?

  3. Di mana saya menyimpan kunci pribadi?

  4. Alih-alih menyimpan kunci privat, apakah lebih baik meminta pengguna memasukkan kunci privat kapan saja mereka membutuhkan kata sandi yang didekripsi? (Pengguna aplikasi ini dapat dipercaya)

  5. Dengan cara apa kata sandi dapat dicuri dan didekripsi? Apa yang perlu saya waspadai?

HyderA
sumber
1
Catatan: Libsodium sekarang dikompilasi ke dalam inti PHP untuk> = 7.2. Ini akan menjadi solusi "pergi ke" sekarang karena penuh dengan metode modern tidak seperti mcrypt yang dianggap usang dan telah dihapus.
Eksibisioner

Jawaban:

212

Secara pribadi, saya akan menggunakan mcryptseperti orang lain yang diposting. Tetapi ada banyak lagi yang perlu diperhatikan ...

  1. Bagaimana cara mengenkripsi dan mendekripsi kata sandi dalam PHP?

    Lihat di bawah ini untuk kelas yang kuat yang mengurus semuanya untuk Anda:

  2. Algoritma apa yang paling aman untuk mengenkripsi kata sandi?

    paling aman ? siapapun dari mereka. Metode teraman jika Anda akan mengenkripsi adalah untuk melindungi terhadap kerentanan pengungkapan informasi (XSS, inklusi jarak jauh, dll). Jika keluar, penyerang akhirnya dapat memecahkan enkripsi (tidak ada enkripsi yang 100% tidak dapat dibalik tanpa kunci - seperti yang ditunjukkan oleh @NullUserException, hal ini tidak sepenuhnya benar. Ada beberapa skema enkripsi yang tidak mungkin diretas seperti OneTimePad ) .

  3. Di mana saya menyimpan kunci pribadi?

    Apa yang akan saya lakukan adalah menggunakan 3 kunci. Satu adalah pengguna yang disediakan, satu adalah aplikasi spesifik dan yang lainnya adalah pengguna spesifik (seperti garam). Kunci spesifik aplikasi dapat disimpan di mana saja (dalam file konfigurasi di luar web-root, dalam variabel lingkungan, dll). Yang khusus pengguna akan disimpan dalam kolom di db di sebelah kata sandi terenkripsi. Pengguna yang disediakan tidak akan disimpan. Kemudian, Anda akan melakukan sesuatu seperti ini:

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

    Manfaat di sana, adalah bahwa 2 kunci dapat dikompromikan tanpa data dikompromikan. Jika ada serangan SQL Injection, mereka bisa mendapatkan $userKey, tetapi bukan yang lain 2. Jika ada exploit server lokal, mereka bisa mendapatkan $userKeydan $serverKey, tetapi bukan yang ketiga $userSuppliedKey. Jika mereka mengalahkan pengguna dengan kunci pas, mereka bisa mendapatkan $userSuppliedKey, tetapi tidak 2 yang lain (tapi sekali lagi, jika pengguna dipukul dengan kunci pas, Anda toh sudah terlambat).

  4. Alih-alih menyimpan kunci privat, apakah lebih baik meminta pengguna memasukkan kunci privat kapan saja mereka membutuhkan kata sandi yang didekripsi? (Pengguna aplikasi ini dapat dipercaya)

    Benar. Sebenarnya, itulah satu-satunya cara saya melakukannya. Kalau tidak, Anda perlu menyimpan versi yang tidak dienkripsi dalam format penyimpanan yang tahan lama (memori bersama seperti APC atau memcached, atau dalam file sesi). Itu membuat Anda terkena kompromi tambahan. Jangan pernah menyimpan versi kata sandi yang tidak terenkripsi dalam apa pun kecuali variabel lokal.

  5. Dengan cara apa kata sandi dapat dicuri dan didekripsi? Apa yang perlu saya waspadai?

    Segala bentuk kompromi dari sistem Anda akan membuat mereka melihat data terenkripsi. Jika mereka dapat menyuntikkan kode atau membuka sistem file Anda, mereka dapat melihat data yang didekripsi (karena mereka dapat mengedit file yang mendekripsi data). Segala bentuk Replay atau serangan MITM juga akan memberi mereka akses penuh ke kunci yang terlibat. Mengendus lalu lintas HTTP mentah juga akan memberi mereka kunci.

    Gunakan SSL untuk semua lalu lintas. Dan pastikan tidak ada di server yang memiliki kerentanan (CSRF, XSS, SQL Injection, Privilege Escalation, Eksekusi Kode Jarak Jauh, dll).

Sunting: Ini adalah implementasi kelas PHP dari metode enkripsi yang kuat:

/**
 * 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);
    }
}

Perhatikan bahwa saya menggunakan fungsi ditambahkan dalam PHP 5.6: hash_equals. Jika Anda berada di bawah 5.6, Anda dapat menggunakan fungsi pengganti ini yang mengimplementasikan fungsi perbandingan aman-waktu menggunakan verifikasi HMAC ganda :

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

Pemakaian:

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

Lalu, untuk mendekripsi:

$e2 = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$data = $e2->decrypt($encryptedData, $key);

Perhatikan bahwa saya menggunakan $e2kedua kalinya untuk menunjukkan kepada Anda berbagai contoh masih akan mendekripsi data dengan benar.

Sekarang, bagaimana cara kerjanya / mengapa menggunakannya di atas solusi lain:

  1. Kunci

    • Kunci tidak digunakan secara langsung. Sebagai gantinya, kunci diregangkan oleh derivasi PBKDF2 standar.

    • Kunci yang digunakan untuk enkripsi adalah unik untuk setiap blok teks terenkripsi. Karenanya, kunci yang disediakan menjadi "kunci utama". Karenanya kelas ini menyediakan rotasi kunci untuk kunci sandi dan kunci autentik.

    • CATATAN PENTING , $roundsparameter ini dikonfigurasikan untuk kunci acak sejati dengan kekuatan yang cukup (minimum 128 bit Cryptographically Secure random). Jika Anda akan menggunakan kata sandi, atau kunci non-acak (atau kurang acak dari 128 bit CS acak), Anda harus meningkatkan parameter ini. Saya menyarankan minimal 10.000 untuk kata sandi (semakin banyak yang Anda mampu, semakin baik, tetapi akan menambah runtime) ...

  2. Integritas data

    • Versi yang diperbarui menggunakan ENCRYPT-THEN-MAC, yang merupakan metode yang jauh lebih baik untuk memastikan keaslian data terenkripsi.
  3. Enkripsi:

    • Ia menggunakan mcrypt untuk benar-benar melakukan enkripsi. Saya sarankan menggunakan salah satu MCRYPT_BLOWFISHatau MCRYPT_RIJNDAEL_128sandi dan MCRYPT_MODE_CBCuntuk mode. Itu cukup kuat, dan masih cukup cepat (siklus enkripsi dan dekripsi memakan waktu sekitar 1/2 detik pada mesin saya).

Sekarang, ke poin 3 dari daftar pertama, apa yang akan memberi Anda adalah fungsi seperti ini:

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

Anda dapat merentangkannya dalam makeKey()fungsi, tetapi karena itu akan diregangkan nanti, tidak ada poin besar untuk melakukannya.

Sejauh ukuran penyimpanan, itu tergantung pada teks biasa. Blowfish menggunakan ukuran blok 8 byte, sehingga Anda akan memiliki:

  • 16 byte untuk garam
  • 64 byte untuk hmac
  • panjang data
  • Padding sehingga panjang data% 8 == 0

Jadi untuk sumber data 16 karakter, akan ada 16 karakter data yang akan dienkripsi. Jadi itu berarti ukuran data terenkripsi yang sebenarnya adalah 16 byte karena padding. Kemudian tambahkan 16 byte untuk garam dan 64 byte untuk hmac dan ukuran total yang disimpan adalah 96 byte. Jadi paling tidak ada 80 karakter overhead, dan paling buruk 87 karakter overhead ...

Saya harap itu membantu...

Catatan: 12/11/12: Saya baru saja memperbarui kelas ini dengan metode enkripsi JAUH lebih baik, menggunakan kunci turunan yang lebih baik, dan memperbaiki generasi MAC ...

ircmaxell
sumber
3
Seseorang tidak mengerti apa artinya "istirahat". @IRC pekerjaan bagus di kelas, itu kode yang sangat bagus.
jcolebrand
1
Berikut ini mengembalikan false. Ada yang tahu kenapa? $ x = Enkripsi baru (MCRYPT_BlOWFISH, MCRYPT_MODE_CBC); $ test = $ x-> mengenkripsi ("test", "a"); echo var_dump ($ x-> decrypt ($ test, "a"));
The Wavelength
2
Oh dan lagi dalam fungsi dekripsi mengubah dua -64s untuk -128membantu (sehingga Anda mendapatkan $enc = substr($data, 128, -128)dan$mac = substr($data, -128);
cosmorogers
4
@ircmaxell Sudah cukup lama sejak kode terakhir direvisi jadi saya bertanya-tanya apakah itu up to date. Saya perlu menggunakan sesuatu yang mirip untuk aplikasi keuangan dan alangkah baiknya jika Anda memberikan apa-apa dengan kelas ini :-)
nt.bas
2
Peringatan! Ekstensi mcrypt telah ditinggalkan selama hampir satu dekade sekarang, dan juga cukup rumit untuk digunakan. Karena itu telah ditinggalkan demi OpenSSL, di mana ia akan dihapus dari inti dan menjadi PECL di PHP 7.2. th1.php.net/manual/en/migration71.deprecated.php
vee
15

Bagaimana cara mengenkripsi dan mendekripsi kata sandi dalam PHP? Dengan menerapkan salah satu dari banyak algoritma enkripsi. (atau menggunakan salah satu dari banyak perpustakaan)

Algoritma apa yang paling aman untuk mengenkripsi kata sandi? Ada banyak algoritma yang berbeda, tidak ada yang 100% aman. Tetapi banyak dari mereka cukup aman untuk tujuan perdagangan dan bahkan militer

Di mana saya menyimpan kunci pribadi? Jika Anda telah memutuskan untuk mengimplementasikan kunci publik - algoritma kriptografi (misalnya RSA), Anda tidak menyimpan kunci pribadi. pengguna memiliki kunci pribadi. sistem Anda memiliki kunci publik yang dapat disimpan di mana saja Anda inginkan.

Alih-alih menyimpan kunci privat, apakah lebih baik meminta pengguna memasukkan kunci privat kapan saja mereka membutuhkan kata sandi yang didekripsi? (Pengguna aplikasi ini dapat dipercaya) Nah, jika pengguna Anda dapat mengingat bilangan prima yang sangat panjang maka - ya, mengapa tidak. Tetapi umumnya Anda harus membuat sistem yang akan memungkinkan pengguna untuk menyimpan kunci mereka di suatu tempat.

Dengan cara apa kata sandi dapat dicuri dan didekripsi? Apa yang perlu saya waspadai? Ini tergantung pada algoritma yang digunakan. Namun selalu pastikan bahwa Anda tidak mengirim kata sandi yang tidak dienkripsi ke atau dari pengguna. Enkripsi / dekripsi di sisi klien, atau gunakan https (atau pengguna alat kriptografi lainnya untuk mengamankan koneksi antara server dan klien).

Namun jika yang Anda butuhkan adalah menyimpan kata sandi dengan cara terenkripsi, saya sarankan Anda menggunakan XOR Cipher yang sederhana. Masalah utama dengan algoritma ini adalah bahwa ia dapat dengan mudah dipatahkan oleh analisis frekuensi. Namun karena umumnya kata sandi tidak dibuat dari paragraf panjang teks bahasa Inggris, saya rasa Anda tidak perlu khawatir. Masalah kedua dengan XOR Cipher adalah bahwa jika Anda memiliki pesan dalam bentuk terenkripsi dan dekripsi, Anda dapat dengan mudah menemukan kata sandi yang dienkripsi. Sekali lagi, bukan masalah besar dalam kasus Anda karena hanya mempengaruhi pengguna yang sudah dikompromikan dengan cara lain.

Ivan
sumber
Pada jawaban 3, ketika Anda mengatakan pengguna memiliki kunci pribadi, saya tidak mengerti apa artinya itu. Anda tidak menganjurkan memasukkan kunci privat ke aplikasi secara manual oleh pengguna, jadi bagaimana lagi kunci privat diteruskan ke aplikasi?
HyderA
Nah itu sedikit masalah. Kunci pribadi dapat disimpan dalam file teks dan kemudian salin disisipkan ke aplikasi. Kunci juga dapat disimpan di server tetapi dalam hal ini masih harus dienkripsi dengan beberapa algoritma enkripsi lain seperti XOR. Menggunakan XOR dalam hal ini cukup aman karena hanya ada satu pasangan kata sandi-pesan dan pesannya cukup acak sehingga analisis frekuensi dingin tidak dapat digunakan.
Ivan
4
Saya tentu tidak akan merekomendasikan menerapkan algoritma enkripsi sendiri, ada terlalu banyak potensi jebakan dan perpustakaan yang ada telah diuji dan dianalisis oleh banyak orang.
Telinga Panjang
Masalah utama dengan XOR adalah jika seseorang mencuri data aplikasi Anda dan hanya mengetahui salah satu kata sandi pengguna, mereka dapat mendekripsi semua kata sandi lainnya untuk pengguna tersebut.
Telinga Panjang
1
@Van: ya, tapi ini adalah salah satu kasus ketika saya pikir DIY benar- benar buruk kecuali Anda BENAR-BENAR memahami kriptografi. Ada cipher kuat yang ada, mengapa tidak menggunakannya?
ircmaxell
13
  1. Fungsi PHP yang Anda cari adalah Mcrypt ( http://www.php.net/manual/en/intro.mcrypt.php ).

Contoh dari manual sedikit diedit untuk contoh ini):

<?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";
?>

Anda akan menggunakan mcrypt_decrypt untuk mendekripsi kata sandi Anda.

  1. Algoritma terbaik agak subyektif - tanyakan 5 orang, dapatkan 5 jawaban. Secara pribadi jika default (Blowfish) tidak cukup baik untuk Anda, Anda mungkin memiliki masalah lebih besar!

  2. Mengingat bahwa diperlukan oleh PHP untuk mengenkripsi - tidak yakin Anda dapat menyembunyikannya di mana saja - selamat datang komentar tentang ini. Praktik pengkodean PHP standar terbaik tentu saja berlaku!

  3. Mengingat bahwa kunci enkripsi akan tetap ada dalam kode Anda, tidak yakin apa yang akan Anda peroleh, asalkan sisa aplikasi Anda aman.

  4. Jelas, jika kata sandi terenkripsi dan kunci enkripsi dicuri, maka game over.

Saya akan menempatkan pengendara pada jawaban saya - saya bukan ahli PHP crypto, tapi, saya pikir apa yang saya jawab adalah praktik standar - saya menyambut komentar yang mungkin dimiliki orang lain.

Jon Rhoades
sumber
$pass = $text. Saya pikir dia mengubahnya untuk memenuhi pertanyaan, dan tidak melihat kejadian kedua.
HyderA
3
Dua hal yang perlu diperhatikan. Pertama, MCRYPT_MODE_ECBtidak menggunakan infus. Kedua, jika itu terjadi, Anda harus menyimpan IV karena Anda tidak dapat mendekripsi data tanpa itu ...
ircmaxell
"Algoritma terbaik agak subyektif - tanyakan 5 orang, dapatkan 5 jawaban. Secara pribadi jika default (Blowfish) tidak cukup baik untuk Anda, Anda mungkin memiliki masalah lebih besar!" Ini benar-benar salah. Setiap ahli crypto akan lebih atau kurang setuju dengan gist.github.com/tqbf/be58d2d39690c3b366ad yang secara khusus tidak termasuk
ikan
6

Banyak pengguna menyarankan menggunakan mcrypt ... yang benar, tetapi saya ingin melangkah lebih jauh untuk membuatnya lebih mudah disimpan dan ditransfer (karena kadang-kadang nilai yang dienkripsi dapat membuat mereka sulit dikirim menggunakan teknologi lain seperti curl, atau json) .

Setelah Anda berhasil dienkripsi menggunakan mcrypt, jalankan melalui base64_encode dan kemudian konversikan ke kode hex. Sekali dalam kode hex mudah untuk mentransfer dalam berbagai cara.

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

Dan di sisi lain:

$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);
Bradley
sumber
Mcrypt bukan pilihan bagus
Scott Arciszewski
2
Nah - itu pada tahun 2011: P
Bradley
5

Saya hanya menyarankan enkripsi kunci publik jika Anda ingin kemampuan untuk mengatur kata sandi pengguna tanpa interaksi mereka (ini dapat berguna untuk mengatur ulang dan kata sandi bersama).

Kunci publik

  1. The OpenSSL ekstensi, khususnya openssl_public_encryptdanopenssl_private_decrypt
  2. Ini akan menjadi RSA langsung dengan asumsi kata sandi Anda akan cocok dengan ukuran kunci - padding, jika tidak, Anda perlu lapisan simetris
  3. Simpan kedua kunci untuk setiap pengguna, frasa sandi kunci pribadi adalah kata sandi aplikasi mereka

Simetris

  1. The mcrypt extension
  2. AES-256 mungkin merupakan taruhan yang aman, tetapi ini bisa menjadi pertanyaan SO sendiri
  3. Anda tidak - ini akan menjadi kata sandi aplikasi mereka

Kedua

4. Ya - pengguna harus memasukkan kata sandi aplikasi mereka setiap saat, tetapi menyimpannya di sesi akan menimbulkan masalah lain

5.

  • Jika seseorang mencuri data aplikasi, itu sama amannya dengan sandi simetris (untuk skema kunci publik, itu digunakan untuk melindungi kunci pribadi dengan frasa sandi.)
  • Aplikasi Anda seharusnya hanya dapat diakses melalui SSL, lebih disukai menggunakan sertifikat klien.
  • Pertimbangkan untuk menambahkan faktor kedua untuk otentikasi yang hanya akan digunakan sekali per sesi, seperti token yang dikirim melalui SMS.
Telinga panjang
sumber
Hindari mcrypt, hati-hati dengan openssl_private_decrypt().
Scott Arciszewski
2

Saya mencoba sesuatu seperti ini tetapi harap dicatat bahwa saya bukan cryptographer atau saya memiliki pengetahuan mendalam tentang phpatau bahasa pemrograman apa pun. Itu hanya sebuah ide. Gagasan saya adalah menyimpan keydalam beberapa file atau database(atau memasukkan secara manual) yang (lokasi) tidak dapat diprediksi dengan mudah (Dan tentu saja apa pun akan didekripsi suatu hari nanti, konsepnya adalah untuk memperpanjang waktu dekripsi) dan mengenkripsi informasi sensitif.

$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH , MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "evenifyouaccessmydatabaseyouwillneverfindmyemail";
$text = "[email protected]";
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.

Harap dicatat bahwa ini hanyalah sebuah konsep. Setiap perbaikan pada kode ini akan sangat dihargai.

Santosh Linkha
sumber
2

Kata sandi untuk perangkat perangkat keras, jadi memeriksa hash tidak perlu dilakukan

Eh? Saya tidak mengerti. Apakah maksud Anda kata sandi itu harus dapat dipulihkan?

Seperti yang orang lain katakan, ekstensi mcrypt menyediakan akses ke banyak fungsi kriptografi - namun Anda mengundang pengguna untuk meletakkan semua telur mereka dalam satu keranjang - yang akan berpotensi menjadi sasaran penyerang - dan jika Anda bahkan tidak tahu bagaimana memulai memecahkan masalah maka Anda melakukan merugikan pengguna. Anda tidak dalam posisi untuk memahami bagaimana melindungi data.

Sebagian besar kerentanan keamanan muncul bukan karena algoritma yang mendasarinya cacat atau tidak aman - tetapi karena masalah dengan cara algoritma digunakan dalam kode aplikasi.

Karena itu, adalah mungkin untuk membangun sistem yang cukup aman.

Anda hanya harus mempertimbangkan enkripsi asimetris jika Anda memiliki persyaratan bagi pengguna untuk membuat pesan aman yang dapat dibaca oleh pengguna (spesifik) lainnya. Alasannya karena harganya yang mahal. Jika Anda hanya ingin memberikan repositori bagi pengguna untuk memasukkan dan mengambil data mereka sendiri, enkripsi simetris memadai.

Namun, jika Anda menyimpan kunci untuk mendekripsi pesan di tempat yang sama dengan pesan terenkripsi (atau di mana pesan terenkripsi disimpan) maka sistem tidak aman. Gunakan token yang sama untuk mengautentikasi pengguna seperti untuk kunci dekripsi (atau dalam hal enkripsi asimetris, gunakan token sebagai frasa kunci pribadi). Karena Anda harus menyimpan token di server tempat dekripsi berlangsung setidaknya untuk sementara, Anda mungkin ingin mempertimbangkan untuk menggunakan substrat penyimpanan sesi yang tidak dapat dicari, atau meneruskan token langsung ke daemon yang terkait dengan sesi yang akan menyimpan token dalam memori dan melakukan dekripsi pesan sesuai permintaan.

symcbean
sumber
1

Gunakan password_hash dan 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";
?>

Dan untuk mendekripsi:

<?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.';
}
?>
jvitoroc
sumber