Nhận dạng kỹ thuật số là một trong những vấn đề lâu đời và khó nhất trên Internet. Trước đây, chưa có cách nào chứng minh thông tin đăng nhập kỹ thuật số là danh tính thực của một người như ở thế giới thực. Cuối cùng điều này đag thay đổi, đầu tiên W3C đag chuẩn hoá định dạng của các thông tin được ký điện tử (digital-signed credentials); thứ hai, mạng lưới blockchain công khai cung cấp hệ thống đăng ký phi tập trung và khám phá khoá công khai cần thiết để xác minh chữ ký số.
1. Vấn đề
Trong thế giới thực, chúng ta sử dụng các thông tin vật lý để chứng thực định danh. Trong thế giới số, chúng ta không có cách chuẩn nào để xác định thông tin số.
Để xác nhận thông tin số, chúng ta phải giải quyết hai vấn đề:
- Chuẩn hoá định dạng -> W3C đang chuẩn hoá
- Chuẩn hoá cách xác nhận thông tin nguồn và tính toàn vẹn của nó: -> làm thế nào để chuẩn hoá việc xác minh chữ ký số của thông tin người phát hành? -> PKI (public key infrastructure): cồng kềnh, tốn kém, không phân tán ~ thường chỉ có công ty mới mua certificate, nếu root/CA có vấn đề hoặc hệ thống có vấn đề -> ....
2. Giải pháp
- Blockchain mở là một hệ thống phi tập trung của root of trust, không ai sở hữu và mọi người đều có thể sử dụng.
- Blockchain thay thế niềm tin con người bằng niềm tin toán học.
- Mỗi transaction trong blockchain được ký bởi block ban đầu.
- Mỗi transaction - đơn hay khối - được móc nối với giao dịch trước đó bởi 1 mã băm kỹ thuật số. Một mã băm kỹ thuật số là một dấu tay điện tử mà có tính duy nhất trên toàn cầu và cực kỳ khó để giả mạo.
- Các giao dịch được xác nhận sẽ được sao chép sang các máy theo thuật toán đồng thuận.
- Trong hệ thống blockchain, các khoá công khai (publish key) có địa chỉ của nó. Địa chỉ này được gọi là định danh phi tập trung (decentralize identifier) viết tắt là DID - một chuẩn từ W3C. DID cung cấp một cách chuẩn mà các cá nhân hay tổ chức có thể tạo ra một định danh vĩnh viễn, duy nhất trên toàn cầu và có thể xác nhận bằng mã hoá dưới sự cho phép của chủ định danh này.
- DID là nhận dạng số có thể xác minh duy nhất trên toàn cầu đầu tiên mà không yêu cầu cơ quan đăng ký.
- DID được lưu trên blockchain cùng với:
Khoá công khai - publish keyCác thông tin mà chủ của đinh danh muốn tiết lộĐịa chỉ mạng cho sự tương tác
- Chủ định danh kiểm soát thông qua khoá cá nhân - private key.
-
3. Bài toán ví dụ
Hệ thống trường Faber nơi Alice tốt nghiệp thay đổi thông tin bảng điểm sang kỹ thuật số. Alice đăng nhập vào hệ thống nhà trường để lấy bảng điểm, nhưng cô ấy nhận ra hệ thống này yêu cầu một dạng định danh mới của cô, dạng định danh mới này có tính chất duy nhất trên thế giới, có thể di chuyển được, không phụ thuộc vào quá khứ, tương lai hay một cơ quan quản lý nào, không ai có thể huỷ bỏ được. Đó là dạng định danh Self-Sorvereign Identity.
Khi Alice có định danh mới, cô ấy click vào "nút Get Transcript". Để quản lý Self-Sorvereign Identity sẽ cần có ứng dụng trên máy tính hoặc mobile, nó có thể là một ứng dụng độc lập hoặc nhà cung cấp dịch vụ thứ ba mà sổ cái (Ledger) gọi là "Agency". Hệ thống của trường Faber gợi ý cho Alice cài đặt ứng dụng Indy nếu cô chưa có, ứng dụng này được cài đặt là một phần trong workflow của "nút Get Transcript".
Khi Alice nhấp chuột vào "nút Get Transcript", cô ấy sẽ cài được ứng dụng Indy, mở nó ra và được hỏi có chấp nhận yêu cầu kết nối đến Faber không? Bây giờ chúng ta sẽ xem đằng sau ngữ cảnh đó là gì...?
3.1 Chuẩn bị cơ sở hạ tầng
- Xác nhận Faber là Trust Anchor.
- Trust Anchor là một người hoặc một tổ chức mà sổ cái (ledger) đã được biết, và Trust Anchor có thể bootstrap người hoặc tổ chức khác.
- Sổ cái mục đích là để lưu trữ "bản ghi định danh" (Identity Record). "Bản ghi định danh" là dữ liệu công khai, nó có thể bao gồm: khoá công khai, service endpoint, lược đồ và sự định nghĩa của thông tin. Mỗi "bản ghi định danh" này được liên kết với chính xác một DID (decentralize identities) có tính duy nhất trên thế giới và có thể đọc được (qua sổ cái) mà không cần bất kỳ cơ quan giải quyết tập trung nào. Một Identity có thể sở hữu nhiều DID.
- Có 2 loại DID, một là DID xác minh (Verinym) được liên kết với "Legal Identity" của "Identity Owner", nó thường dùng để xuất bản các lược đồ cho các loại tài liệu. Thứ hai, DID bút danh (Pseudonym) dùng để duy trì kết nối giữa 2 Identity. 2 Identity liên lạc với nhau sẽ có 2 Pseudonym được gọi là mã định danh theo cặp duy nhất (Pairwise-Unique Identifier)
- Việc tạo ra một "bản ghi định danh" (Identity Record) cũng là việc tạo ra một DID mà sổ cái có thể đọc được, quá trình này gọi là giao dịch NYM (NYM transaction)
- Bước đầu tiên để thực hiện các giao dịch trên sổ cái liên quan đến việc nhận vai trò Trust Anchor trên sổ cái. Như vậy, trường Faber cần lấy vai trò Trust Anchor trên sổ cái của họ để có thể tạo ra DID Verinym và Pairwise-Unique Identifiers để cung cấp dịch vụ cho Alice.
- Steward là vai trò quản lý đầu tiên trong 1 hệ thống Self-Sovereign Identity, Steward có vai trò Trust Anchor
3.2 Kết nối đến hệ thống, ví dụ Hyperledger Indy
- Lần đầu tiên, sau khi hệ thống được khởi động, chúng ta cần kết nối đến hệ thống. Chúng ta kết nối đến hệ thống với tư cách là Steward's Agent.
- Sau khi hệ thống được khởi động nó có một NODE transaction được gọi là "genesis transaction", chúng ta có thể lấy được danh sách các node của hệ thống qua NODE transaction.
- Cấu hình về nhóm các node được đinh nghĩa là một cặp: "name": json.({"key1": "value1", ...}) và trường quan trọng nhất trong {"keyN": "valueN"} là đường dẫn tới file lưu trữ "genesis transaction"
await pool.set_protocol_version(2)
pool_ = {'name': 'pool1'} pool_['genesis_txn_path'] = get_pool_genesis_txn_path(pool_['name']) pool_['config'] = json.dumps({"genesis_txn": str(pool_['genesis_txn_path'])}) await pool.create_pool_ledger_config(pool_['name'], pool_['config']) pool_['handle'] = await pool.open_pool_ledger(pool_['name'], None)
- Steward's Agent sẽ có quyền sở hữu DID cái mà có NYM transaction tương ứng với vai trò Steward trên sổ cái. Khi cấu hình hệ thống, chúng ta phải định nghĩa một số thông tin liên quan đến NYM transaction, một trong số đó là các giá trị "seed". Các giá trị "seed" này là 1 số ngẫu nhiên, cho phép khôi phục lại DID ở Steward's Agent.
# Steward Agent steward = { 'name': "Sovrin Steward", 'wallet_config': json.dumps({'id': 'sovrin_steward_wallet'}), 'wallet_credentials': json.dumps({'key': 'steward_wallet_key'}), 'pool': pool_['handle'], 'seed': '000000000000000000000000Steward1' } await wallet.create_wallet(steward['wallet_config'], steward['wallet_credentials']) steward['wallet'] = await wallet.open_wallet(steward['wallet_config'], steward['wallet_credentials']) steward['did_info'] = json.dumps({'seed': steward['seed']}) steward['did'], steward['key'] = await did.create_and_store_my_did(steward['wallet'], steward['did_info'])
3.3 Faber thiết lập kết nối đến Steward
- Mỗi kết nối có một Pairwise-Unique Identity (các DID mù). Mỗi bên sở hữu một Pseudonym DID, cả hai bên đều biết Pseudonym của nhau và không chia sẻ được cho bên khác.
- Steward tạo DID mới trong ví (wallet) để sử dụng trong tương tác bảo mật với duy nhất Faber
# Steward Agent (steward['did_for_faber'], steward['key_for_faber']) = await did.create_and_store_my_did(steward['wallet'], "{}")
- Steward gửi giao dịch NYM tương ứng đến sổ cái (khả năng sổ cái này của Steward???)
# Steward Agent nym_request = await ledger.build_nym_request(steward['did'], steward['did_for_faber'], steward['key_for_faber'], None, role) await ledger.sign_and_submit_request(steward['pool'], steward['wallet'], steward['did'], nym_request)
- Steward tạo yêu cầu kết nối đến Faber
connection_request = { 'did': steward['did_for_faber'], 'nonce': 123456789 }
- Steward gửi yêu cầu kết nối đến Faber (có thể là qua mail, phone, hoăc ...??? không thấy mô tả)
- Faber nhận yêu cầu kết nối và sau đó tạo sổ cái, nếu nó chưa tồn tại trên Faber Agent
# Faber Agent await wallet.create_wallet(faber['wallet_config'], faber['wallet_credentials']) faber['wallet'] = await wallet.open_wallet(faber['wallet_config'], faber['wallet_credentials'])
- Faber tạo DID mới trong ví để sử dụng trong tương tác bảo mật với Steward
# Faber Agent (faber['did_for_steward'], faber['key_for_steward']) = await did.create_and_store_my_did(faber['wallet'], "{}")
- Faber tạo yêu cầu kết nối với Steward
# Faber Agent connection_response = json.dumps({ 'did': faber['did_for_steward'], 'verkey': faber['key_for_steward'], 'nonce': connection_request['nonce'] })
- Faber hỏi sổ cái về khoá xác minh (verkey) của DID của Steward
# Faber Agent faber['steward_key_for_faber'] = await did.key_for_did(faber['pool'], faber['wallet'], connection_request['did'])
- Faber mã hoá ẩn danh phản hồi kết nối bằng khoá xác minh của Steward
# Faber Agent anoncrypted_connection_response = await crypto.anon_crypt(faber['steward_key_for_faber'], connection_response.encode('utf-8'))
- Faber gửi phản hồi kết nối được mã hoá ẩn danh đến Steward (không thấy mô tả)
- Steward giải mã ẩn danh phản hồi kết nối này
# Steward Agent decrypted_connection_response = \ (await crypto.anon_decrypt(steward['wallet'], steward['key_for_faber'], anoncrypted_connection_response)).decode("utf-8")
- Steward chứng thực Faber bằng cách so sánh Nonce
# Steward Agent assert connection_request['nonce'] == decrypted_connection_response['nonce']
- Steward gửi giao dịch NYM của DID của Faber tới sổ cái (quá trình tạo DID trên sổ cái gọi là giao dịch NYM). Chú ý, mặc dù Steward là người gửi giao dịch này, chủ sở hữu DID sẽ là Faber vì nó sử dụng khoá xác minh mà Faber cung cấp
# Steward Agent nym_request = await ledger.build_nym_request(steward['did'], decrypted_connection_response['did'], decrypted_connection_response['verkey'], None, role) await ledger.sign_and_submit_request(steward['pool'], steward['wallet'], steward['did'], nym_request)