8 Ide Produk Digital yang Sukses untuk Dijual di Situs Anda Uncategorized Praktis IoT Cryptography pada espressif ESP8266

Praktis IoT Cryptography pada espressif ESP8266

Chipset ESPRESS ESP8266 membuat Dewan Perkembangan Tiga Dolar ‘Internet of Things’. Menurut situs bangunan firmware otomatis populer Nodemcu-build, dalam 60 hari terakhir telah ada 13.341 firmware kustom dibangun untuk platform itu. Dari mereka, hanya 19% memiliki dukungan SSL, dan 10% termasuk modul kriptografi.

Kita sering mengkritik kurangnya keamanan di sektor IOT, dan sering menutup botnet dan serangan lainnya, tetapi akankah kita mengadakan proyek-proyek kita dengan standar yang sama dengan kita? Akankah kita berhenti mengidentifikasi masalah, atau dapatkah kita menjadi bagian dari solusi?

Artikel ini akan fokus pada penerapan Enkripsi AES dan fungsi Otorisasi Hash ke Protokol MQTT menggunakan chip ESP8266 yang sedang berlari Firmware Nodemcu. Tujuan kami bukan untuk menyediakan copy / paste panacea, tetapi untuk melalui proses langkah demi langkah, mengidentifikasi tantangan dan solusi di sepanjang jalan. Hasilnya adalah sistem yang end-to-end dienkripsi dan diautentikasi, mencegah menguping di sepanjang jalan, dan spoofing data yang valid, tanpa mengandalkan SSL.

Kami menyadari bahwa ada juga platform yang lebih kuat yang dapat dengan mudah mendukung SSL (mis. Raspberry Pi, Orange Pi, Friendarm), tetapi mari kita mulai dengan perangkat keras termurah Sebagian besar dari kita telah berbaring, dan protokol cocok untuk banyak proyek kami . AES adalah sesuatu yang dapat Anda terapkan pada AVR jika perlu.

Teori

MQTT adalah protokol olahpesan ringan yang berjalan di atas TCP / IP dan sering digunakan untuk proyek IOT. Perangkat klien berlangganan atau terbitkan ke topik (mis. sensor / suhu / dapur), dan pesan-pesan ini disampaikan oleh broker MQTT. Informasi lebih lanjut tentang MQTT tersedia di halaman web mereka atau dalam seri kami sendiri.

Protokol MQTT tidak memiliki fitur keamanan bawaan di luar otentikasi nama pengguna / kata sandi, jadi umum untuk mengenkripsi dan mengotentikasi seluruh jaringan dengan SSL. Namun, SSL bisa agak menuntut untuk ESP8266 dan ketika diaktifkan, Anda pergi dengan memori yang jauh lebih sedikit untuk aplikasi Anda. Sebagai alternatif ringan, Anda hanya dapat mengenkripsi muatan data yang dikirim, dan menggunakan ID sesi dan fungsi hash untuk otentikasi.

Cara langsung untuk melakukan ini adalah menggunakan LUA dan modul Crypto Nodemcu, yang mencakup dukungan untuk algoritma AES dalam mode CBC serta fungsi hash HMAC. Menggunakan enkripsi AES dengan benar membutuhkan tiga hal untuk menghasilkan ciphertext: pesan, kunci, dan vektor inisialisasi (IV). Pesan dan kunci adalah konsep langsung, tetapi vektor inisialisasi bernilai beberapa diskusi.

Ketika Anda menyandikan pesan di AES dengan kunci statis, itu akan selalu menghasilkan output yang sama. Misalnya, pesan “usernamepassword” dienkripsi dengan kunci “1234567890ABCDEF” mungkin menghasilkan hasil seperti “E40D86C04D723AFF”. Jika Anda menjalankan enkripsi lagi dengan kunci dan pesan yang sama, Anda akan mendapatkan hasil yang sama. Ini membuka Anda untuk beberapa jenis serangan umum, terutama analisis pola dan serangan replay.

Dalam serangan analisis pola, Anda menggunakan pengetahuan bahwa sepotong data yang diberikan akan selalu menghasilkan ciphertext yang sama untuk menebak apa tujuan atau isi pesan yang berbeda tanpa benar-benar mengetahui kunci rahasia. Misalnya, jika pesan “E40D86C04D723AFF” dikirim sebelum semua komunikasi lain, satu mungkin dengan cepat menebak itu adalah login. Singkatnya, jika sistem login sederhana, mengirim paket itu (serangan replay) mungkin cukup untuk mengidentifikasi diri Anda sebagai pengguna yang berwenang, dan kekacauan terjadi.

