Modul ssl --- SSL/TLS¶
Modul ini menyediakan akses ke fasilitas enkripsi Transport Layer Security (sebelumnya dan secara luas dikenal sebagai "Secure Sockets Layer") serta autentikasi peer untuk soket jaringan, baik sisi klien maupun sisi server.
Tip
Baru mengenal TLS di kamera? Mulailah dengan tutorial Bekerja dengan sertifikat TLS. Tutorial tersebut membahas pemilihan jenis kunci, pembuatan dan konversi sertifikat ke format DER yang diperlukan kamera, cara menempatkannya di perangkat, serta verifikasi server dan klien -- dengan contoh kerja lengkap.
Catatan
MicroPython tidak mengimplementasikan ssl.SSLError. Kegagalan SSL/TLS dimunculkan sebagai OSError.
Contoh¶
Klien TLS, memverifikasi sertifikat server terhadap sertifikat CA (dalam format DER) yang disimpan di filesystem:
import socket
import ssl
import ntptime
# CERT_REQUIRED checks the certificate's validity dates, so the clock
# must be set (see the certificates tutorial linked above).
ntptime.settime()
# Open a plain TCP connection.
addr = socket.getaddrinfo("example.com", 443)[0][-1]
sock = socket.socket()
sock.connect(addr)
# Wrap it for TLS and require a valid certificate.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="ca.der")
ssock = ctx.wrap_socket(sock, server_hostname="example.com")
ssock.write(b"GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
print(ssock.read())
ssock.close()
Untuk koneksi cepat yang tidak aman (tanpa validasi sertifikat), fungsi kenyamanan ssl.wrap_socket() dapat digunakan sebagai gantinya:
ssock = ssl.wrap_socket(sock, server_hostname="example.com")
Server TLS, menampilkan sertifikat dan kunci privatnya sendiri (format DER):
import socket
import ssl
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(socket.getaddrinfo("0.0.0.0", 8443)[0][-1])
sock.listen(1)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("server.der", "server.key")
while True:
client, addr = sock.accept()
sclient = ctx.wrap_socket(client, server_side=True)
sclient.write(b"hello\n")
sclient.close()
Fungsi¶
- ssl.wrap_socket(sock: Any, server_side: bool = False, key: bytes | None = None, cert: bytes | None = None, cert_reqs: int = CERT_NONE, cadata: bytes | None = None, server_hostname: str | None = None, do_handshake: bool = True) Any¶
Membungkus sock yang diberikan dan mengembalikan objek wrapped-socket baru. Implementasi fungsi ini adalah dengan terlebih dahulu membuat
SSLContextlalu memanggil metodeSSLContext.wrap_socket()pada objek konteks tersebut. Argumen sock, server_side, dan server_hostname diteruskan tanpa perubahan ke pemanggilan metode. Argumen do_handshake diteruskan sebagai do_handshake_on_connect. Argumen-argumen lainnya memiliki perilaku berikut:cert_reqs menentukan apakah peer (server atau klien) harus menunjukkan sertifikat yang valid. Perhatikan bahwa
ssl.CERT_NONEdanssl.CERT_OPTIONALtidak memvalidasi sertifikat apa pun; hanyassl.CERT_REQUIREDyang melakukan validasi.cadata adalah objek bytes yang berisi rantai sertifikat CA (dalam format DER) yang akan memvalidasi sertifikat peer. Saat ini hanya satu sertifikat berenkode DER yang didukung.
Kelas¶
- class ssl.SSLContext(protocol: int, /)¶
Membuat instans SSLContext baru. Argumen protocol harus berupa salah satu konstanta
PROTOCOL_*.- load_cert_chain(certfile: str | bytes, keyfile: str | bytes) None¶
Memuat kunci privat dan sertifikat yang sesuai. certfile adalah string berisi jalur file sertifikat. keyfile adalah string berisi jalur file kunci privat.
Perbedaan dengan CPython
Ekstensi MicroPython: certfile dan keyfile dapat berupa objek bytes alih-alih string, dalam hal ini keduanya diinterpretasikan sebagai data sertifikat/kunci yang sebenarnya.
- load_verify_locations(cafile: str | None = None, cadata: bytes | None = None) None¶
Memuat rantai sertifikat CA yang akan memvalidasi sertifikat peer. cafile adalah jalur file sertifikat CA. cadata adalah objek bytes yang berisi sertifikat CA. Hanya salah satu dari argumen-argumen ini yang boleh diberikan.
- get_ciphers() List[str]¶
Mendapatkan daftar cipher yang diaktifkan, dikembalikan sebagai daftar string.
- set_ciphers(ciphers: List[str]) None¶
Mengatur cipher yang tersedia untuk soket yang dibuat dengan konteks ini. ciphers harus berupa daftar string dalam format IANA cipher suite .
- wrap_socket(sock: Any, *, server_side: bool = False, do_handshake_on_connect: bool = True, server_hostname: str | None = None, client_id: bytes | None = None) Any¶
Mengambil stream sock (biasanya instans socket.socket bertipe
SOCK_STREAM), dan mengembalikan instans ssl.SSLSocket yang membungkus stream yang mendasarinya. Objek yang dikembalikan memiliki metode antarmuka stream yang umum sepertiread(),write(), dll.server_side memilih apakah soket yang dibungkus berada di sisi server atau klien. Soket SSL sisi server harus dibuat dari soket biasa yang dikembalikan oleh
accept()pada soket server listening non-SSL.do_handshake_on_connect menentukan apakah handshake dilakukan sebagai bagian dari
wrap_socketatau apakah ditunda untuk dilakukan sebagai bagian dari pembacaan atau penulisan awal. Untuk soket pemblokiran, melakukan handshake segera adalah standar. Untuk soket non-pemblokiran (yaitu ketika sock yang diteruskan kewrap_socketberada dalam mode non-pemblokiran), handshake umumnya harus ditunda karena jika tidakwrap_socketakan memblokir hingga selesai.server_hostname digunakan sebagai klien, dan mengatur nama host untuk diperiksa terhadap sertifikat server yang diterima. Ini juga mengatur nama untuk Server Name Indication (SNI), memungkinkan server menampilkan sertifikat yang tepat.
client_id adalah argumen ekstensi khusus MicroPython yang hanya digunakan saat mengimplementasikan DTLS Server. Lihat Dukungan DTLS untuk detailnya.
Peringatan
Secara default tidak ada validasi sertifikat yang dilakukan (
ssl.CERT_NONE). Untuk koneksi yang aman, Anda harus memverifikasi sertifikat peer dengan mengatur cert_reqs /SSLContext.verify_modekessl.CERT_REQUIRED; jika tidak, koneksi rentan terhadap serangan man-in-the-middle.wrap_socketmilik CPython mengembalikan objekSSLSocketyang memiliki metode-metode umum untuk soket, sepertisend,recv, dll.wrap_socketmilik MicroPython mengembalikan objek yang lebih mirip denganSSLObjectmilik CPython yang tidak memiliki metode soket tersebut.
- verify_mode¶
Mengatur atau mendapatkan perilaku untuk verifikasi sertifikat peer. Harus berupa salah satu konstanta
CERT_*.Catatan
ssl.CERT_REQUIREDmengharuskan tanggal/waktu perangkat diatur dengan benar, misalnya menggunakan mpremote rtc --set atauntptime, danserver_hostnameharus ditentukan saat berada di sisi klien.
Dukungan DTLS¶
Perbedaan dengan CPython
Ini adalah ekstensi MicroPython.
Modul ini mendukung DTLS dalam mode klien dan server melalui konstanta PROTOCOL_DTLS_CLIENT dan PROTOCOL_DTLS_SERVER yang dapat digunakan sebagai argumen protocol dari SSLContext.
Dalam kasus ini, soket yang mendasarinya diharapkan berperilaku sebagai soket datagram (yaitu seperti soket yang dibuka dengan socket.socket dengan socket.AF_INET sebagai af dan socket.SOCK_DGRAM sebagai type).
Dukungan server DTLS¶
Dukungan server DTLS MicroPython dikonfigurasi dengan "Hello Verify" sebagaimana diperlukan untuk DTLS 1.2. Ini transparan untuk klien DTLS, tetapi ada pertimbangan yang relevan saat mengimplementasikan server DTLS di MicroPython:
Server harus meneruskan argumen tambahan client_id saat memanggil
SSLContext.wrap_socket(). ID ini harus berupa objekbytes(atau sejenis) dengan pengidentifikasi khusus transport yang mewakili klien.Pendekatan paling sederhana adalah mengonversi tuple
(client_ip, client_port)yang dikembalikan darisocket.recv_from()menjadi string byte, yaitu:_, client_addr = sock.recvfrom(1, socket.MSG_PEEK) sock.connect(client_addr) # Connect back to the client sock = ssl_ctx.wrap_socket(sock, server_side=True, client_id=repr(client_addr).encode())
Pertama kali klien terhubung, panggilan server ke
wrap_socketakan gagal dengan errorOSError"Hello Verify Required". Ini karena cookie DTLS "Hello Verify" belum diketahui oleh klien. Jika klien yang sama terhubung untuk kedua kalinya, makawrap_socketakan berhasil.Cookie DTLS untuk "Hello Verify" dikaitkan dengan objek
SSLContext, sehingga objekSSLContextyang sama harus digunakan untuk membungkus koneksi berikutnya dari klien yang sama. Implementasi cookie mencakup timeout dan memiliki penggunaan memori konstan terlepas dari berapa banyak klien yang terhubung, sehingga tidak masalah menggunakan kembali objekSSLContextyang sama selama masa hidup server.
Konstanta¶
- ssl.PROTOCOL_TLS_SERVER: int¶
Nilai yang didukung untuk parameter protocol, memilih mode server TLS.
- ssl.PROTOCOL_DTLS_CLIENT: int¶
Nilai yang didukung untuk parameter protocol, memilih mode klien DTLS.
- ssl.PROTOCOL_DTLS_SERVER: int¶
Nilai yang didukung untuk parameter protocol, memilih mode server DTLS.
- ssl.CERT_NONE: int¶
Nilai yang didukung untuk parameter cert_reqs, dan atribut
SSLContext.verify_mode. Tidak ada verifikasi sertifikat yang dilakukan pada peer.
- ssl.CERT_OPTIONAL: int¶
Nilai yang didukung untuk parameter cert_reqs, dan atribut
SSLContext.verify_mode. Verifikasi sertifikat bersifat opsional. Perhatikan bahwa pada OpenMV Cam ini berperilaku sepertissl.CERT_NONE.
- ssl.CERT_REQUIRED: int¶
Nilai yang didukung untuk parameter cert_reqs, dan atribut
SSLContext.verify_mode. Sertifikat yang valid diperlukan dari peer.