Image default
Máy Tính

Camera Giám Sát và Frigate: Giải Pháp Tạo Entropy Ngẫu Nhiên An Toàn Như Cloudflare

Việc tạo ra các số ngẫu nhiên thực sự là một thách thức lớn trong thế giới kỹ thuật số, bởi lẽ máy tính vốn được thiết kế để hoạt động theo quy luật định sẵn, tức là mang tính xác định. Bất kỳ giá trị “ngẫu nhiên” nào mà máy tính tạo ra đều được suy luận từ các giá trị “thực” thông qua một thuật toán. Do đó, tính bảo mật của các số này phụ thuộc vào việc “gieo hạt” (seeding) chúng bằng dữ liệu mà kẻ tấn công không thể dự đoán. Một chiếc máy tính cần dữ liệu để làm cơ sở tạo ra thứ gì đó “ngẫu nhiên”, và nếu bạn có thể dự đoán dữ liệu gốc mà nó sử dụng, thì nó sẽ không còn ngẫu nhiên nữa. Các hệ điều hành hiện đại ngày nay đều tích hợp các bộ thu thập entropy được kiểm định kỹ lưỡng và các bộ tạo số giả ngẫu nhiên an toàn về mặt mật mã (CSPRNG – Cryptographically Secure Pseudorandom Number Generators) – đối với hầu hết các trường hợp sử dụng, bấy nhiêu là đủ.

Tuy nhiên, việc bổ sung thêm dữ liệu không thể dự đoán từ thế giới vật lý là một cách để nâng cao mức độ bảo mật lên một tầm cao mới. Đó là lý do tại sao bạn có thể đã từng nghe về những giải pháp độc đáo như bức tường đèn lava của Cloudflare, mà công ty này chụp ảnh liên tục để tạo ra một luồng byte có entropy cao cho việc tạo khóa TLS của họ. Lý do rất đơn giản: các cảnh tự nhiên động tạo ra dữ liệu pixel biến đổi rất nhiều, ngay cả nhiễu cảm biến cấp thấp cũng thêm vào tính không thể đoán trước, và các ảnh chụp định kỳ có thể được hash và trộn vào một pool entropy. Lấy cảm hứng từ ý tưởng đó, tôi đã tự xây dựng một giải pháp thay thế bằng cách sử dụng Frigate, một nền tảng NVR mã nguồn mở, và một chiếc camera Wi-Fi giá cả phải chăng.

Để thực hiện điều này một cách đúng đắn, bạn cần phải trích xuất dữ liệu hình ảnh thô từ camera, và cũng cần có một nguồn entropy ngay trước nó. Tôi sống ở Ireland, một quốc gia rất nhiều gió, và camera CCTV ngoài trời của tôi hướng vào một nhóm cây cối đang lung lay và di chuyển rất nhiều – đó chính là nguồn entropy của tôi. Nếu bạn có một camera được kết nối với máy tính Linux, bạn có thể lấy dữ liệu thô bằng một công cụ như fswebcam. Tuy nhiên, dự án này chỉ là một bằng chứng về khái niệm (proof of concept) hơn là một giải pháp bảo mật thực sự, và nên được xem xét như vậy. Đây không phải là giải pháp thay thế trực tiếp cho RNG của hệ điều hành của bạn.

Tại sao Entropy lại quan trọng và vai trò của Frigate

Bản chất của sự ngẫu nhiên và tầm quan trọng của Entropy

Bức tường đèn lava của Cloudflare - Nguồn tạo entropy ngẫu nhiên vật lý cho mật mã họcBức tường đèn lava của Cloudflare – Nguồn tạo entropy ngẫu nhiên vật lý cho mật mã học