IVS membuat analisis pola lebih sulit. An IV adalah sepotong data yang dikirim bersama dengan kunci yang memodifikasi hasil end ciphertext. Seperti namanya, itu menginisialisasi keadaan algoritma enkripsi sebelum data masuk. IV perlu berbeda untuk setiap pesan yang dikirim sehingga data berulang mengenkripsi ke dalam ciphertext yang berbeda, dan beberapa cipher (seperti AES-CBC) mengharuskannya tidak dapat diprediksi – cara praktis untuk mencapai ini hanya untuk mengacaknya setiap kali. IV tidak harus dirahasiakan, tetapi khas untuk mengaburkannya dengan cara tertentu.

Sementara ini melindungi terhadap analisis pola, itu tidak membantu serangan replay. Misalnya, mentransmisikan kembali serangkaian data terenkripsi akan tetap duplikat hasilnya. Untuk mencegahnya, kita perlu mengotentikasi pengirim. Kami akan menggunakan ID sesi pseudorandomly yang dihasilkan untuk setiap pesan. ID sesi ini dapat dihasilkan oleh perangkat penerima dengan memposting ke topik MQTT.

Mencegah serangan-serangan ini penting dalam beberapa kasus penggunaan umum. Tersedia kompor internet, dan utilitas dipertanyakan, akan menyenangkan jika mereka tidak menggunakan perintah tidak aman. Kedua, jika saya datalogging dari seratus sensor, saya tidak ingin ada yang mengisi database saya dengan sampah.

Enkripsi praktis

Menerapkan di atas pada nodemcu membutuhkan beberapa upaya. Anda akan memerlukan firmware yang dikompilasi untuk memasukkan modul ‘Crypto’ selain yang lain yang Anda inginkanIRE untuk aplikasi Anda. Dukungan SSL tidak diperlukan.

Pertama, mari kita asumsikan Anda terhubung ke broker MQTT dengan sesuatu seperti berikut ini. Anda dapat mengimplementasikan ini sebagai fungsi terpisah dari kriptografi untuk menjaga semuanya bersih. Klien berlangganan ke saluran sessionid, yang menerbitkan ID sesi pseudorandom yang sangat panjang dan sesuai. Anda bisa mengenkripsi mereka, tetapi itu tidak perlu.

1
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
m = mqtt.client (& quot; ClientID & quot ;, 120)

M: Connect (& quot; myserver.com & quot;, 1883, 0,
Fungsi (Klien)
Cetak (& quot; terhubung & quot;)
Klien: Berlangganan (& quot; mytopic / sessionid & quot ;, 0,
Fungsi (Klien) Cetak (& quot; berlangganan kesuksesan & quot;) Akhir
)
akhir,
Fungsi (klien, alasan)
Cetak (& quot; alasan gagal: & quot; .. Alasan)
akhir
)

m: pada (& quot; pesan & quot ;, fungsi (klien, topik, sessip) end)

Pindah, Node ID adalah cara yang mudah untuk membantu mengidentifikasi sumber data. Anda dapat menggunakan string apa pun yang Anda inginkan: nodeid = node.chipid ().

Kemudian, kami mengatur vektor inisialisasi statis dan kunci. Ini hanya digunakan untuk mengaburkan vektor inisialisasi acak yang dikirim dengan setiap pesan, tidak digunakan untuk data apa pun. Kami juga memilih kunci terpisah untuk data. Tombol-tombol ini adalah hex 16-bit, hanya menggantinya dengan milik Anda.

Akhirnya kita akan membutuhkan frasa sandi untuk fungsi hash yang akan kita gunakan nanti. Serangkaian panjang yang wajar baik-baik saja.

1
2.
3.
4.
Staticiv = & quot; ABCDEF2345678901 & quot;
Ivey = & quot; 2345678901abcdef & quot;
datakey = & quot; 0123456789abcdef & quot;
Passphrase = & quot; MyPassphrase & quot;

Kami juga akan menganggap Anda memiliki beberapa sumber data. Untuk contoh ini, itu akan menjadi nilai yang dibaca dari ADC. Data = ADC.LEAD (0)

Sekarang, kami menghasilkan vektor inisialisasi pseudorandom. Nomor hex 16 digit terlalu besar untuk fungsi nomor pseudorandom, jadi kami menghasilkannya dalam dua bagian (16 ^ 8 minus 1) dan menggabungkannya.

1
2.
3.
4.
5.
Half1 = Node.Random (4294967295)
Half2 = node.Random (4294967295)
I = string.format (& quot;% 8x & quot ;, setengah1)
V = string.format (& quot;% 8x & quot ;, setengah2)
IV = i .. v

