Penjelasan paling sederhana tentang bagaimana algoritma enkripsi simetris bekerja hari ini

(Saya menemukan utas di Twitter dengan penjelasan yang sangat keren tentang sandi simetris. Itu ditulis oleh Colm MacCárthaigh, salah satu kontributor utama Apache. Saya meminta izin kepada Colm untuk menerjemahkan, dia setuju).


Saya akan menjelaskan kepada Anda dalam bahasa sederhana apa yang terjadi ketika data dienkripsi. Saya berharap bahwa tanpa mistisisme dan hal-hal kompleks yang ditemukan oleh cryptographers.


Jadi, enkripsi simetris adalah persis apa yang kita gunakan dalam kebanyakan kasus ketika kita ingin mengenkripsi banyak data. Browser Anda mengirim dan menerima data menggunakan enkripsi simetris. Jika Anda mengenkripsi file atau disk, enkripsi simetris juga berfungsi dalam hal ini. iMessage, Signal, WhatsApp - semuanya menggunakan enkripsi simetris untuk keamanan korespondensi Anda.


Jika Anda berpikir bahwa ketika mengenkripsi data dicampur sehingga tidak ada yang bisa membacanya tanpa kunci, cara itu benar-benar terjadi.


Ini adalah contoh sederhana. Misalkan saya memiliki string Ovaltine dan ingin mengenkripsi itu. Saya bisa menggunakan rot13 - sandi tua-sekolah Caesar yang sangat sederhana, yang membuat tarian bundar huruf di mana a dan z berpegangan tangan, dan mengganti setiap huruf dengan huruf alfabet lain, yang merupakan 13 karakter dari huruf yang diganti. Jadi, "O" berubah menjadi "B", dan "v" menjadi "i", sebagai akibatnya, "Ovaltine" berubah menjadi "Binygvar". Tentu saja, ini tidak terlalu aman. Ini adalah contoh naif, yang sangat mudah retak, karena penyerang dapat mengetahui huruf mana yang paling sering ditemukan (biasanya dalam teks asli itu adalah "e") dan menemukan huruf yang tersisa dengan cara yang sama.


Sekarang Anda dapat membayangkan bahwa harus ada cara yang lebih sulit untuk "mencampur" surat-surat itu. Misalnya, beberapa skema rumit di mana "a" masuk ke "p", tetapi ketika dienkripsi ulang, menjadi "f". Mungkin bahkan terkadang skema ini mulai mengenkripsi "a" dengan dua huruf, misalnya, "jd" atau sesuatu yang lain. Dengan demikian, skema rumit ini dapat mengenkripsi "Ovaltine" ke dalam string "FGyswDmweeRq" (perhatikan bahwa ia telah menjadi lebih lama). Algoritma enkripsi muncul di masa lalu yang bekerja dengan cara yang serupa, tetapi itu sama sekali bukan cara kerja enkripsi modern.


Alih-alih huruf "menyeret", enkripsi modern mengambil string rahasia Anda dan menggabungkannya dengan data acak. Ini mirip dengan rot13 hanya dalam dua aspek: enkripsi dan dekripsi pada dasarnya operasi yang sama, dan semuanya terjadi "di tempat". Memang, pernahkah Anda memperhatikan bahwa rot13 merupakan algoritma enkripsi dan dekripsi? rot13 (Ovaltine) -> Binygvar, rot13 (Binygvar) -> Ovaltine. Saya percaya bahwa ini adalah simetri yang sangat indah dalam enkripsi simetris. Tapi kembali ke topik kita. Caranya adalah kita menggunakan operasi XOR bitwise. Dalam kriptografi, logika formal, dan kode, program XOR dapat didefinisikan secara berbeda, tetapi saya akan menggunakan notasi yang kemungkinan besar Anda kenal. Ini terlihat seperti ini: ^.


