Tôi tạo định danh phi tập trung cho blog: did:web là gì và chữ ký số trên bài viết chứng minh được gì?
Blog có định danh phi tập trung did:web và chữ ký số Ed25519 cho từng bài: DID là gì, cách công bố, cách tự kiểm chứng và điều chữ ký không chứng minh được.
Nghe 7 phút Đã ký sốĐã neo Bitcoin · khối #972625Xem bằng chứng ↓CHUỖI BÀI · PHẦN 3/4 Xuất bản AI-nativePhần tiếp: MCP: khi AI bước ra khỏi khung chat để làm việc
Phóng viên hỏi, tác giả trả lời. Kịch bản do AI viết từ bài, giọng đọc do AI tạo (không phải giọng tác giả). Có thể diễn giải khác bài gốc; bài viết là bản chính thức.
Trong bài Bitcoin và việc chứng thực tài liệu, tôi tìm cách chứng minh một bài viết đã có từ khi nào. Bài này đi tiếp một câu hỏi khác: làm sao chứng minh bài viết là của ai?
Câu hỏi nghe đơn giản nhưng ngày càng khó. Ảnh chụp màn hình “bài của Trung Phan” có thể dựng trong vài giây. AI có thể viết một đoạn văn giống giọng tôi rồi gắn tên tôi vào. Một trang web giả giao diện blog này có thể nằm ở một tên miền na ná. Người đọc gần như không có cách tự kiểm tra.
Vì vậy tôi thử làm một việc nhỏ trên chính blog này: tạo cho mình một định danh phi tập trung (gọi tắt là DID) và dùng nó để ký số từng bài viết. Dưới đây là cách nó hoạt động, giải thích càng đơn giản càng tốt.
1. Hai cách để biết một bài viết là của ai
Hiện nay, hầu hết chúng ta chứng minh “đây là tôi” bằng tài khoản do nền tảng cấp: Facebook, LinkedIn, Gmail, X. Người đọc tin một bài là của tôi vì nền tảng hiển thị tên tôi bên cạnh.
Cách này tiện, nhưng mọi niềm tin dồn vào nền tảng:
- Tài khoản bị khóa, bị chiếm hay nền tảng đóng cửa thì “tôi” ở đó cũng mất.
- Bài viết chép sang nơi khác thì không còn gì chứng minh tác giả.
- Muốn kiểm tra, người đọc phải tin nền tảng, không tự kiểm được.
Có một cách khác, đã có từ lâu trong mật mã học: chữ ký số. Người viết tự ký vào bài, người đọc tự kiểm chữ ký. Không cần ai đứng giữa.
2. Chữ ký số giống mẫu chữ ký ở ngân hàng
Cách dễ hình dung nhất là nghĩ tới chữ ký tay ở ngân hàng.
- Khi mở tài khoản, bạn để lại mẫu chữ ký. Ngân hàng giữ mẫu này để đối chiếu.
- Mỗi lần bạn ký giấy tờ, nhân viên so chữ ký với mẫu. Khớp thì đúng là bạn.
Chữ ký số làm đúng như vậy, chỉ khác là dùng toán học thay cho mắt người:
- Khóa riêng là “cây bút” chỉ mình bạn giữ. Ai có nó là ký được thay bạn, nên nó phải được cất kỹ.
- Khóa công khai là “mẫu chữ ký” bạn đưa cho mọi người. Nhìn vào nó, không ai đoán ra được khóa riêng.
- Chữ ký tạo bằng khóa riêng chỉ khớp với đúng khóa công khai đi cặp với nó. Chừng nào khóa riêng còn được giữ kín thì không ai giả được chữ ký, và sửa nội dung dù chỉ một ký tự thì chữ ký không còn khớp.
Phần toán học này đã giải quyết xong từ lâu. Câu hỏi khó còn lại là: treo “mẫu chữ ký” ở đâu để người đọc tin rằng nó đúng là của tôi? Đó là việc của DID.
3. DID là gì?
DID (Decentralized Identifier, tức định danh phi tập trung) là một chuẩn quốc tế của W3C, tổ chức đặt chuẩn cho web. Chuẩn này chính thức được công bố ngày 19/7/2022.1
Một DID là một cái tên, có dạng:
did:<cách tra cứu>:<tên cụ thể>
Mỗi DID trỏ tới một tài liệu DID: một tệp nhỏ ghi các khóa công khai của chủ nhân và mỗi khóa dùng vào việc gì. Nói theo ví dụ ngân hàng, tài liệu DID chính là tấm thẻ mẫu chữ ký, chỉ khác là treo công khai cho mọi người xem.
Khác biệt quan trọng nhất so với tài khoản nền tảng: không ai cấp DID cho tôi. Tôi tự tạo cặp khóa trên máy mình và tự công bố tài liệu DID. Người giữ khóa riêng là người làm chủ định danh.
Phần “cách tra cứu” quyết định tấm thẻ được treo ở đâu. Có cách ghi lên blockchain, có cách dùng mạng riêng. Tôi chọn cách đơn giản nhất: treo ngay trên blog.
4. did:web: treo mẫu chữ ký trên chính blog
Định danh của tôi là:
did:web:blog.phdtrung.com
Chữ web nghĩa là tài liệu DID nằm trên một website. Theo quy tắc của did:web, cái tên trên được đổi thành địa chỉ:2
https://blog.phdtrung.com/.well-known/did.json
Ai mở địa chỉ đó cũng thấy khóa công khai của tôi, tên là #key-1. Khóa này dùng thuật toán chữ ký Ed255193 và được ghi theo định dạng Multikey của W3C.4 Khóa riêng đi cặp với nó thì chỉ nằm trên máy tính của tôi.
Tôi chọn did:web vì ba lý do:
- Không cần blockchain, không tốn phí. Chỉ là một tệp nhỏ trên website tôi đã có.
- Dựa vào niềm tin sẵn có. Bạn đọc vốn đã biết
blog.phdtrung.comlà blog của tôi. Treo mẫu chữ ký ở đây là tận dụng đúng niềm tin đó. - Đã được dùng thật. Ví dụ, AT Protocol, giao thức đứng sau mạng xã hội Bluesky, chấp nhận
did:weblàm định danh tài khoản.5
5. Ký và kiểm một bài viết diễn ra thế nào?
Khi ký, việc của tôi chỉ là chạy một lệnh. Máy làm ba bước:
- Lấy văn bản gốc của bài và tính mã băm SHA-256. Mã băm giống dấu vân tay của văn bản: mỗi văn bản cho một dấu vân tay riêng, đổi một dấu phẩy là dấu vân tay đổi hẳn.
- Ghi một tờ khai ngắn: ai ký, bằng khóa nào, bài nào, dấu vân tay là gì, ký lúc nào.
- Ký tờ khai đó bằng khóa riêng, đóng gói theo chuẩn JWS6 với thuật toán EdDSA,7 rồi công bố thành một tệp chữ ký trên blog.
Khi kiểm, người đọc làm ngược lại:
- Tải tệp chữ ký. Trong đó ghi bài được ký bằng khóa
did:web:blog.phdtrung.com#key-1. - Tra tài liệu DID trên blog để lấy khóa công khai
#key-1. - Dùng khóa công khai kiểm chữ ký, rồi tính lại dấu vân tay của bài để so.
Khớp cả hai thì bài bạn đang đọc đúng nguyên văn bài mà người giữ khóa của blog đã ký.
Bài nào đã ký sẽ có khối “Chữ ký số” ở cuối, kèm liên kết tới tệp chữ ký và tài liệu DID. Chính bài viết này cũng được ký. Ai biết dùng dòng lệnh có thể kiểm bằng công cụ của blog hoặc bất kỳ thư viện nào hỗ trợ chuẩn JWS. Không cần tài khoản, không cần hỏi tôi, không cần tin GitLab hay Cloudflare.
6. Chuyện thật trên blog này: khóa cất ở đâu, ký thế nào?
Nghe “khóa riêng”, “ký số” thì dễ tưởng là thứ gì phức tạp lắm. Thực tế trên blog này đơn giản hơn nhiều.
Khóa riêng: một tệp nhỏ trên máy Mac của tôi
Khóa riêng của tôi là một tệp văn bản chỉ 3 dòng, nặng 119 byte, nằm trong một thư mục ẩn trên chiếc Mac tôi dùng hằng ngày. Không có thẻ cứng, không có thiết bị đặc biệt nào.
Tệp này được bảo vệ bằng ba lớp:
- Quyền đọc: chỉ tài khoản máy tính của tôi mở được tệp. Tài khoản khác trên cùng máy cũng không đọc được.
- Mã hóa ổ đĩa: ổ đĩa của máy được mã hóa bằng FileVault. Máy bị mất cắp thì người lấy cũng không đọc được tệp nếu không có mật khẩu đăng nhập.
- Không bao giờ rời máy: tệp nằm ngoài thư mục mã nguồn của blog, nên không bị đưa lên GitLab, không gửi qua email hay chat, không đưa cho AI.
Điểm yếu cũng cần nói rõ: mất tệp này (hỏng máy, xóa nhầm) là mất khả năng ký. Vì vậy khóa cần một bản sao lưu cất riêng, có mã hóa, ví dụ trên USB mã hóa hoặc trong trình quản lý mật khẩu. Còn nếu ai đó lấy được tệp, tôi phải đổi khóa ngay: treo khóa công khai mới lên blog và gỡ khóa cũ.
Mẫu chữ ký: một tệp công khai trên blog
Phần công khai thì ai cũng xem được tại blog.phdtrung.com/.well-known/did.json. Bỏ bớt các dòng kỹ thuật, nó trông như sau:
{
"id": "did:web:blog.phdtrung.com",
"verificationMethod": [{
"id": "did:web:blog.phdtrung.com#key-1",
"type": "Multikey",
"publicKeyMultibase": "z6MkfqVrcqW8qHLSEfUKW64nowR6Jbi99bHfGGj4WChaZy6o"
}]
}
Chuỗi bắt đầu bằng z6Mk… chính là khóa công khai, tức “mẫu chữ ký”. Từ chuỗi này không ai suy ngược ra được tệp khóa riêng trên máy tôi.
Ký một bài: gõ một lệnh
Khi một bài đã viết xong và tôi đã đọc duyệt lần cuối, tôi mở cửa sổ dòng lệnh trên Mac và gõ:
python3 scripts/did/sign_post.py content/posts/did-web-dinh-danh-phi-tap-trung.md
Trong vài giây, công cụ ký làm lần lượt:
- Kiểm tra tệp khóa vẫn đang được khóa quyền đọc như trên; nếu không thì dừng.
- Đọc khóa riêng, suy ra khóa công khai và so với “mẫu chữ ký” đang treo trên blog. Nếu khác (ví dụ lấy nhầm khóa) thì dừng, không ký.
- Tính dấu vân tay của bài, ghi tờ khai, ký tờ khai.
- Ghi kết quả ra một tệp chữ ký nằm cạnh bài viết.
Màn hình chỉ hiện ba dòng: địa chỉ bài, dấu vân tay và nơi lưu tệp chữ ký. Khóa riêng không bao giờ được in ra.
Ví dụ, tờ khai trong tệp chữ ký của lần ký đầu tiên bài này trông như sau (dấu vân tay rút gọn):
{
"did": "did:web:blog.phdtrung.com",
"kid": "did:web:blog.phdtrung.com#key-1",
"url": "https://blog.phdtrung.com/posts/did-web-dinh-danh-phi-tap-trung/",
"sha256": "6df08371…dae0b78",
"signedAt": "2026-10-22T12:54:02+07:00"
}
Kèm theo là chữ ký: một chuỗi khoảng 550 ký tự, chỉ khóa riêng của tôi tạo ra được.
Từ máy tôi lên blog
Tệp chữ ký đi lên blog theo đúng quy trình xuất bản thường ngày: lưu vào kho mã nguồn trên GitLab, mở yêu cầu hợp nhất (Merge Request), tôi duyệt, rồi hệ thống tự dựng lại trang. Trước khi đưa lên, hệ thống kiểm tra tự động còn so nội dung bài với dấu vân tay đã ký. Nếu ai sửa bài sau khi tôi ký, dù chỉ một chữ, bước kiểm tra sẽ chặn lại cho tới khi tôi ký lại.
Đoạn mô phỏng dưới đây tóm cả quá trình: ký trên máy tôi, kiểm trên trình duyệt của người đọc, và điều gì xảy ra khi có người sửa bài.
Ranh giới với AI
Blog này được vận hành cùng AI, nên tôi viết thành quy tắc bắt buộc cho mọi trợ lý AI làm việc với blog: không in, không đọc, không lưu khóa riêng; không tự chạy lệnh ký. AI được giúp viết bài, viết công cụ ký và công cụ kiểm, chuẩn bị mọi thứ, nhưng bước ký cuối cùng luôn do tôi tự gõ lệnh. Chữ ký có giá trị chính vì chỉ tôi tạo ra được nó.
7. Chữ ký chứng minh được gì, không chứng minh được gì?
Công nghệ mới rất dễ bị hiểu quá lên, nên phần này tôi nói thẳng.
Chữ ký chứng minh được:
- Bài được ký bằng khóa đang treo trên
blog.phdtrung.com. - Bài không bị sửa sau khi ký.
- Bản sao của bài ở nơi khác, nếu kèm tệp chữ ký, thì người đọc tự kiểm được có đúng nguyên văn hay không.
Chữ ký không chứng minh được:
- Thời điểm viết. Giờ ký do máy tôi tự ghi. Muốn chứng minh “đã có từ khi nào” thì cần một nguồn độc lập, như dấu thời gian OpenTimestamps trên Bitcoin trong bài trước.
- Nội dung là đúng. Chữ ký chỉ nói “tôi viết đoạn này và chịu trách nhiệm về nó”, không nói đoạn này đúng.
- Tôi là ai ngoài đời.
did:webchỉ chứng minh quyền kiểm soát một tên miền và một khóa, không gắn với căn cước công dân của tôi.
Điểm yếu của did:web:
- Chỉ an toàn bằng tên miền. Ai chiếm được tên miền hay quyền sửa blog thì có thể thay “mẫu chữ ký”. Chính đặc tả
did:webthừa nhận nhiều hướng tấn công đến từ hệ thống tên miền (DNS).2 - Không lưu lịch sử. Tệp
did.jsonchỉ có phiên bản hiện tại. Khi đổi khóa, muốn kiểm các chữ ký cũ thì phải giữ khóa cũ trong tệp một thời gian, hoặc tra lịch sử của kho mã nguồn. - Chưa phải chuẩn W3C chính thức.
did:webdo một nhóm cộng đồng của W3C soạn. Chuẩn DID nói chung thì đã chính thức.
Về pháp lý: chữ ký này không phải chữ ký số theo nghĩa của pháp luật Việt Nam. Luật Giao dịch điện tử yêu cầu chữ ký số phải được bảo đảm bởi chứng thư chữ ký số; với chữ ký số công cộng, chứng thư đó do tổ chức cung cấp dịch vụ chứng thực chữ ký số công cộng cấp.8 Chữ ký trên blog chỉ là công cụ kỹ thuật để người đọc tự kiểm, không dùng thay chữ ký số trong hợp đồng, giao dịch hay hồ sơ hành chính. (Nhận định này chỉ để tham khảo, không phải tư vấn pháp lý.)
8. Bước tiếp theo: từ định danh đến chứng nhận
Định danh và chữ ký bài viết mới là bước đầu. Bước tiếp theo trong cùng họ chuẩn là chứng nhận có thể kiểm chứng (Verifiable Credentials), được W3C công bố chính thức ngày 15/5/2025.9
Ví dụ, với định danh này tôi có thể cấp:
- Giấy xác nhận một người đã tham gia buổi chia sẻ hay khóa học do tôi hướng dẫn.
- Thư giới thiệu mà người nhận tự mang đi trình, bên nhận tự kiểm chứng mà không cần gọi hỏi tôi.
Tôi chưa làm phần này. Trước khi cấp chứng nhận cho người khác, tôi muốn tự dùng định danh và cách giữ khóa của mình một thời gian, xem nó có đứng vững không.
Thay lời kết
Thử nghiệm này không giải quyết bài toán danh tính trên Internet. Nó chỉ chuyển một phần niềm tin từ “tin vào nơi bạn thấy bài” sang “tự kiểm được bài có đúng nguyên văn hay không”.
Ghép với dấu thời gian trên Bitcoin, một bài viết có thể mang theo hai bằng chứng độc lập: ai viết và viết từ khi nào. Cả hai đều kiểm được mà không cần hỏi tôi, cũng không cần tin bất kỳ nền tảng nào.
Khi nội dung giả rẻ hơn bao giờ hết, tôi nghĩ người viết nên bắt đầu ký tên mình theo cách mà máy tính cũng kiểm được.
W3C, Decentralized Identifiers (DIDs) v1.0, W3C Recommendation ngày 19/7/2022. ↑ quay lại
W3C Credentials Community Group, did:web Method Specification: định danh không có đường dẫn được đổi thành
https://<tên miền>/.well-known/did.json; mục bảo mật nêu rủi ro DNS và việc đặc tả không quy định cơ chế xác thực khi ghi tài liệu DID. ↑ quay lại 2Thuật toán chữ ký Ed25519 được chuẩn hóa trong RFC 8032 (IETF, tháng 1/2017). ↑ quay lại
W3C, Controlled Identifiers v1.0, W3C Recommendation ngày 15/5/2025, định nghĩa kiểu khóa
Multikeyvà trườngpublicKeyMultibase. ↑ quay lạiAT Protocol, DID specification: giao thức hỗ trợ hai phương thức
did:plcvàdid:web. ↑ quay lạiJSON Web Signature (JWS) được chuẩn hóa trong RFC 7515 (IETF, tháng 5/2015). ↑ quay lại
Thuật toán
EdDSAcho JOSE/JWS được định nghĩa trong RFC 8037 (IETF, tháng 1/2017). ↑ quay lạiLuật Giao dịch điện tử số 20/2023/QH15, hiệu lực từ 01/7/2024. Điều 22 khoản 3: chữ ký số phải được bảo đảm bởi chứng thư chữ ký số; chữ ký số công cộng phải được bảo đảm bởi chứng thư chữ ký số của tổ chức cung cấp dịch vụ chứng thực chữ ký số công cộng. ↑ quay lại
W3C, Verifiable Credentials Data Model v2.0, W3C Recommendation ngày 15/5/2025. ↑ quay lại
Bài này có giúp ích cho bạn không?
Góp ý và phản biện.
Rất hoan nghênh góc nhìn khác biệt và phản biện có căn cứ.
Có góp ý, phản biện hay phát hiện lỗi trong bài? Gửi qua form của blog, không cần tài khoản. Cần tác giả giải thích thêm hay trả lời riêng qua email thì chọn Hỏi tác giả.