Kita sekarang dapat menjalankan enkripsi yang sebenarnya. Di sini kami mengenkripsi vektor inisialisasi saat ini, ID Node, dan satu potong data sensor.

1
2.
3.
Encrypted_IV = Crypto.Encrypt (& quot; AES-CBC & quot ;, Ivkey, IV, Staticiv)
Encrypted_NodeID = crypto.encrypt (& quot; AES-CBC & quot;, DataKey, Nodeid, IV)
Encrypted_Data = Crypto.Encrypt (& quot; AES-CBC & quot;, DataKey, Data, IV)

Sekarang kami menerapkan fungsi hash untuk otentikasi. Pertama-tama kita menggabungkan id nodid, iv, data, dan sesi ke dalam satu pesan, kemudian menghitung hash HMAC SHA1 menggunakan frasa sandi yang kita definisikan sebelumnya. Kami mengubahnya menjadi Hex untuk membuatnya sedikit lebih dapat dibaca manusia untuk setiap debugging.

1
2.
fullmessage = nodeid .. iv .. data .. SessionID
hmac = crypto.tohex (crypto.hmac (& quot; sha1 & quot;, fullmessage, frasa sandi))

Sekarang pemeriksaan enkripsi dan otentikasi ada di tempat, kita dapat menempatkan semua informasi ini dalam beberapa struktur dan mengirimkannya. Di sini, kami akan menggunakan nilai-nilai yang dipisahkan koma karena nyaman:

1
2.
payload = table.concat ({enrypted_iv, ips, data1, hmac}, & quot;, & quot;)
M: Publish (& quot; yourmqttopic & quot;, muatan, 2, 1, fungsi (klien) p = & quot; Terkirim & quot; Cetak (P) end)

Ketika kami menjalankan kode di atas pada Nodemcu yang sebenarnya, kami akan mendapatkan output sesuatu seperti ini:

1D54DD1AF0F75A91A00D4DCD8F4AD28D,
D1A0B14D187C5ADFC948DFD77C2B2EE5,
564633A4A053153BCBD6ED25370346D5,
C66697DF7E7D467112757C841BFB6BCE051D6289.

Semua bersama, program enkripsi adalah sebagai berikut (bagian MQTT dikecualikan untuk kejelasan):

1
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
nodeid = node.chipid ()
Staticiv = & quot; ABCDEF2345678901 & quot;
Ivey = & quot; 2345678901abcdef & quot;
datakey = & quot; 0123456789abcdef & quot;
Passphrase = & quot; MyPassFrase & quot;

Data = ADC.LEAD (0)
Half1 = Node.Random (4294967295)
Half2 = node.Random (4294967295)
I = string.format (& quot;% 8x & quot ;, setengah1)
V = string.format (& quot;% 8x & quot ;, setengah2)
IV = i .. v

Encrypted_IV = Crypto.Encrypt (& quot; AES-CBC & quot ;, Ivkey, IV, Staticiv)
Encrypted_NodeID = crypto.encrypt (& quot; AES-CBC & quot;, DataKey, Nodeid, IV)
Encrypted_Data = Crypto.Encrypt (& quot; AES-CBC & quot;, DataKey, Data, IV)
fullmessage = nodeid .. iv .. data .. SessionID
hmac = crypto.tohex (crypto.hmac (& quot; sha1 & quot;, fullmessage, frasa sandi))
payload = table.concat ({enrypted_iv, encrypted_nodeid, enkripsi_data, hmac}, & quot;)

Dekripsi.

Sekarang, broker MQTT Anda tidak tahu atau peduli bahwa data dienkripsi, itu hanya meneruskannya. Jadi, klien MQTT Anda yang lain berlangganan topik perlu tahu cara mendekripsi data. Pada nodemcu ini agak mudah. Hanya membagi data yang diterima ke dalam string melalui koma, dan melakukan sesuatu seperti di bawah ini. Perhatikan tujuan ini akan menghasilkan ID sesi jadi sudah mengetahuinya.

1
2.
3.
4.
5.
6.
7.
8.
9.
10.
Staticiv = & quot; ABCDEF2345678901 & quot;
Ivey = & quot; 2345678901abcdef & quot;
datakey = & quot; 0123456789abcdef & quot;
Passphrase = & quot; MyPassFrase & quot;