XOR singkatan dari "eksklusif ATAU". Ini adalah operator (atau fungsi, jika Anda mau), yang mengambil dua argumen dan mengembalikan hasilnya. A ^ B = C. Operator ini disebut "bitwise" karena berlaku untuk bit yang sesuai satu sama lain. Jika A dan B adalah byte, maka kita dapat mengasumsikan bahwa A ^ B = C pada dasarnya adalah 8 operasi berbeda yang terjadi secara bersamaan. ^ membandingkan bit pertama A dan bit pertama B, dan kemudian menempatkan hasilnya di bit pertama C. Ia mengulangi yang sama 7 kali lebih banyak untuk bit yang tersisa. Aturannya sederhana: jika bit dari A adalah "1" ATAU bit dari B adalah "1", maka kita mengatur bit yang sesuai C ke "1", tetapi hanya jika "A" dan "B" bukan "1" pada saat yang sama. Ini adalah bagian eksklusif. Berikut adalah tabel kebenaran sekolah tua:


A|B|C 0|0|0 1|0|1 0|1|1 1|1|0 

Hal paling keren tentang XOR adalah tampilannya seperti rot13. Kita dapat menggunakannya untuk enkripsi dan dekripsi. Saya akan menunjukkan ini dengan contoh sederhana. Mari kita bayangkan bahwa kita ingin mengenkripsi angka "3" yang biasa dan kunci enkripsi kita adalah angka lain "7". Jadi 3 ^ 7 = 4. Artinya, hasil enkripsi adalah "4". Sekarang mari kita menguraikan nomornya. Saya hanya akan melakukan hal yang sama lagi: 4 ^ 7 = 3. Ambil nomor apa pun yang Anda suka atau data apa pun, dan itu akan selalu berfungsi - XOR akan selalu dapat mendekripsi dirinya.


Sedikit demi sedikit - ini adalah bagaimana kita benar-benar mengenkripsi dan mendekripsi data, tidak ada pencampuran, hanya XOR-ing. Bagian yang sulit adalah menemukan data yang dapat kita terapkan XOR. Satu pendekatan adalah mengambil sejumlah besar data rahasia dan menggunakannya sebagai argumen kedua untuk XOR. Dalam hal ini, semua peserta dalam proses transmisi data terenkripsi harus menggunakan set data rahasia yang sama untuk enkripsi dan dekripsi. Dan itu akan berhasil. Benar, ada beberapa masalah.


Masalah pertama. Data rahasia seharusnya tampak acak. Anda tidak dapat mengambil teks dari buku atau semacamnya. Pola apa pun akan muncul dalam data terenkripsi. Inilah yang membuat pasukan sekutu unggul dalam Perang Dunia II.


Masalah kedua. Anda tidak dapat menggunakan kembali data sensitif, karena pola akan muncul kembali. Dengan demikian, Anda entah bagaimana harus memberikan potongan besar data rahasia untuk semua orang yang membutuhkannya, seperti papan sekali pakai. Ini terlalu sulit.


Dalam enkripsi modern, kita "menghasilkan" data rahasia yang kita butuhkan dari kunci kecil. Kunci-kunci ini lebih mudah dibawa dan dilindungi. Inilah yang sebenarnya merupakan algoritma enkripsi simetris - skema untuk generasi deterministik data acak dari suatu kunci. Bagian tentang "determinisme" sangat penting: dua orang dengan kunci yang sama harus benar-benar menghasilkan set data yang sama, jika tidak mereka tidak akan dapat saling memahami. Anda mungkin pernah mendengar tentang algoritme tersebut: AES, 3DES, DES, RC4, ChaCha20. Mereka semua melakukannya.


Ternyata masalah matematika menghasilkan aliran data acak (di mana tidak ada pola dalam bentuk yang dapat diprediksi) menggunakan kunci sangat sulit. Dari daftar ini, hanya AES dan ChaCha20 yang dianggap aman hari ini. Algoritme lain diretas: orang dapat memperkirakannya. Selain itu, AES memiliki reputasi yang sedikit ternoda, karena cryptographers mengatakan yang berikut:


AES adalah algoritma enkripsi utama dan paling dianalisis. Standar Benar-Benar Emas! : dark_sunglasses:

Tetapi pada saat yang sama mereka menambahkan:


Implementasi AES dalam perangkat lunak (bukan dalam perangkat keras) tidak aman atau lambat, dan terkadang tidak aman, dan lambat. Itu tidak dirancang mempertimbangkan fakta bahwa itu bisa diretas menggunakan analisis cache. : facepalm:

Jangan terlalu takut jika ini tidak jelas bagi Anda. Gagasan utamanya adalah ini: AES cantik dari sudut pandang matematika, tetapi sangat rumit dalam implementasi perangkat lunak. Tetapi jangan khawatir - kami hampir selalu memiliki dukungan AES di tingkat perangkat keras (daftar semua prosesor dengan dukungan perangkat keras AES dapat ditemukan di sini https://en.wikipedia.org/wiki/AES_instruction_set , - catatan penerjemah).


Meskipun begitu, kami melanjutkan ... Bagaimana algoritma ini bekerja? Bagaimana kita bisa mengambil kunci dan dengan aman menghasilkan aliran data acak? Saya akan menyederhanakan sedikit di sini dan mulai dengan blok.


Algoritma ini menerima tiga parameter pada input dan memberikan ciphertext pada output. Parameter input - kunci, teks terenkripsi dan ... kejutan - sesuatu yang aneh yang disebut "vektor inisialisasi" (vektor inisialisasi, IV).


 AES(key, IV, plaintext) -> encrypted_data. 

Kunci dan IV digabungkan satu sama lain untuk membuat satu set "kondisi awal" untuk algoritma; ini mirip dengan pertukaran awal atau pengacakan ubin dalam game Scrabble. Kombinasi kunci dan IV yang sama akan selalu membuat kondisi awal yang sama. Anda bertanya, mengapa kita bahkan membutuhkan IV? Kami membutuhkan infus sehingga kami dapat mengenkripsi beberapa pesan menggunakan kunci yang sama. Tanpa IV, setiap aliran data yang dihasilkan akan sama, dan ini buruk. Ini akan melanggar salah satu aturan yang kita bicarakan sebelumnya: kita tidak bisa menggunakan kembali data yang sama untuk enkripsi. Jadi kita perlu infus untuk mencampur hasilnya. Tetapi tidak seperti kunci IV, itu bisa publik.


Jadi, ketika Anda mengenkripsi pesan dan mengirimkannya ke seseorang, Anda juga dapat menambahkan: "Hei, ini IV yang saya gunakan." Masih penting bahwa kami tidak menggunakan kembali kombinasi kunci dan IV, karena mereka akan memberi kami data acak berulang. Ada dua cara untuk mencapai kondisi ini: 1) IV adalah jenis penghitung yang kami tingkatkan dengan setiap pesan baru. 2) IV dihasilkan secara acak, sementara itu memiliki nilai yang cukup besar, jadi kita tidak perlu terlalu khawatir tentang tabrakan. Bagaimanapun, saya menyebutkan bahwa saya akan berbicara tentang blok.


Kunci dan IV adalah "campuran" atau digabungkan sedemikian rupa untuk membuat satu set kondisi awal ... kondisi ini sebenarnya adalah "blok" awal data acak. Panjang blok ini adalah 128 bit untuk AES128, 256 bit untuk AES256, dan 512 bit untuk ChaCha20. Dan di sini keajaiban nyata dan individualitas dari algoritma enkripsi tertentu dimanifestasikan. Bahkan, esensi mereka terletak pada bagaimana urutan blok dihasilkan dan bagaimana setiap blok dikaitkan dengan tetangganya. Hubungan antara blok-blok ini tetap dapat diprediksi bahkan bagi mereka yang tidak memiliki kunci.