Trong ngôn ngữ hàng ngày, entropy là một thước đo của sự hỗn loạn. Trong mật mã học, entropy tốt hơn nên được hiểu là tính khó đoán. Nguồn ngẫu nhiên của bạn càng có nhiều entropy, thì kẻ tấn công càng khó phát hiện các mẫu, và các khóa, IVs (Initialisation Vectors), nonces (numbers used once) và one-time pads của bạn sẽ càng mạnh hơn. Hầu hết các hệ điều hành đã duy trì một kernel entropy pool, và bạn thậm chí có thể thấy điều này trên Linux bằng cách chạy lệnh sau:

head -c 32 /dev/urandom | hexdump -C

Lưu ý rằng /dev/urandom, khi được đọc trong thời gian khởi động sớm, có thể trả về dữ liệu trước khi pool entropy của hệ thống được khởi tạo. Do đó, getRandom hoặc /dev/random có thể được sử dụng thay thế, mặc dù /dev/urandom vẫn là lựa chọn tốt hơn trong hầu hết các trường hợp.

Mặc dù vậy, đôi khi bạn cần sự ngẫu nhiên dành riêng cho ứng dụng. Một ví dụ điển hình là ví phần cứng (hardware wallet) luôn duy trì tính xác định qua các chu kỳ tắt/bật nguồn. Hơn nữa, dữ liệu thế giới thực sẽ luôn luôn vượt trội hơn bất cứ thứ gì hệ thống của bạn tạo ra làm entropy, và đó là lúc một bộ cấp entropy chuyên dụng có thể giúp ích. Đã có những ví dụ khác về các bộ tạo entropy mà bạn có thể sử dụng, như tính ngẫu nhiên thực sự dựa trên nhiễu khí quyển của random.org.

Nếu bạn đã từng nghe về khái niệm thao túng RNG (RNG manipulation), phổ biến trong nhiều trò chơi và thường là một thành phần của các nỗ lực speedrun, thì khái niệm tương tự cũng áp dụng cho bất kỳ cấp độ ngẫu nhiên nào trên máy tính. Mặc dù thao túng RNG thường vô hại trong một trò chơi, điều đó không đúng khi xử lý các vấn đề bảo mật thực tế. Điều đáng nói là các trò chơi (đặc biệt là các tựa game cũ hơn) sẽ sử dụng các thuật toán đơn giản, dễ dự đoán hơn cho các sự kiện “ngẫu nhiên” của chúng, và thao túng RNG là một chiến thuật phổ biến trong các trò chơi như Pokémon để bắt Pokémon shiny hoặc gặp Pokémon có chỉ số tốt hơn.

Những gì tôi đã tạo ra, về cơ bản, là một giải pháp trung gian giữa một thứ quá phức tạp như bức tường đèn lava của Cloudflare và việc không có bất kỳ entropy nào cả. Tôi đã có Frigate được cấu hình với một vài camera, vì vậy khá dễ dàng để sử dụng nó và API của nó để tạo ra các khóa riêng nếu tôi cần. Hầu hết mọi người không bao giờ cần đến mức độ tạo khóa mật mã an toàn này, nhưng đây là một bài tập để chứng minh cách nó có thể được thực hiện và sử dụng nó như một công cụ để giải thích tại sao nó lại cần thiết trong một số bối cảnh nhất định.

Về lý do tại sao chúng ta sử dụng Frigate, câu trả lời là nó có một API tuyệt vời mà bất kỳ ai có quyền ủy quyền đều có thể truy cập. Nó dễ sử dụng, là một phần mềm được triển khai phổ biến và tính năng API vượt trội cho dự án này là khả năng lấy một snapshot của khung hình mới nhất được camera chỉ định chụp. Nó nằm tại địa chỉ:

https://(IP):5000/api/(camera_name)/latest.jpg