IV = crypto.decrypt (& quot; AES-CBC & quot ;, Ivey, Encrypted_IV, Staticiv)
nodeid = crypto.decrypt (& quot; AES-CBC & QUOT;, DataKey, Encrypted_NodeID, IV)
Data = crypto.decrypt (& quot; AES-CBC & quot;, DataKey, Encrypted_Data, IV)
fullmessage = nodeid .. iv .. data .. SessionID
hmac = crypto.tohex (crypto.hmac (& quot; sha1 & quot;, fullmessage, frasa sandi))

Kemudian bandingkan HMAC yang diterima dan dihitung, dan terlepas dari hasilnya, nonmalidasi ID sesi itu dengan menghasilkan yang baru.

Sekali lagi, di Python

Untuk sedikit variasi, pertimbangkan bagaimana kami akan menangani dekripsi di Python, jika kami memiliki klien MQTT pada mesin virtual yang sama dengan broker yang menganalisis data atau menyimpannya dalam database. Mari kita asumsikan Anda telah menerima data sebagai string “payload”, dari sesuatu seperti klien Paho MQTT yang sangat baik untuk Python.

Dalam hal ini nyaman untuk menyandikan hex data terenkripsi pada nodemcu sebelum mentransmisikan. Jadi pada nodemcu kami mengkonversi semua data terenkripsi ke hex, misalnya: enkripsi_iv = crypto.tohex (crypto.encrypt (“AES-CBC”, IVEY, staticiv))

Menerbitkan sessionid acak tidak dibahas di bawah ini, tetapi cukup mudah menggunakan OS.urandom () dan klien Paho MQTT. Dekripsi ditangani sebagai berikut:

1
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
dari crypto.cipher import AES
Impor Binascii.
dari crypto.hash impor sha, hmac

# Tentukan semua kunci
Ivey = ‘2345678901abcdef’
datakey = ‘0123456789abcdef’
Staticiv = ‘ABCDEF2345678901’
Passphrase = ‘MyPassphrase’

# Konversi string yang diterima ke daftar
Data = payload.split (& quot;, & quot;)

# ekstrak item daftar
Encrypted_IV = BINASCII.UNHEXLIFY (DATA [0])
Encrypted_nodeID = BINASCII.UNHEXLIFY (DATA [1])
Encrypted_Data = BINASCII.UNHEXLIFY (DATA [2])
DITERIMA_HASH = BINASCII.UNHEXLIFY (DATA [3])

# mendekripsi vektor inisialisasi
IV_DECRYPSTION_SUITE = AES.NEW (IVEY, AES.MODE_CBC, Staticiv)
IV = IV_DECRYPSTION_SUITE.DECRYPT (Encrypted_IV)

# mendekripsi data menggunakan vektor inisialisasi
ID_DECRYPSTION_SUITE = AES.NEW (DATAKEY, AES.MODE_CBC, IV)
nodeid = id_decryption_suite.decrypt (enrypted_nodeid)
Data_decryption_Suite = AES.New (DataKey, AES.MODE_CBC, IV)
sensordata = data_decryption_suite.decrypt (enrypted_data)

# komputasi fungsi hash untuk dibandingkan dengan menerima_hash
fullmessage = s.join ([nodeid, iv, sensordata, sessionid])
hmac = hmac.new (frasa sandi, fullmessage, sha)
computed_hash = hmac.hexdigest ()

# lihat docs.python.org/2/library/hmac.html untuk cara membandingkan hash dengan aman

Akhir, awal

Sekarang kami memiliki sistem yang mengirim pesan terenkripsi dan terotentikasi melalui server MQTT ke klien ESP8266 lain atau sistem yang lebih besar menjalankan Python. Masih ada ujung longgar yang penting bagi Anda untuk mengikat jika Anda menerapkan ini sendiri. Semua tombol disimpan dalam memori flash ESP8266S, sehingga Anda ingin mengontrol akses ke perangkat ini untuk mencegah rekayasa balik. Kunci juga disimpan dalam kode pada komputer yang menerima data, di sini menjalankan Python. Selanjutnya, Anda mungkin ingin setiap klien memiliki kunci dan frasa sandi yang berbeda. Itu banyak materi rahasia untuk tetap aman dan berpotensi diperbarui bila perlu. Memecahkan masalah distribusi utama dibiarkan sebagai latihan untuk pembaca yang termotivasi.

Dan pada catatan penutupan, salah satu hal mengerikan tentang menulis artikel yang melibatkan kriptografi adalah kemungkinan menjadi salah di Internet. Ini adalah aplikasi yang cukup mudah dari mode AES-CBC yang diuji dan benar dengan HMAC, sehingga harus cukup padat. Meskipun demikian, jika Anda menemukan kekurangan menarik di atas, beri tahu kami di komentar.

Leave a Reply

Your email address will not be published. Required fields are marked *