Khai thác tính năng nhúng video của Slack để tạo liên lạc mã hóa đầu cuối (E2EE)
Một nhà phát triển đã sáng tạo sử dụng khối video của Slack để chạy mã hóa phía máy khách, cho phép gửi tin nhắn E2EE mà máy chủ không thể đọc được. Dự án này tận dụng iframe và thư viện OpenPGP.js để biến Slack thành một kênh liên lạc bảo mật hơn.

Khai thác tính năng nhúng video của Slack để tạo liên lạc mã hóa đầu cuối (E2EE)
Gần đây, trong quá trình nghiên cứu tài liệu Block Kit của Slack, tôi nhận ra một điểm thú vị: khối video (video block). Khi thấy rằng nó chấp nhận một tham số video_url, câu hỏi đầu tiên xuất hiện trong đầu tôi là: Slack phân biệt nội dung nào là video thực sự và nội dung nào không? Có yêu cầu hay giới hạn đặc biệt nào đối với nguồn nhúng không?
Câu trả lời là không. Không có kiểm tra thời gian chạy (runtime check) nào ngoài việc kiểm tra xem URL được cung cấp có truy cập được và trả về mã trạng thái 2xx hay 3xx hay không. Sau các kiểm tra đó, nó không gì khác hơn là một iframe đơn giản.
Vì vậy, tôi đã nảy ra một ý tưởng: Điều gì sẽ xảy ra nếu có một ứng dụng cho phép bạn mã hóa tin nhắn bằng cặp khóa và gửi chúng qua Slack?
Quy trình gửi tin nhắn mã hóa
Ý tưởng và Cơ chế hoạt động
Ý tưởng rất đơn giản. Bên trong máy khách của bạn, sử dụng API mật mã của trình duyệt, bạn tạo một cặp khóa, mã hóa khóa riêng tư và gửi nó đến máy chủ. Sau đó, bất cứ khi nào bạn muốn thực hiện thao tác (ký, mã hóa, giải mã), máy chủ sẽ gửi lại khóa của bạn và bên trong khối video, bạn sẽ giải mã khóa của mình và thực hiện thao tác.
Bằng cách này, máy chủ không bao giờ nhận được khóa đã giải mã, nhưng thông qua các cặp khóa, bạn có thể mã hóa tin nhắn cho bất kỳ ai.
Quy trình triển khai
Để phát triển ứng dụng này, tôi đã chọn TypeScript. Không có lý do gì đặc biệt ngoài việc tôi đã quen thuộc với nó và có thể lặp lại nhanh chóng.
Trong quá trình triển khai ứng dụng Slack, tôi đã mất một khoảng thời gian đáng kể mới nhận ra rằng các khối video không thể được bao gồm trong các tin nhắn tạm thời (ephemeral messages). Hành vi này không được ghi lại ở bất kỳ đâu trong tài liệu.
Về phần mã hóa, ban đầu tôi thử tự viết toàn bộ logic mã hóa bằng cách sử dụng subtle crypto API của trình duyệt (có sẵn đầy đủ trong khối video của Slack). Tuy nhiên, tôi sớm nhận ra sự khó khăn của nó và có bao nhiêu kỹ thuật cũng như trường hợp tôi cần phải lưu ý.
May mắn thay, trước khi gặp nhiều khó khăn hơn, tôi đã tìm thấy openpgpjs. Đây là một thư viện tuyệt vời được Proton duy trì (những người tạo ra dịch vụ email bảo mật) thực hiện tất cả các thao tác mật mã học mà tôi cần.
Giao diện ứng dụng E2EE trên Slack
Tôi muốn máy chủ lưu trữ càng ít dữ liệu càng tốt bằng cách lưu trữ hầu hết dữ liệu trong các trường metadata của Slack. Tuy nhiên, do độ dài của các tin nhắn đã mã hóa, tôi không thể sử dụng tính năng này.
Để phục vụ các iframe, tôi đã sử dụng một hệ thống slug. Trong mỗi cuộc gọi cần tương tác của máy khách, một slug duy nhất chứa dữ liệu cần thiết để thực hiện hành động sẽ được lưu trữ trong cơ sở dữ liệu KV. Khi nhúng video được tải, thông tin này được nhúng cùng với mã máy khách để tất cả các thao tác mật mã có thể được thực hiện cục bộ.
Ví dụ, quy trình để mã hóa một tin nhắn rất đơn giản:
- Thực hiện lệnh Slack
/e2ee send. Một modal của Slack sẽ mở ra, yêu cầu người nhận tin nhắn. - Sau khi modal đó được gửi đi, một slug được tạo ra, chứa: khóa riêng tư của tác giả & khóa công khai của người nhận.
- Khi nhấp vào khối video bên trong Slack, máy khách cục bộ được tải với thông tin trên.
- Tác giả giải mã khóa riêng tư của họ thông qua cụm mật khẩu (cục bộ).
- Tác giả viết tin nhắn, mã hóa nó cho người nhận và ký nó bằng khóa của mình (cục bộ).
- Tác giả chỉ gửi tin nhắn đã mã hóa.
- Máy chủ gửi các phong bì (envelopes) đến từng người nhận của tin nhắn.
Kết luận và Triển vọng
Bạn có thể xem dự án ngay bây giờ, mã nguồn có tại gh:v1ctorio/e2ee-slack. Và bạn có thể tự host (triển khai) cho không gian làm việc Slack của mình trong khoảng 5 phút.
Dự án này kết quả là một "hack" vì nó không tuân thủ hoàn toàn các ràng buộc thiết kế của Slack. Nhưng nó khiến tôi suy nghĩ.
Với tất cả sự linh hoạt mà các công nghệ web mang lại, liệu các dịch vụ lớn có nên hỗ trợ các ứng dụng đầy đủ tính năng bên trong máy khách của họ không? Tôi ý là Discord đã làm điều gì đó tương tự với 'Activities', hoặc Telegram với 'Mini Apps'. Liệu có phải sẽ rất thú vị nếu thấy nhiều dịch vụ chính thống hơn áp dụng cách tiếp cận này không?



