Apakah Python memiliki cara bawaan dan sederhana untuk mengenkode / mendekode string menggunakan kata sandi?
Sesuatu seperti ini:
>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'
Jadi string "John Doe" akan dienkripsi sebagai 'sjkl28cn2sx0'. Untuk mendapatkan string asli, saya akan "membuka" string itu dengan kunci 'mypass', yang merupakan sandi dalam kode sumber saya. Saya ingin ini menjadi cara saya mengenkripsi / mendekripsi dokumen Word dengan kata sandi.
Saya ingin menggunakan string terenkripsi ini sebagai parameter URL. Tujuan saya adalah kebingungan, bukan keamanan yang kuat; tidak ada misi penting yang dikodekan. Saya menyadari bahwa saya dapat menggunakan tabel database untuk menyimpan kunci dan nilai, tetapi saya berusaha untuk minimalis.
python
encryption
passwords
RexE
sumber
sumber
Jawaban:
Dengan asumsi Anda hanya mencari kebingungan sederhana yang akan mengaburkan hal-hal dari pengamat yang sangat biasa, dan Anda tidak ingin menggunakan pustaka pihak ketiga. Saya akan merekomendasikan sesuatu seperti sandi Vigenere. Ini adalah salah satu yang terkuat dari sandi kuno sederhana.
Sandi Vigenère
Cepat dan mudah diterapkan. Sesuatu seperti:
Dekode kurang lebih sama, kecuali Anda mengurangi kuncinya.
Jauh lebih sulit untuk memutuskan jika string yang Anda enkode pendek, dan / atau sulit menebak panjang frasa sandi yang digunakan.
Jika Anda mencari sesuatu yang kriptografik, PyCrypto mungkin adalah pilihan terbaik Anda, meskipun jawaban sebelumnya mengabaikan beberapa detail: Mode ECB di PyCrypto mengharuskan pesan Anda terdiri dari kelipatan 16 karakter. Jadi, Anda harus pad. Selain itu, jika Anda ingin menggunakannya sebagai parameter URL, gunakan
base64.urlsafe_b64_encode()
, bukan yang standar. Ini menggantikan beberapa karakter dalam alfabet base64 dengan karakter aman URL (seperti yang disarankan namanya).Namun, Anda harus BENAR-BENAR yakin bahwa lapisan yang sangat tipis dari obfuscation ini cukup untuk kebutuhan Anda sebelum menggunakan ini. Artikel Wikipedia yang saya tautkan memberikan instruksi terperinci untuk memecahkan sandi, jadi siapa pun dengan tekad yang moderat dapat dengan mudah memecahkannya.
sumber
'str' object cannot be interpreted as an integer
Saat Anda secara eksplisit menyatakan bahwa Anda menginginkan ketidakjelasan, bukan keamanan, kami tidak akan menegur Anda karena kelemahan dari apa yang Anda sarankan :)
Jadi, menggunakan PyCrypto:
Jika seseorang mendapatkan database Anda dan basis kode Anda, mereka akan dapat memecahkan kode data yang dienkripsi. Jaga
secret_key
keamananmu!sumber
encrypt
fungsi khusus ini adalah stateful dlitz.net/software/pycrypto/api/current/… jadi Anda tidak boleh mencoba dan menggunakannya kembali.Python tidak memiliki skema enkripsi built-in, tidak. Anda juga harus menganggap serius penyimpanan data terenkripsi; Skema enkripsi sepele yang dipahami oleh satu pengembang sebagai tidak aman dan skema mainan mungkin disalahartikan sebagai skema aman oleh pengembang yang kurang berpengalaman. Jika Anda mengenkripsi, enkripsi dengan benar.
Namun, Anda tidak perlu melakukan banyak pekerjaan untuk menerapkan skema enkripsi yang tepat. Pertama-tama, jangan menemukan kembali roda kriptografi , gunakan pustaka kriptografi tepercaya untuk menangani ini untuk Anda. Untuk Python 3, pustaka tepercaya itu adalah
cryptography
.Saya juga merekomendasikan bahwa enkripsi dan dekripsi berlaku untuk byte ; menyandikan pesan teks menjadi byte terlebih dahulu;
stringvalue.encode()
menyandikan ke UTF8, dengan mudah dikembalikan lagi menggunakanbytesvalue.decode()
.Last but not least, ketika mengenkripsi dan mendekripsi, kita berbicara tentang kunci , bukan kata sandi. Kunci tidak boleh mudah diingat manusia, ini adalah sesuatu yang Anda simpan di lokasi rahasia tetapi dapat dibaca oleh mesin, sedangkan kata sandi seringkali dapat dibaca dan diingat oleh manusia. Anda dapat memperoleh kunci dari kata sandi, dengan sedikit hati-hati.
Tetapi untuk aplikasi web atau proses yang berjalan dalam cluster tanpa perhatian manusia untuk tetap menjalankannya, Anda ingin menggunakan kunci. Kata sandi digunakan ketika hanya pengguna akhir yang membutuhkan akses ke informasi tertentu. Meski begitu, Anda biasanya mengamankan aplikasi dengan kata sandi, kemudian bertukar informasi terenkripsi menggunakan kunci, mungkin yang dilampirkan ke akun pengguna.
Enkripsi kunci simetris
Fernet - AES CBC + HMAC, sangat disarankan
The
cryptography
perpustakaan meliputi resep Fernet , resep-praktek terbaik untuk menggunakan kriptografi. Fernet adalah standar terbuka , dengan implementasi siap dalam berbagai bahasa pemrograman dan paket enkripsi AES CBC untuk Anda dengan informasi versi, stempel waktu, dan tanda tangan HMAC untuk mencegah gangguan pesan.Fernet membuatnya sangat mudah untuk mengenkripsi dan mendekripsi pesan dan membuat Anda tetap aman. Ini adalah metode ideal untuk mengenkripsi data dengan rahasia.
Saya sarankan Anda menggunakan
Fernet.generate_key()
untuk menghasilkan kunci aman. Anda juga dapat menggunakan kata sandi (bagian selanjutnya), tetapi kunci rahasia 32-byte penuh (16 byte untuk dienkripsi, ditambah 16 byte lainnya untuk tanda tangan) akan lebih aman daripada kebanyakan kata sandi yang dapat Anda pikirkan.Kunci yang dihasilkan Fernet adalah
bytes
objek dengan URL dan karakter base64 yang aman untuk file, sehingga dapat dicetak:Untuk mengenkripsi atau mendekripsi pesan, buat
Fernet()
instance dengan kunci yang diberikan, dan panggilFernet.encrypt()
atauFernet.decrypt()
, pesan teks biasa untuk dienkripsi dan token yang dienkripsi adalahbytes
objek.encrypt()
dandecrypt()
fungsinya akan terlihat seperti:Demo:
Fernet dengan kata sandi - kunci yang berasal dari kata sandi, agak melemahkan keamanan
Anda dapat menggunakan sandi sebagai ganti kunci rahasia, asalkan Anda menggunakan metode derivasi kunci yang kuat . Anda kemudian harus menyertakan salt dan hitungan iterasi HMAC dalam pesan, sehingga nilai yang dienkripsi tidak lagi kompatibel dengan Fernet tanpa terlebih dahulu memisahkan token salt, count dan Fernet:
Demo:
Menyertakan salt dalam output memungkinkan untuk menggunakan nilai salt acak, yang pada gilirannya memastikan output terenkripsi dijamin sepenuhnya acak terlepas dari penggunaan ulang sandi atau pengulangan pesan. Menyertakan hitungan iterasi memastikan bahwa Anda dapat menyesuaikan agar kinerja CPU meningkat seiring waktu tanpa kehilangan kemampuan untuk mendekripsi pesan yang lebih lama.
Kata sandi saja bisa seaman kunci acak Fernet 32-byte, asalkan Anda membuat kata sandi acak yang benar dari kumpulan ukuran yang sama. 32 byte memberi Anda 256 ^ 32 jumlah kunci, jadi jika Anda menggunakan alfabet dengan 74 karakter (26 atas, 26 lebih rendah, 10 digit dan 12 simbol yang mungkin), maka kata sandi Anda harus setidaknya
math.ceil(math.log(256 ** 32, 74))
== 42 karakter. Namun, sejumlah besar iterasi HMAC yang dipilih dengan baik dapat mengurangi kurangnya entropi karena ini membuatnya jauh lebih mahal bagi penyerang untuk memaksa masuk secara brutal.Ketahuilah bahwa memilih kata sandi yang lebih pendek tetapi masih cukup aman tidak akan melumpuhkan skema ini, ini hanya mengurangi jumlah kemungkinan nilai yang harus dicari oleh penyerang brute force; pastikan untuk memilih kata sandi yang cukup kuat untuk kebutuhan keamanan Anda .
Alternatif
Mengaburkan
Alternatifnya adalah tidak mengenkripsi . Jangan tergoda untuk hanya menggunakan sandi dengan keamanan rendah, atau implementasi rumahan, katakanlah Vignere. Tidak ada keamanan dalam pendekatan ini, tetapi dapat memberikan pengembang yang tidak berpengalaman yang diberi tugas untuk menjaga kode Anda di masa depan ilusi keamanan, yang lebih buruk daripada tidak ada keamanan sama sekali.
Jika yang Anda butuhkan hanyalah ketidakjelasan, cukup base64 datanya; untuk persyaratan aman URL,
base64.urlsafe_b64encode()
fungsinya baik-baik saja. Jangan gunakan kata sandi di sini, cukup encode dan Anda selesai. Paling banyak, tambahkan beberapa kompresi (sepertizlib
):Ini berubah
b'Hello world!'
menjadib'eNrzSM3JyVcozy_KSVEEAB0JBF4='
.Integritas saja
Jika yang Anda butuhkan hanyalah cara untuk memastikan bahwa data dapat dipercaya tidak diubah setelah dikirim ke klien yang tidak tepercaya dan diterima kembali, maka Anda ingin menandatangani data, Anda dapat menggunakan
hmac
perpustakaan untuk ini dengan SHA1 (masih dianggap aman untuk penandatanganan HMAC ) atau lebih baik:Gunakan ini untuk menandatangani data, lalu lampirkan tanda tangan dengan data dan kirimkan ke klien. Saat Anda menerima data kembali, pisahkan data dan tanda tangan dan verifikasi. Saya telah menetapkan algoritme default ke SHA256, jadi Anda memerlukan kunci 32-byte:
Anda mungkin ingin melihat
itsdangerous
perpustakaan , yang mengemas semua ini dengan serialisasi dan de-serialisasi dalam berbagai format.Menggunakan enkripsi AES-GCM untuk memberikan enkripsi dan integritas
Fernet mengembangkan AEC-CBC dengan tanda tangan HMAC untuk memastikan integritas data terenkripsi; penyerang jahat tidak dapat memberi makan data sistem Anda yang tidak masuk akal untuk membuat layanan Anda sibuk berjalan berputar-putar dengan masukan yang buruk, karena ciphertext ditandatangani.
The blok modus Galois / Kontra cipher menghasilkan ciphertext dan tag untuk melayani tujuan yang sama, sehingga dapat digunakan untuk melayani tujuan yang sama. Kelemahannya adalah tidak seperti Fernet, tidak ada resep satu ukuran untuk semua yang mudah digunakan untuk digunakan kembali di platform lain. AES-GCM juga tidak menggunakan padding, jadi ciphertext enkripsi ini cocok dengan panjang pesan input (sedangkan Fernet / AES-CBC mengenkripsi pesan ke blok dengan panjang tetap, agak mengaburkan panjang pesan).
AES256-GCM menggunakan rahasia 32 byte biasa sebagai kunci:
lalu gunakan
Saya telah menyertakan stempel waktu untuk mendukung kasus penggunaan waktu-ke-langsung yang didukung Fernet.
Pendekatan lain di halaman ini, dengan Python 3
AES CFB - seperti CBC tetapi tanpa perlu bantalan
Ini adalah pendekatan yang diikuti All Іѕ Vаиітy , meskipun salah. Ini adalah
cryptography
versinya, tetapi perhatikan bahwa saya menyertakan IV di ciphertext , itu tidak boleh disimpan sebagai global (menggunakan kembali IV melemahkan keamanan kunci, dan menyimpannya sebagai modul global berarti itu akan dihasilkan kembali permintaan Python berikutnya, membuat semua ciphertext tidak dapat dienkripsi):Ini tidak memiliki pelindung tambahan dari tanda tangan HMAC dan tidak ada stempel waktu; Anda harus menambahkannya sendiri.
Hal di atas juga menggambarkan betapa mudahnya menggabungkan blok penyusun kriptografi dasar secara tidak benar; Semua penanganan Vаиітy yang salah atas nilai IV dapat menyebabkan pelanggaran data atau semua pesan terenkripsi tidak dapat dibaca karena IV hilang. Menggunakan Fernet malah melindungi Anda dari kesalahan semacam itu.
AES ECB - tidak aman
Jika sebelumnya Anda menerapkan enkripsi AES ECB dan masih perlu mendukungnya di Python 3, Anda juga dapat melakukannya
cryptography
. Peringatan yang sama berlaku, ECB tidak cukup aman untuk aplikasi kehidupan nyata . Mengimplementasikan ulang jawaban itu untuk Python 3, menambahkan penanganan padding otomatis:Sekali lagi, ini tidak memiliki tanda tangan HMAC, dan Anda tidak boleh menggunakan ECB. Hal di atas hanya untuk ilustrasi yang
cryptography
dapat menangani blok penyusun kriptografi umum, bahkan yang seharusnya tidak Anda gunakan.sumber
"Encoded_c" yang disebutkan dalam jawaban sandi Vigenere @ smehmood harus "key_c".
Berikut adalah fungsi encode / decode yang berfungsi.
Penafian: Seperti yang tersirat dalam komentar, ini tidak boleh digunakan untuk melindungi data dalam aplikasi nyata, kecuali Anda membaca ini dan tidak keberatan berbicara dengan pengacara:
Apa yang salah dengan enkripsi XOR?
sumber
encodedmsg = encode('mypassword', 'this is the message éçàèç"')
print encodedmsg
print decode('mypassword', encodedmsg)
berfungsi dengan baik.Berikut adalah versi Python 3 fungsi dari jawaban @qneill :
Enkode / dekode tambahan diperlukan karena Python 3 telah membagi larik string / byte menjadi dua konsep berbeda, dan memperbarui API mereka untuk mencerminkan hal itu ..
sumber
.encode()).decode()
. di balikencode()
, dan.decode()
di baris kedua masukdecode()
.Penafian: Seperti yang disebutkan dalam komentar, ini tidak boleh digunakan untuk melindungi data dalam aplikasi nyata.
Apa yang salah dengan enkripsi XOR?
/crypto/56281/breaking-a-xor-cipher-of-known-key-length
https://github.com/hellman/xortool
Seperti yang telah disebutkan, pustaka PyCrypto berisi serangkaian cipher. "Sandi" XOR dapat digunakan untuk melakukan pekerjaan kotor jika Anda tidak ingin melakukannya sendiri:
Sandi bekerja sebagai berikut tanpa harus memasukkan teks biasa:
Kredit ke https://stackoverflow.com/a/2490376/241294 untuk fungsi encode / decode base64 (saya pemula python).
sumber
sudo pip3 install pycrypto
.Berikut implementasi enkripsi dan Dekripsi Aman URL menggunakan AES (PyCrypto) dan base64.
Jika Anda menghadapi beberapa masalah seperti ini https://bugs.python.org/issue4329 (
TypeError: character mapping must return integer, None or unicode
) gunakanstr(cipher)
saat decoding sebagai berikut:Uji:
sumber
TypeError: Object type <class 'str'> cannot be passed to C code
.b'...'
, saya mengedit jawabannya untuk referensi di masa mendatang!Fungsi encode / decode yang berfungsi di python3 (diadaptasi sangat sedikit dari jawaban qneill):
sumber
Terima kasih atas jawaban yang bagus. Tidak ada yang orisinal untuk ditambahkan, tetapi berikut adalah beberapa penulisan ulang progresif dari jawaban qneill menggunakan beberapa fasilitas Python yang berguna. Saya harap Anda setuju bahwa mereka menyederhanakan dan mengklarifikasi kode.
sumber
Jika Anda ingin aman, Anda dapat menggunakan Fernet, yang terdengar secara kriptografis. Anda dapat menggunakan "garam" statis jika Anda tidak ingin menyimpannya secara terpisah - Anda hanya akan kehilangan kamus dan pencegahan serangan pelangi. Saya memilihnya karena saya dapat memilih kata sandi panjang atau pendek ', yang tidak mudah dilakukan dengan AES.
Jika itu terlalu rumit, seseorang menyarankan simplecrypt
sumber
Siapa pun yang datang ke sini (dan bountier) tampaknya mencari satu baris dengan tidak banyak pengaturan, yang tidak disediakan oleh jawaban lain. Jadi saya mengedepankan base64.
Sekarang, perlu diingat bahwa ini hanyalah pengaburan dasar, dan dalam ** TIDAK ADA CARA BISA UNTUK KEAMANAN ** , tetapi berikut adalah beberapa kalimat satu kalimat:
Beberapa hal yang perlu diperhatikan:
bytes()
danbytes::decode()
=
karakter. Orang-orang seperti saya benar-benar berkeliling memecahkan kode mereka di konsol javascript ketika kita melihatnya di situs web. Semudah itubtoa(string)
(js)Sekarang, jika yang Anda inginkan bahkan tidak memerlukan kunci apa pun, tetapi hanya beberapa kebingungan, Anda dapat menggunakan base64 lagi, tanpa kunci apa pun:
sumber
Fernet(key).encrypt(message)
hanya satu ekspresi seperti panggilan base64 Anda.key
sama sekali. Banyak pengembang akan menyalin dan menempel dari Stack Overflow tanpa memperhatikan dan akan menganggap kuncinya sebagai rahasia. Jika Anda harus memasukkannya, paling tidak jangan gunakan dan peringatkan atau buat pengecualian jika tetap digunakan. Jangan meremehkan kebodohan budaya salin dan tempel dan tanggung jawab Anda untuk memberikan fungsi yang waras.Saya akan memberikan 4 solusi:
1) Menggunakan enkripsi Fernet dengan
cryptography
perpustakaanBerikut adalah solusi menggunakan paket
cryptography
yang dapat Anda instal seperti biasa denganpip install cryptography
:Anda dapat menyesuaikan dengan salt Anda sendiri, jumlah iterasi, dll. Kode ini tidak terlalu jauh dari jawaban @ HCLivess tetapi tujuannya adalah di sini untuk memiliki fungsi
encrypt
dan siap pakaidecrypt
. Sumber: https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet .Catatan: gunakan
.encode()
dan di.decode()
mana - mana jika Anda menginginkan string,'John Doe'
bukan byte sepertib'John Doe'
.2) Enkripsi AES sederhana dengan
Crypto
perpustakaanIni bekerja dengan Python 3:
Catatan: Anda dapat menghapus
base64.b64encode
dan.b64decode
jika Anda tidak ingin output yang dapat dibaca teks dan / atau jika Anda ingin menyimpan ciphertext ke disk sebagai file biner.3) AES menggunakan fungsi derivasi kunci kata sandi yang lebih baik dan kemampuan untuk menguji apakah "kata sandi salah dimasukkan", dengan
Crypto
perpustakaanSolusi 2) dengan AES "mode CFB" baik-baik saja, tetapi memiliki dua kelemahan: fakta yang
SHA256(password)
dapat dengan mudah dipaksakan dengan tabel pencarian, dan bahwa tidak ada cara untuk menguji apakah sandi yang dimasukkan salah. Ini diselesaikan di sini dengan menggunakan AES dalam "mode GCM", sebagaimana dibahas dalam AES: bagaimana cara mendeteksi bahwa sandi yang salah telah dimasukkan? dan Apakah metode untuk mengatakan "Kata sandi yang Anda masukkan salah" aman? :4) Menggunakan RC4 (tidak perlu perpustakaan)
Diadaptasi dari https://github.com/bozhu/RC4-Python/blob/master/rc4.py .
(Kedaluwarsa sejak pengeditan terbaru, tetapi disimpan untuk referensi di masa mendatang): Saya mengalami masalah menggunakan Windows + Python 3.6 + semua jawaban yang melibatkan
pycrypto
(tidak dapatpip install pycrypto
di Windows) ataupycryptodome
(jawaban di sini denganfrom Crypto.Cipher import XOR
gagal karenaXOR
tidak didukung olehpycrypto
garpu ini ; dan solusi menggunakan... AES
gagal juga denganTypeError: Object type <class 'str'> cannot be passed to C code
). Selain itu, pustakasimple-crypt
memilikipycrypto
ketergantungan, jadi ini bukan opsi.sumber
password_encrypt()
.Ini berfungsi tetapi panjang kata sandi harus persis
8
. Ini sederhana dan membutuhkan pyDes .KELUARAN:
sumber
Implementasi lain dari kode @qneill yang menyertakan checksum CRC dari pesan asli, ini memunculkan pengecualian jika pemeriksaan gagal:
sumber
Anda dapat menggunakan AES untuk mengenkripsi string Anda dengan kata sandi. Namun, Anda pasti ingin memilih kata sandi yang cukup kuat sehingga orang tidak dapat dengan mudah menebaknya (maaf, saya tidak bisa menahannya. Saya ingin tahu tentang keamanan).
AES kuat dengan ukuran kunci yang bagus, tetapi juga mudah digunakan dengan PyCrypto.
sumber
Perpustakaan eksternal menyediakan algoritme enkripsi kunci rahasia.
Misalnya,
Cypher
modul di PyCrypto menawarkan pilihan dari banyak algoritma enkripsi:Crypto.Cipher.AES
Crypto.Cipher.ARC2
Crypto.Cipher.ARC4
Crypto.Cipher.Blowfish
Crypto.Cipher.CAST
Crypto.Cipher.DES
Crypto.Cipher.DES3
Crypto.Cipher.IDEA
Crypto.Cipher.RC5
Crypto.Cipher.XOR
MeTooCrypto adalah
Python
pembungkus untuk OpenSSL , dan menyediakan (di antara fungsi lainnya) pustaka kriptografi tujuan umum berkekuatan penuh. Termasuk adalah cipher simetris (seperti AES).sumber
jika Anda ingin enkripsi aman:
untuk python 2, Anda harus menggunakan keyczar http://www.keyczar.org/
untuk python 3, hingga keyczar tersedia, saya telah menulis simple-crypt http://pypi.python.org/pypi/simple-crypt
keduanya akan menggunakan penguatan kunci yang membuatnya lebih aman daripada kebanyakan jawaban lain di sini. dan karena sangat mudah digunakan, Anda mungkin ingin menggunakannya meskipun keamanan tidak penting ...
sumber
Jadi, karena tidak ada misi penting yang dikodekan , dan Anda hanya ingin mengenkripsi untuk obsfuscation .
Izinkan saya menunjukkan sandi caaser
Sandi Caesar atau pergeseran Caesar, adalah salah satu teknik enkripsi yang paling sederhana dan paling dikenal. Ini adalah jenis sandi substitusi di mana setiap huruf dalam teks biasa diganti dengan sebuah huruf dengan beberapa posisi tetap di bawah alfabet. Misalnya, dengan pergeseran ke kiri sebesar 3, D akan diganti dengan A, E menjadi B, dan seterusnya.
Kode sampel untuk referensi Anda:
Keuntungan: ini memenuhi kebutuhan Anda dan sederhana dan melakukan pengkodean thing'y '.
Kekurangan: dapat dipecahkan dengan algoritma brute force sederhana (sangat tidak mungkin ada orang yang mencoba untuk melihat semua hasil tambahan).
sumber
Menambahkan satu kode lagi dengan decode dan encode untuk referensi
sumber