Điều tuyệt vời của phương pháp này là mỗi khung hình sẽ khác nhau, ngay cả khi, bằng mắt thường, hình ảnh không thay đổi. Ánh sáng, chuyển động và các khía cạnh khác của bức ảnh khiến dữ liệu không bao giờ thực sự giống nhau, và điều đó quan trọng vì lý do entropy. Một luồng byte đầu vào không bao giờ được giống hệt một luồng khác, vì vậy chúng ta có thể kết hợp điều đó với entropy được tính toán của hệ thống thông qua một hàm dẫn xuất khóa (key derivation function) và xây dựng một “hạt giống” (seed) độc đáo cho quá trình tạo mật mã của chúng ta. Mặc dù tôi sử dụng JPG cho dự án này, JPG không được khuyến khích cho một triển khai thực sự sẵn sàng cho sản xuất. Nó có một khối dữ liệu có thể dự đoán được và khá giống với phần tiêu đề, và nén cũng sẽ tạo ra các khu vực của hình ảnh rất giống với cùng một khu vực trong các hình ảnh khác. Tốt hơn hết bạn nên sử dụng các khung hình thô hoặc, ít nhất, các định dạng không mất dữ liệu như PNG và hash dữ liệu pixel không nén.

Do đó, dự án này là một bằng chứng về khái niệm và nên được xem xét như vậy.

Kết hợp mọi thứ: Từ ảnh camera đến khóa mã hóa an toàn

Thu thập dữ liệu từ Frigate và tính toán giá trị Hash

Mã Python minh họa quá trình thu thập seed ngẫu nhiên từ Frigate để tạo khóa mã hóa an toànMã Python minh họa quá trình thu thập seed ngẫu nhiên từ Frigate để tạo khóa mã hóa an toàn

Để xây dựng dự án này một cách hoàn chỉnh, bạn sẽ cần một instance Frigate có camera được kết nối và bạn sẽ cần Python với các thư viện cryptographyrequests đã được cài đặt. Chúng ta sẽ tạo một hàm Python để thực hiện yêu cầu đến nguồn hình ảnh và sau đó trả về dưới dạng một luồng byte. Luồng dữ liệu này sau đó có thể được hash với quá trình tạo giả ngẫu nhiên của hệ thống của chúng ta hoặc được sử dụng riêng để tạo seed. Dưới đây là đoạn mã Python để tạo ra các giá trị đó:

 # Build 512-bit seed from frame and 256 bits OS entropy
 seed = hashlib.sha512(frame + os.urandom(32)).digest()

 # Fresh HKDF object each iteration
 aes_key = HKDF(
 algorithm=hashes.SHA256(),
 length=32,
 salt=None,
 info=b"frigate-rng",
 backend=default_backend(),
 ).derive(seed)

 # HMAC-SHA256 demo
 h = hmac.HMAC(aes_key, hashes.SHA256(), backend=default_backend())
 h.update(b"hello xda")
 tag = h.finalize()

 # Printable 64-char token
 token = token_from_seed(seed)

 def token_from_seed(seed: bytes, length: int = 64, symbols: bool = False) -> str:
 alphabet = string.ascii_letters + string.digits
 if symbols:
 alphabet += string.punctuation
 # HKDF just to expand/compress the seed into exactly <length> bytes
 token_raw = HKDF(
 algorithm=hashes.SHA256(),
 length=length,
 salt=None,
 info=b"frigate-token",
 backend=default_backend(),
 ).derive(seed)
 return ''.join(alphabet[b % len(alphabet)] for b in token_raw)

Tại thời điểm này, chúng ta có mọi thứ mình cần: một snapshot camera thay đổi mỗi giây và một chút entropy hệ thống. Chúng ta kết hợp hai luồng byte đó thành một seed 512 bit duy nhất và ngay lập tức dẫn xuất ba tạo phẩm:

  • Khóa AES-256: Dài 32 byte, phù hợp cho các lược đồ như AES-GCM hoặc AES-SIV.
  • Thẻ HMAC-SHA256: Xác thực thông điệp với một khóa mới.
  • Một token dài 64 ký tự bao gồm các ký tự chữ hoa, chữ thường và số, có thể được sử dụng cho mật khẩu hoặc các ứng dụng yêu cầu token để lưu trữ cục bộ.