Saya tidak akan masuk jauh ke dalam bagaimana algoritma ini bekerja, tetapi jika Anda ingin tahu lebih banyak, saya menyarankan Anda untuk mulai menjelajahi topik ini dengan generator linear congruential (LCG). LCG adalah fungsi yang membuat blok data "melingkar" secara acak dan tidak berulang. Kemudian lihat jaringan Feistel, level pengembangan LCG berikutnya. Kemudian berurusan dengan S-Boxes, dan kemudian lihat bagaimana Salsa20 menciptakan interlacing dalam algoritma ChaCha20. Semua ini jauh lebih terjangkau daripada yang mungkin Anda pikirkan!


Jadi, kita sekarang tahu bagaimana aliran data acak dapat dikombinasikan dengan teks untuk mengenkripsi dan mendekripsi, dan kita sudah sedikit dalam subjek tentang bagaimana aliran data acak ini dibuat. Bukankah itu yang kita butuhkan? Untuk enkripsi disk, itu hampir semuanya. Kami dapat mengenkripsi setiap blok atau sektor penyimpanan menggunakan satu kunci dan IV, yang dapat diperoleh dari "posisi" pada disk. Dengan demikian, kita selalu dapat mendekripsi blok data apa saja di mana saja pada disk, selama kita memiliki kuncinya. Tetapi ada satu masalah ... seseorang dapat merusak data terenkripsi kami. Jika saya mengubah nilai byte apa pun, bahkan jika saya tidak memiliki kunci, maka pada akhirnya kita tidak akan dapat mendekripsi blok. Dan tidak ada perlindungan terhadap gangguan semacam ini. Dalam hal pengiriman pesan dan data melalui jaringan, ini menjadi lebih kritis. Kami tidak ingin siapa pun merusak data yang kami kirim. Jadi kita perlu menambahkan pemeriksaan integritas! Ada beberapa skema untuk melakukan ini.


HMAC, GCM, dan Poly1305 adalah skema pemeriksaan integritas modern paling umum. Algoritma ini pada dasarnya bekerja seperti ini: mereka disediakan dengan data dan kunci lain (disebut kunci integritas). Setelah perhitungan, mereka memberikan MAC (kode otentikasi pesan) atau tag, yang pada gilirannya hanyalah sepotong data yang bertindak sebagai tanda tangan.


Jadi, untuk enkripsi dan perlindungan, skema kami mungkin terlihat seperti ini:


 AES(key, IV, "Ovaltine") -> encrypted_output HMAC(key, encrypted_output) -> MAC 

dan kemudian dengan kawat kami kirim:


 IV | encrypted_output | MAC 

Untuk dekripsi, kami memeriksa MAC, menghasilkannya lagi dan membandingkan hasilnya dengan MAC yang diterima, dan kemudian mendekripsi datanya. Ada perbedaan internal dalam cara HMAC, GCM, dan Poly1305 menghasilkan tanda tangan ini, tetapi Anda tidak perlu khawatir tentang itu. Sampai saat ini, kombinasi operasi ini biasanya dibungkus dengan fungsi yang disebut "AEAD" (Enkripsi terotentikasi dengan Data Tambahan). Di bawah tenda, dia melakukan semua yang saya bicarakan sebelumnya:


 AEAD(key, IV, plaintext, additional_data) -> IV_encrypted_data_MAC 

Sepotong yang disebut "additional_data" hanyalah data yang dengannya Anda dapat memastikan bahwa pihak pengirim memiliki data ini, meskipun tidak dikirim kepada mereka. Ini seperti meta-data yang menetapkan hak akses. Seringkali bidang ini dibiarkan kosong.


