Protokol transportasi I2P dikembangkan hampir 15 tahun yang lalu, ketika tugas utamanya adalah menyembunyikan konten lalu lintas, dan bukan fakta menggunakan satu atau beberapa protokol lain. DPI (inspeksi paket mendalam) dan pemblokiran lalu lintas tidak diperhitungkan pada saat itu. Namun, waktu berubah, dan meskipun protokol I2P yang ada masih cukup terlindungi dengan baik, ada kebutuhan untuk protokol transportasi baru yang menanggapi ancaman yang ada dan di masa depan, dan, pertama-tama, DPI, yang menganalisis panjang paket. Selain itu, protokol baru menggunakan kemajuan kriptografi terbaru. Deskripsi lengkap protokol ada di
sini . Dasarnya adalah
Noise , di mana SHA256 digunakan sebagai fungsi hash, dan x25519 sebagai DH (dalam terminologi Noise).
Kriptografi baru
Untuk NTCP2, selain yang sudah ada di I2P, perlu untuk mengimplementasikan algoritma kriptografi berikut:
- x25519
- HMAC-SHA256
- Chacha20
- Poly1305
- Aead
- Siphash
Semuanya, kecuali Siphash, diimplementasikan dalam openssl 1.1.0. Siphash, pada gilirannya, akan muncul di openssl 1.1.1, yang akan segera dirilis. Untuk kompatibilitas dengan openssl 1.0.2, yang termasuk dalam sebagian besar OS yang saat ini digunakan, i2pd telah menambahkan implementasi sendiri yang ditulis oleh salah satu pengembang i2pd
Jeff Becker , yang dikenal dalam ps sebagai I ps.
Dibandingkan dengan NTCP, x25519 menggantikan DH, AEAD / Chaha20 / Poly1305 menggantikan AES-256-CBC / Adler32, dan Siphash digunakan untuk mengenkripsi panjang pesan yang dikirimkan. Prosedur untuk menghitung kunci bersama telah menjadi lebih kompleks: dengan banyak panggilan ke HMAC-SHA256.
Perubahan ke RouterInfo
Untuk bekerja pada protokol NTCP2, selain dua kunci yang ada (enkripsi dan tanda tangan), kunci ketiga x25519 diperkenalkan, disebut kunci statis, yang harus ada di beberapa alamat RouterInfo sebagai parameter “s” untuk klien dan server. Jika lebih dari satu alamat mendukung NTCP2, misalnya ipv4 dan ipv6, maka "s" harus sama di mana-mana. Untuk klien, alamat mungkin hanya berisi "s" dan tidak mengandung parameter "host" dan "port". Parameter yang diperlukan dari NTCP2 adalah "v", saat ini selalu sama dengan "2".
Alamat NTCP2 dapat ditetapkan sebagai alamat tipe “NTCP” dengan parameter tambahan - dalam hal ini, koneksi dapat dibuat menggunakan NTCP dan NTCP2, atau sebagai alamat tipe NTCP2 yang hanya mendukung koneksi NTCP2. Di Java I2P, metode pertama digunakan, di i2pd - yang kedua.
Jika tuan rumah menerima koneksi NTCP2 yang masuk, maka ia harus mempublikasikan parameter "i" dengan nilai IV untuk mengenkripsi kunci publik ketika membuat koneksi.
Buat koneksi
Dalam proses membangun koneksi, para pihak menghasilkan pasangan kunci sementara x25519, dan berdasarkan mereka dan kunci statis, set kunci untuk mengirimkan data dihitung. Kunci statis juga disahkan dan dicocokkan dengan konten RouterInfo.
Para pihak bertukar tiga pesan:
SessionRequest ------------------->
<- SessionCreated
SessionConfirmed ----------------->
untuk masing-masingnya kunci umum x25519 dihitung, disebut “bahan kunci input”, dan kemudian kunci enkripsi pesan dihasilkan menggunakan operasi MixKey, sedangkan nilai ck (kunci rantai) disimpan di antara pesan dan hasilnya berdasarkan pada dasar di mana kunci untuk transmisi data dihitung . Implementasi MixKey terlihat seperti ini:
Kode MixKeyvoid NTCP2Establisher::MixKey (const uint8_t * inputKeyMaterial, uint8_t * derived) {
SessionRequest terdiri dari kunci publik 32-byte x25519 dari klien, dan blok data 16-byte AEAD / Chacha20 / Poly1305 terenkripsi + 16 byte hash, serta kumpulan data acak (bantalan), yang panjangnya ditransmisikan dalam blok terenkripsi. Panjang bagian kedua dari pesan SessionConfirmed juga dikirimkan di sana. Blok dienkripsi dan ditandatangani dengan kunci berdasarkan kunci sementara klien dan kunci statis server. Ck awal untuk MixKey diatur ke SHA256 ("Noise_XKaesobfse + hs2 + hs3_25519_ChaChaPoly_SHA256").
Karena 32 byte kunci publik x25519 dapat dikenali oleh dpi, mereka dienkripsi menggunakan AES-256-CBC, di mana kuncinya adalah hash dari alamat server, dan IV diambil dari parameter “i” dari alamat di RouterInfo.
SessionCreated dalam struktur mirip dengan SessionRequest, kecuali bahwa kunci dihitung berdasarkan kunci sementara dari kedua pihak, dan IV digunakan untuk enkripsi / dekripsi kunci publik IV setelah dekripsi / enkripsi kunci publik dari SessionRequest.
SessionConfirmed terdiri dari dua bagian: kunci publik statis klien dan RouterInfo klien. Tidak seperti pesan sebelumnya, kunci publik dienkripsi dengan AEAD / Chaha20 / Poly1305 dengan kunci yang sama dengan SessionCreated. Oleh karena itu, panjang bagian pertama bukan 32, tetapi 48 byte. Bagian kedua juga dienkripsi dengan AEAD / Chaha20 / Poly1305, tetapi dengan kunci baru, kami menghitungnya berdasarkan kunci sementara server dan kunci statis klien. Juga, satu blok data acak dapat ditambahkan ke RouterInfo, tetapi, sebagai suatu peraturan, ini tidak perlu, karena panjang RouterInfo berbeda.
Generasi kunci untuk transmisi data
Jika semua pemeriksaan hash dan kunci selama pengaturan koneksi berhasil, maka setelah MixKey terakhir, kedua belah pihak harus memiliki ck yang sama, dari mana 2 set tiga kali lipat dari tombol <k, sipk, sipiv> akan dihasilkan di setiap sisi, di mana k adalah kunci AEAD / Chaha20 / Poly1305, sipk adalah kunci untuk Siphash, sipiv adalah nilai IV awal untuk Siphash, yang berubah setelah setiap aplikasi.
Kode Pembuatan Kunci void NTCP2Session::KeyDerivationFunctionDataPhase () { uint8_t tempKey[32]; unsigned int len;
16 byte pertama dari array sipkeys adalah kunci Siphash, 8 byte kedua adalah IV.
Sebenarnya, Siphash membutuhkan dua kunci masing-masing 8 byte, tetapi di i2pd mereka dianggap sebagai 1 kunci dengan panjang 16 byte.
Transfer data
Data ditransmisikan dalam bingkai, setiap frame terdiri dari 3 bagian:
- Panjang bingkai 2 byte yang dienkripsi oleh Siphash
- data dienkripsi oleh Chacha20
- 16 byte hash Poly1305
Panjang maksimum data yang dikirim dalam satu bingkai adalah 65519 byte.
Panjang pesan dienkripsi menggunakan operasi XOR dengan dua byte pertama dari Siphash IV saat ini.
Data terdiri dari blok, setiap blok didahului oleh header 3 byte dengan tipe dan panjang blok. Pada dasarnya, blok I2NP yang berisi pesan I2NP dengan header yang dimodifikasi dikirimkan. Dalam satu bingkai, beberapa blok I2NP dapat ditransmisikan.
Jenis blok penting lainnya adalah blok data acak, yang direkomendasikan untuk ditambahkan ke setiap frame. Ini bisa menjadi satu dan yang terakhir.
Selain itu, dalam implementasi NTCP2 saat ini ada 3 jenis blok lagi:
- RouterInfo - biasanya berisi server RouterInfo segera setelah koneksi dibuat, tetapi RouterInfo dari node sewenang-wenang dapat ditransmisikan kapan saja untuk mempercepat pekerjaan tempat penimbunan banjir, yang bidang bendera disediakan dalam pesan.
- Termination - dikirim oleh node ketika koneksi terputus atas inisiatifnya, menunjukkan alasannya.
- DateTime - waktu saat ini dalam detik.
Dengan demikian, protokol transport baru memungkinkan tidak hanya untuk secara efektif menolak DPI, tetapi juga secara signifikan mengurangi beban pada prosesor karena lebih modern dan lebih cepat dan kriptografi, yang sangat penting ketika bekerja pada perangkat yang lemah seperti smartphone dan router. Saat ini, dukungan NTCP2 sepenuhnya diimplementasikan di I2P dan i2pd resmi dan akan muncul secara resmi di rilis berikutnya masing-masing 0,9,36 dan 2,20. Untuk mengaktifkan ntcp2 di i2pd, tentukan parameter konfigurasi ntcp2.enabled = true, dan ntcp2.published = true dan ntcp2.port = <port> untuk koneksi yang masuk.