Tuy nhiên, chỉ vì nó nên ngẫu nhiên không có nghĩa là nó thực sự ngẫu nhiên, vì vậy tôi đã đưa thuật toán vào thử nghiệm. Tôi đã gửi hàng ngàn yêu cầu đến máy chủ Frigate của mình, kiểm tra xem một hình ảnh có độc nhất hay không. Nếu có, tôi sẽ kéo nó, hash nó bằng khóa giả ngẫu nhiên được hệ thống tạo ra, và sau đó lưu giá trị seed đầu ra vào một tệp. Một giải pháp thích hợp hơn cho việc này là chủ động hash từng hình ảnh và kiểm tra các va chạm, nhưng đối với trường hợp sử dụng này, nó hoạt động khá tốt. Tôi đã sử dụng hai camera của mình trong Frigate để tăng tốc độ. Bằng cách thực hiện điều này lặp đi lặp lại, chúng ta có thể tạo ra nhiều kết quả khác nhau, và sau đó kiểm tra sự nối ghép cuối cùng của mọi seed bằng một công cụ như Dieharder.

Thử nghiệm thực tế với Dieharder

Kết quả kiểm tra Dieharder trên mẫu seed entropy từ Frigate và /dev/urandom cho thấy tính ngẫu nhiênKết quả kiểm tra Dieharder trên mẫu seed entropy từ Frigate và /dev/urandom cho thấy tính ngẫu nhiên

Dieharder là một công cụ miễn phí được xây dựng để kiểm tra các bộ tạo số ngẫu nhiên, nhưng ý tưởng là nó được cho là phải nhận vào gigabyte dữ liệu và xác định xem có bất kỳ mẫu nào không. Khi bạn cung cấp cho nó một kích thước mẫu giới hạn, nó sẽ “rewind” tệp nhiều lần, và điều này sẽ ảnh hưởng đáng kể đến kết quả kiểm tra. Tôi đã không cung cấp cho nó lượng dữ liệu cần thiết thông thường để kiểm tra thực sự, nhưng kết quả vẫn khá tốt. Để so sánh, một số bài kiểm tra lớn nhất của nó (như rgb_lagged_sum) yêu cầu tối thiểu 13.5 GB dữ liệu. Tuy nhiên, đối với một kiểm tra nhanh chóng về tính hợp lý, các bài kiểm tra ban đầu khá hữu ích và cho chúng ta một chỉ dẫn liệu chúng ta có đang đi đúng hướng hay không. Tôi đã thu thập khoảng 11 MB dữ liệu và vẫn thấy một số kết quả rất hứa hẹn.

Vượt qua hầu hết các bài kiểm tra ban đầu, với lượng dữ liệu thấp này, không chứng minh rằng luồng là hoàn hảo, nhưng đó là một tín hiệu ban đầu tốt trước khi bạn dành hàng giờ để thu thập các mẫu nhiều gigabyte cho toàn bộ quá trình thử nghiệm. Bất kỳ kết quả tốt nào ở đây sẽ cho thấy (để rõ ràng, không xác nhận) rằng thuật toán của chúng ta đang hoạt động, mặc dù đây là một kiểm tra tính hợp lý sơ bộ chứ không phải là một sự đảm bảo. Để có ngữ cảnh, với việc chúng ta đang sử dụng một giá trị ngẫu nhiên đã biết vượt qua các bài kiểm tra của Dieharder (/dev/urandom trên máy ảo Linux của tôi) để hashing, điều đó làm tăng xác suất vượt qua các bài kiểm tra này. Việc bao gồm /dev/urandom vào hỗn hợp có nghĩa là Dieharder đang xác thực bộ tạo số giả ngẫu nhiên của kernel, cộng thêm bất kỳ entropy bổ sung nào được thêm vào bởi camera.

