Saat ini saya adalah seorang pelajar dan saya sedang belajar PHP, saya mencoba membuat enkripsi / dekripsi data sederhana dalam PHP. Saya melakukan beberapa riset online dan beberapa di antaranya cukup membingungkan (setidaknya bagi saya).
Inilah yang saya coba lakukan:
Saya memiliki tabel yang terdiri dari bidang-bidang ini (UserID, Fname, Lname, Email, Password)
Yang ingin saya miliki adalah semua bidang dienkripsi dan kemudian didekripsi (Apakah mungkin digunakan sha256
untuk enkripsi / dekripsi, jika bukan algoritma enkripsi apa pun)
Hal lain yang ingin saya pelajari adalah bagaimana membuat satu cara yang hash(sha256)
dikombinasikan dengan "garam" yang baik. (Pada dasarnya saya hanya ingin implementasi enkripsi / dekripsi sederhana, hash(sha256)+salt)
Pak / Bu, jawaban Anda akan sangat membantu dan sangat kami hargai. Terima kasih ++
sumber
Jawaban:
Kata pengantar
Dimulai dengan definisi tabel Anda:
Berikut perubahannya:
Fname
,Lname
danEmail
akan dienkripsi menggunakan cipher simetris, disediakan oleh OpenSSL ,IV
lapangan akan menyimpan vektor inisialisasi yang digunakan untuk enkripsi. Persyaratan penyimpanan tergantung pada sandi dan mode yang digunakan; lebih lanjut tentang ini nanti.Password
lapangan akan diacak dengan menggunakan satu arah hash password,Enkripsi
Sandi dan mode
Memilih cipher dan mode enkripsi terbaik berada di luar cakupan jawaban ini, tetapi pilihan terakhir memengaruhi ukuran kunci enkripsi dan vektor inisialisasi; untuk posting ini kita akan menggunakan AES-256-CBC yang memiliki ukuran blok tetap 16 byte dan ukuran kunci 16, 24 atau 32 byte.
Kunci enkripsi
Kunci enkripsi yang baik adalah gumpalan biner yang dihasilkan dari generator nomor acak yang andal. Contoh berikut akan direkomendasikan (> = 5.3):
Ini dapat dilakukan sekali atau beberapa kali (jika Anda ingin membuat rantai kunci enkripsi). Jaga kerahasiaannya sebisa mungkin.
IV
Vektor inisialisasi menambahkan keacakan pada enkripsi dan diperlukan untuk mode CBC. Nilai-nilai ini idealnya harus digunakan hanya sekali (secara teknis sekali per kunci enkripsi), jadi pembaruan ke bagian mana pun dari baris harus memperbaruinya.
Sebuah fungsi disediakan untuk membantu Anda menghasilkan IV:
Contoh
Mari mengenkripsi bidang nama, menggunakan yang sebelumnya
$encryption_key
dan$iv
; untuk melakukan ini, kita harus memasukkan data kita ke ukuran blok:Persyaratan penyimpanan
Output terenkripsi, seperti IV, adalah biner; Menyimpan nilai-nilai ini dalam database bisa dilakukan dengan menggunakan tipe kolom yang ditentukan seperti
BINARY
atauVARBINARY
.Nilai keluaran, seperti IV, adalah biner; untuk menyimpan nilai-nilai tersebut di MySQL, pertimbangkan untuk menggunakan kolom
BINARY
atauVARBINARY
. Jika ini bukan pilihan, Anda juga dapat mengonversi data biner menjadi representasi tekstual menggunakanbase64_encode()
ataubin2hex()
, melakukannya membutuhkan ruang penyimpanan antara 33% hingga 100% lebih banyak.Dekripsi
Dekripsi dari nilai yang disimpan serupa:
Enkripsi terautentikasi
Anda selanjutnya dapat meningkatkan integritas teks sandi yang dihasilkan dengan menambahkan tanda tangan yang dihasilkan dari kunci rahasia (berbeda dari kunci enkripsi) dan teks sandi. Sebelum teks sandi didekripsi, tanda tangan diverifikasi terlebih dahulu (sebaiknya dengan metode perbandingan waktu konstan).
Contoh
Lihat juga:
hash_equals()
Hashing
Menyimpan kata sandi yang dapat dibalik dalam database Anda harus sebisa mungkin dihindari; Anda hanya ingin memverifikasi kata sandi daripada mengetahui isinya. Jika pengguna kehilangan kata sandinya, lebih baik izinkan mereka menyetel ulang daripada mengirimkan kata sandi asli kepada mereka (pastikan penyetelan ulang kata sandi hanya dapat dilakukan untuk waktu yang terbatas).
Menerapkan fungsi hash adalah operasi satu arah; setelah itu dapat digunakan dengan aman untuk verifikasi tanpa mengungkap data asli; untuk kata sandi, metode brute force adalah pendekatan yang layak untuk mengungkapnya karena panjangnya yang relatif pendek dan pilihan kata sandi yang buruk dari banyak orang.
Algoritme hash seperti MD5 atau SHA1 dibuat untuk memverifikasi konten file terhadap nilai hash yang diketahui. Mereka sangat dioptimalkan untuk membuat verifikasi ini secepat mungkin dengan tetap akurat. Mengingat ruang keluaran yang relatif terbatas, mudah untuk membangun database dengan kata sandi yang diketahui dan keluaran hash masing-masing, tabel pelangi.
Menambahkan salt ke kata sandi sebelum melakukan hashing akan membuat tabel pelangi tidak berguna, tetapi kemajuan perangkat keras baru-baru ini membuat pencarian brute force menjadi pendekatan yang layak. Itulah mengapa Anda memerlukan algoritme hashing yang sengaja lambat dan tidak mungkin dioptimalkan. Ini juga harus dapat meningkatkan beban untuk perangkat keras yang lebih cepat tanpa mempengaruhi kemampuan untuk memverifikasi hash kata sandi yang ada untuk membuatnya menjadi bukti di masa mendatang.
Saat ini ada dua pilihan populer yang tersedia:
Jawaban ini akan menggunakan contoh dengan bcrypt.
Generasi
Hash kata sandi dapat dibuat seperti ini:
Salt dibuat
openssl_random_pseudo_bytes()
untuk membentuk gumpalan data acak yang kemudian dijalankanbase64_encode()
danstrtr()
dicocokkan dengan alfabet yang diperlukan[A-Za-z0-9/.]
.The
crypt()
melakukan fungsi hashing berdasarkan algoritma ($2y$
untuk Blowfish), faktor biaya (faktor dari 13 Dibutuhkan sekitar 0.40s pada mesin 3GHz) dan garam 22 karakter.Validasi
Setelah Anda mengambil baris yang berisi informasi pengguna, Anda memvalidasi kata sandi dengan cara ini:
Untuk memverifikasi kata sandi, Anda memanggil
crypt()
lagi tetapi Anda meneruskan hash yang dihitung sebelumnya sebagai nilai garam. Nilai yang dikembalikan menghasilkan hash yang sama jika kata sandi yang diberikan cocok dengan hash. Untuk memverifikasi hash, sering kali disarankan untuk menggunakan fungsi perbandingan waktu konstan untuk menghindari serangan waktu.Hash sandi dengan PHP 5.5
PHP 5.5 memperkenalkan fungsi hashing kata sandi yang dapat Anda gunakan untuk menyederhanakan metode hashing di atas:
Dan memverifikasi:
Lihat juga:
password_hash()
,password_verify()
sumber
$iv_size = 16;
, saya akan menggunakan:$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("AES-256-CBC"))
untuk menunjukkan hubungan antara ukuran iv untuk digunakan dengan sandi yang digunakan. Anda juga dapat memperluas sedikit tentang kebutuhan (atau tidak) daripkcs7_pad()
/pkcs7_unpad()
, atau cukup sederhanakan posting dengan menyingkirkannya dan menggunakan "aes-256-ctr". Pos hebat @ Ja͢ckSaya pikir ini telah dijawab sebelumnya ... tetapi bagaimanapun, jika Anda ingin mengenkripsi / mendekripsi data, Anda tidak dapat menggunakan SHA256
sumber
Latar Belakang Jawaban dan Penjelasan
Untuk memahami pertanyaan ini, Anda harus terlebih dahulu memahami apa itu SHA256. SHA256 adalah Fungsi Hash Kriptografi . Fungsi Hash Cryptographic adalah fungsi satu arah, yang keluarannya aman secara kriptografis. Ini berarti mudah untuk menghitung hash (setara dengan mengenkripsi data), tetapi sulit mendapatkan input asli menggunakan hash (setara dengan mendekripsi data). Karena menggunakan fungsi hash Cryptographic berarti dekripsi tidak layak secara komputasi, jadi oleh karena itu Anda tidak dapat melakukan dekripsi dengan SHA256.
Yang ingin Anda gunakan adalah fungsi dua arah, tetapi lebih khusus lagi, Block Cipher . Sebuah fungsi yang memungkinkan enkripsi dan dekripsi data. Fungsi
mcrypt_encrypt
danmcrypt_decrypt
secara default menggunakan algoritma Blowfish. Penggunaan mcrypt PHP dapat ditemukan di manual ini . Daftar definisi cipher untuk memilih penggunaan cipher mcrypt juga ada. Wiki tentang Blowfish dapat ditemukan di Wikipedia . Sebuah cipher blok mengenkripsi input dalam blok dengan ukuran dan posisi yang diketahui dengan kunci yang diketahui, sehingga data tersebut nantinya dapat didekripsi menggunakan kunci tersebut. Inilah yang tidak dapat disediakan SHA256 untuk Anda.Kode
sumber
Berikut ini contoh penggunaan openssl_encrypt
sumber
mcrypt_create_iv()
, saya akan menggunakanopenssl_random_pseudo_bytes(openssl_cipher_iv_length($encryptionMethod))
:, dengan cara ini metodologi bekerja untuk nilai apa pun dari $ encryptionMethod dan hanya akan menggunakan ekstensi openssl.false
untukopenssl_decrypt()
. Lihat stackoverflow.com/q/41952509/1066234 Karena cipher blok seperti AES memerlukan data input untuk menjadi kelipatan yang tepat dari ukuran blok (16-byte untuk AES) padding diperlukan.sumber
Butuh waktu cukup lama bagi saya untuk mencari tahu, bagaimana tidak mendapatkan
false
saat menggunakanopenssl_decrypt()
dan mendapatkan enkripsi dan dekripsi berfungsi.Jika Anda ingin meneruskan string yang dienkripsi melalui URL, Anda perlu melakukan urlencode string tersebut:
Untuk lebih memahami apa yang sedang terjadi, baca:
Untuk menghasilkan kunci panjang 16 byte, Anda dapat menggunakan:
Untuk melihat pesan error openssl Anda dapat menggunakan:
echo openssl_error_string();
Semoga membantu.
sumber