Namun demikian, Anda dapat memiliki masalah dengan AEAD jika Anda menggunakan IV yang sama. Ini buruk! Ada upaya untuk memperbaiki situasi ini: kolega saya, yang bernama Shay, sedang mengerjakan skema SIV yang keren yang menambahkan lapisan perlindungan terhadap masalah ini. Tetapi jika Anda menggunakan IV yang unik, enkripsi modern sangat aman. Artinya, Anda bisa menerbitkan ciphertext di New York Times, dan tidak ada yang bisa memecahkannya. Cipher akan tetap tidak dapat diakses bahkan jika "beberapa" bagian dari teks diketahui. Misalnya, dalam protokol Internet sejumlah besar teks diketahui. Server HTTP selalu merespons hal yang sama dan byte pertama selalu diketahui. Tetapi fakta ini tidak masalah sama sekali - itu tidak akan membantu penyerang untuk menemukan satu bagian dari data yang tersisa ... Kami telah menempuh perjalanan panjang sejak Perang Dunia Kedua.


Tetapi ada serangan yang berhasil! Jika Anda mengirim data melalui jaringan dan seseorang melacak waktu dan ukuran pesan, maka data terenkripsi dapat dipecahkan menggunakan analisis lalu lintas.


gambar


Mari kita cari tahu panjangnya terlebih dahulu. Jelas, panjang bukanlah karakteristik yang tersembunyi. Dan ini normal jika Anda mencoba melindungi kata sandi atau nomor kartu kredit di suatu tempat di tengah pesan. Bukan masalah besar. Tetapi ini berarti bahwa siapa pun yang berpotensi dapat menentukan jenis konten yang Anda kirimkan. Contoh sederhana: jika Anda mengirim gif menggunakan messenger dan jika ukuran gambar ini unik, penyerang mencegat data Anda mungkin menyarankan GIF mana yang baru saja dikirim. Ada versi yang lebih rumit dari serangan ini untuk Google Maps, Netflix, Wikipedia, dll. Untuk melindungi dari serangan ini, Anda dapat "menyelesaikan" pesan yang dikirim dengan byte tambahan, sehingga semua pesan yang dikirim memiliki panjang yang sama, apa pun yang terjadi. Enkripsi yang digunakan dalam jaringan militer selalu "menyelesaikan" lalu lintas dengan data tambahan, yaitu, untuk pencegat selalu terlihat sama! Masalah lain dengan panjangnya adalah bahwa jika Anda menggunakan kompresi dan memberi penyerang kemampuan untuk mengubah bagian mana pun dari konten pada halaman yang dilihat pengguna, ini memungkinkan penyerang untuk mengetahui bahkan rahasia terkecil sekalipun. Cari serangan yang disebut CRIME. Dia cantik dan menakutkan.


Saya juga mengatakan bahwa masalah lainnya adalah waktu. Jelas, waktu pengiriman setiap pesan adalah informasi terbuka. Mungkinkah ini menjadi masalah? Mungkin Misalnya, jika Anda mengirim pesan setiap kali Anda menekan tombol, maka itu sepele untuk mengetahui apa yang sebenarnya dicetak menggunakan analisis waktu. Keren! Contoh lain adalah VOIP. Jika aplikasi panggilan Anda mengirim data hanya ketika orang berbicara, tetapi tidak selama keheningan, ini sudah cukup untuk mengembalikan 70% pidato bahasa Inggris. Hanya karena keheningan. Keren menakutkan.


Contoh-contoh ini hanyalah puncak gunung es. Bahkan ketika Anda menggunakan algoritma dan skema enkripsi yang telah membaik selama 80 tahun, masih ada celah yang dapat digunakan untuk memecahkan keamanan. Itulah mengapa sangat berharga untuk mengetahuinya!


Bagaimanapun, ini adalah tingkat penjelasan yang ingin saya bahas sekarang, tetapi kami telah mempertimbangkan hal-hal yang paling perlu untuk diketahui. Jika Anda membaca sampai titik ini - terima kasih! Anda sekarang harus memiliki pemahaman yang lebih besar tentang apa yang terjadi selama enkripsi dan apa yang harus diperhatikan.


Jangan ragu untuk bertanya.


Terjemahan diterbitkan di bawah Lisensi CC BY-NC-SA 4.0

Source: https://habr.com/ru/post/id443050/


All Articles