Phân tích Dieharder chỉ với dữ liệu ảnh camera, chứng minh khả năng tạo số ngẫu nhiên bảo mậtPhân tích Dieharder chỉ với dữ liệu ảnh camera, chứng minh khả năng tạo số ngẫu nhiên bảo mật

Sau đó tôi đã đi xa hơn một chút; tôi đã loại bỏ hoàn toàn /dev/urandom khỏi phương trình, nơi tôi chỉ hash toàn bộ khung hình riêng lẻ, loại bỏ entropy cấp độ hệ điều hành, và tính toán khóa AES 256 bit từ đó. Tôi đã thu thập 22MB seed (mất vài giờ), và kết quả thực sự ấn tượng. Một lần nữa, với việc cần một tệp lớn hơn nhiều để kiểm tra thực sự nhiều thuật toán này, các giá trị “pass” này là một chỉ dẫn khá tốt cho thấy chúng ta đang đi đúng hướng để tạo số ngẫu nhiên an toàn về mặt mật mã.

Ứng dụng và cân nhắc bảo mật

Liệu điều này có thể được sử dụng để tạo khóa an toàn về mặt mật mã? Thực tế, bạn nên dùng /dev/urandom thì tốt hơn. Lượng công việc cần thiết để đảm bảo tính xác thực của thuật toán này và độ an toàn của nó không đáng để đánh đổi lấy một lượng lợi ích nhỏ bé mà nó mang lại. Tuy nhiên, việc triển khai các công cụ như thế này không phải là điều điên rồ, phi thực tế. Như chúng ta đã thấy, Cloudflare cũng có các giải pháp tương tự, và có lý do cho điều đó. Trong bối cảnh phù hợp, nó có thể an toàn hơn về mặt kỹ thuật, và đó là điều quan trọng nhất khi nói đến môi trường doanh nghiệp.

Cũng cần lưu ý rằng tôi đã thực hiện một số “phím tắt” trong dự án này, như sử dụng JPG thay vì PNG và không sử dụng đầu vào thô. Tuy nhiên, ngay cả khi đó, kết quả vẫn rất ấn tượng. Nó hoàn toàn khả thi với một chút công sức nữa, nghĩa là bạn cũng có thể tự tạo bức tường đèn lava của riêng mình. Giống như Cloudflare.


Kết luận

Việc tạo ra số ngẫu nhiên thực sự, khó đoán là nền tảng của mật mã học hiện đại. Mặc dù các hệ điều hành đã cung cấp các giải pháp mạnh mẽ như CSPRNG và /dev/urandom, ý tưởng bổ sung entropy từ thế giới vật lý, như bức tường đèn lava của Cloudflare hay giải pháp dựa trên camera giám sát Frigate mà chúng ta vừa khám phá, mang đến một lớp bảo mật tiềm năng khác. Dự án này, dù chỉ ở mức “proof of concept” và có một số hạn chế về mặt thực thi, đã chứng minh rõ ràng khả năng của việc tận dụng dữ liệu hình ảnh động để tạo ra các seed ngẫu nhiên chất lượng cao. Nó không chỉ là một minh chứng thú vị về kỹ thuật mà còn là một lời nhắc nhở về tầm quan trọng không ngừng của việc đổi mới trong lĩnh vực an ninh mạng. Hãy chia sẻ ý kiến của bạn về giải pháp này hoặc bất kỳ ý tưởng sáng tạo nào khác để tăng cường tính ngẫu nhiên trong mật mã ở phần bình luận bên dưới nhé!

Related posts

Tối Ưu Dual-Boot Windows Và Linux: 5 Giải Pháp Khắc Phục Lỗi Phổ Biến

Administrator

Vì Sao SSD Cấp Doanh Nghiệp Đã Qua Sử Dụng Là Lựa Chọn Lưu Trữ Thông Minh?

Administrator

Kích Hoạt XMP/EXPO Cho RAM: Mở Khóa Hiệu Suất PC Tối Đa Chỉ Với Một Click

Administrator