14.4.3. Chứng chỉ tự ký

Chứng chỉ tự ký là cách nhanh nhất để TLS hoạt động giữa hai thiết bị bạn kiểm soát: cả hai đầu tin cậy một chứng chỉ duy nhất mà bạn tự tạo ra. Nó bao gồm mọi triển khai trong đó bạn cấu hình cả hai phía của kết nối -- Cơ quan Chứng nhận công khai chỉ xuất hiện khi các máy khách bên thứ ba phải kết nối mà không được yêu cầu tin cậy vào chứng chỉ tùy chỉnh.

14.4.3.1. Tạo chứng chỉ tự ký

Chạy OpenSSL trên máy phát triển của bạn. subjectAltName (SAN) là thứ mà các máy khách TLS hiện đại kiểm tra trong quá trình xác minh tên máy chủ, vì vậy hãy đặt nó thành tên máy chủ và/hoặc địa chỉ IP mà các máy khách sẽ sử dụng để tiếp cận camera (chỉ CN là di sản và bị nhiều máy khách bỏ qua). Thay thế DNS:openmv / IP:192.168.1.50 bằng địa chỉ mà các máy khách của bạn thực sự kết nối.

ECDSA P-256 -- được khuyến nghị:

# Generate a P-256 private key.
openssl ecparam -name prime256v1 -genkey -noout -out server.key

# Self-signed certificate valid for one year, with a SAN.
openssl req -new -x509 -key server.key -out server.crt -days 365 \
    -subj "/CN=openmv" -addext "subjectAltName=DNS:openmv,IP:192.168.1.50"

ECDSA P-384 -- mạnh hơn, lớn hơn/chậm hơn:

openssl ecparam -name secp384r1 -genkey -noout -out server.key

openssl req -new -x509 -key server.key -out server.crt -days 365 \
    -subj "/CN=openmv" -addext "subjectAltName=DNS:openmv,IP:192.168.1.50"

RSA-2048 -- tương thích tối đa:

openssl req -new -x509 -newkey rsa:2048 -nodes -keyout server.key \
    -out server.crt -days 365 -subj "/CN=openmv" \
    -addext "subjectAltName=DNS:openmv,IP:192.168.1.50"

Ghi chú

Chứng chỉ máy khách (được sử dụng để xác thực lẫn nhau, bên dưới) được tạo với chính xác các lệnh tương tự -- không có gì đặc biệt cho máy khách trong bản thân chứng chỉ. Chỉ cần tạo một cặp khóa/chứng chỉ thứ hai, độc lập với tên khác nhau (ví dụ: client.key / client.crt) và sử dụng nó trên máy khách như được hiển thị trong ví dụ mTLS. subjectAltName chỉ quan trọng cho phía mà tên máy chủ của nó được peer xác minh (máy khách kiểm tra tên máy chủ của máy chủ; không có gì kiểm tra tên máy khách), vì vậy nó có thể bị bỏ qua cho chứng chỉ chỉ dành cho máy khách. -subj / CN cũng chỉ là nhãn trên chứng chỉ máy khách -- phía máy chủ ở đây chỉ kiểm tra rằng chứng chỉ liên kết với CA được tin cậy, nó không bao giờ khớp tên -- vì vậy hãy đặt nó thành bất cứ điều gì xác định máy khách đó (ví dụ: /CN=sensor-01). Giữ một giá trị -subj bất kể thế nào, để OpenSSL có thể tạo chứng chỉ không tương tác.

Thời gian sống của chứng chỉ được đặt bởi -days; chứng chỉ hết hạn và phải được tạo lại và triển khai lại trước đó.

14.4.3.2. Chuyển đổi sang DER

Chuyển đổi cả chứng chỉ và khóa riêng tư sang DER trước khi sao chép chúng vào camera:

openssl x509 -in server.crt -outform DER -out server.der
openssl pkey -in server.key -outform DER -out server.key.der

14.4.3.3. Sao chép tệp vào camera

Sao chép các tệp DER vào hệ thống tệp của camera -- ví dụ bằng cách kéo chúng vào ổ đĩa USB của OpenMV Cam, hoặc với mpremote cp server.der :mpremote cp server.key.der :. Trên phía xác minh, cũng sao chép chứng chỉ CA / peer ở dạng DER.

Các tệp DER không cần phải tồn tại trên hệ thống tệp có thể ghi. MicroPython cũng có thể gắn kết một hình ảnh ROMFS chỉ đọc tại /rom, và các chứng chỉ được đặt ở đó được tải giống như bất kỳ tệp nào khác -- ví dụ: ctx.load_cert_chain("/rom/server.der", "/rom/server.key.der"). Hình ảnh ROMFS được chuẩn bị trên máy phát triển của bạn và chỉ đọc khi runtime, vì vậy chứng chỉ không thể bị thay đổi trên thiết bị -- hữu ích để khóa một đơn vị sản xuất. Lưu ý rằng khóa riêng tư được lưu trữ trong ROMFS vẫn có thể đọc được bởi mã chạy trên camera; ROMFS bảo vệ chống lại sửa đổi, không phải trích xuất. Chứng chỉ nằm trong ROMFS chỉ có thể được thay thế bằng cách xây dựng lại và nạp lại hình ảnh.

14.4.3.4. Sử dụng chứng chỉ

Một máy khách hoàn chỉnh đặt đồng hồ, mở socket, xác minh máy chủ tự ký và trao đổi dữ liệu:

import socket
import ssl
import ntptime

ntptime.settime()                 # correct clock for the validity check

# Open a plain TCP connection.
addr = socket.getaddrinfo("openmv", 8443)[0][-1]
sock = socket.socket()
sock.connect(addr)

# Wrap it for TLS, trusting the server's self-signed certificate.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="server.der")
ssock = ctx.wrap_socket(sock, server_hostname="openmv")

ssock.write(b"hello\n")
print(ssock.read())
ssock.close()

Một máy chủ hoàn chỉnh trình bày chứng chỉ và khóa của nó:

import socket
import ssl
import ntptime

ntptime.settime()                 # correct clock for the validity check

ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("server.der", "server.key.der")

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)

while True:
    client, addr = sock.accept()
    sclient = ctx.wrap_socket(client, server_side=True)
    sclient.write(b"hello\n")
    print(sclient.read())
    sclient.close()

Để xác thực lẫn nhau (mTLS), máy chủ thêm vào yêu cầu và xác minh chứng chỉ máy khách, và máy khách trình bày một chứng chỉ của riêng mình:

# Server side: also demand and verify a client certificate.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("server.der", "server.key.der")
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="client.der")

# Client side: present a certificate of our own.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.load_cert_chain("client.der", "client.key.der")
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="server.der")

Xem tài liệu module ssl để biết toàn bộ API.

Ghi chú

Mọi thứ trên trang này áp dụng không thay đổi cho DTLS (TLS qua UDP). Các khóa, chứng chỉ, định dạng DER, mô hình tin cậy, lo ngại hết hạn, và các lệnh gọi load_cert_chain / load_verify_locations giống hệt nhau; chỉ có phương tiện truyền tải khác nhau -- bạn bọc socket socket.SOCK_DGRAM và chọn ssl.PROTOCOL_DTLS_CLIENT / ssl.PROTOCOL_DTLS_SERVER thay vì các hằng số giao thức TLS. Sự phức tạp thêm là cookie chống giả mạo phía máy chủ -- kết nối đầu tiên từ một máy khách mới dự kiến sẽ thất bại và máy khách chỉ cần thử lại; xem Hỗ trợ DTLS để biết chi tiết.