Identity
atproto ID システムには、いくつかの要件があります。
- ID プロビジョニング。 ユーザーは、サービス間で安定したグローバル ID を作成できる必要があります。これらの ID は、コンテンツへのリンクが安定していることを保証するために、ほとんど変更されない必要があります。
- 公開キーの配布。 分散システムは、データの信頼性を証明し、エンドツーエンドのプライバシーを提供するために暗号化に依存しています。ID システムは、強力なセキュリティで公開キーを公開する必要があります。
- キーのローテーション。 ユーザーは、ID を中断することなくキー マテリアルをローテーションできる必要があります。
- サービスの検出。 ユーザーと対話するには、アプリケーションは、特定のユーザーが使用しているサービスを検出できる必要があります。
- 使いやすさ。 ユーザーの名前は、人間が読みやすく、覚えやすいものにする必要があります。
- 移植性。 ID はサービス間で移植可能である必要があります。プロバイダーを変更しても、ユーザーが ID、ソーシャル グラフ、またはコンテンツを失うことはありません。
このシステムを採用すると、エンドツーエンドの暗号化、署名されたユーザー データ、サービス サインイン、および一般的な相互運用のためのツールがアプリケーションに提供されるはずです。
識別子
私たちは、ハンドル と DID という 2 つの相互に関連する識別子形式を使用します。ハンドルは DNS 名ですが、DID は安全で安定した ID として機能する 新しい W3C 標準 です。
以下はすべて有効なユーザー識別子です:
alice.host.com
at://alice.host.com
at://did:plc:bv6ggog3tya2z3vxsub7hnal
これらの関係は次のように視覚化できます:
┌──────────────────┐ ┌───────────────┐
│ DNS name ├──resolves to──→ │ DID │
│ (alice.host.com) │ │ (did:plc:...) │
└──────────────────┘ └─────┬─────────┘
↑ │
│ resolves to
│ │
│ ↓
│ ┌───────────────┐
└───────────references───────┤ DID Document │
│ {"id":"..."} │
└───────────────┘
DNS ハンドルはユーザー向けの識別子です。UI に表示され、ユーザーを見つける方法として宣伝される必要があります。アプリケーションはハンドルを DID に解決し、DID を安定した正規の識別子として使用します。その後、DID は、公開キーとユーザー サービスを含む DID ドキュメントに安全に解決できます。
- Handles
- ハンドルは DNS 名です。これらは
com.atproto.identity.resolveHandle
XRPC メソッドを使用して解決され、DID ドキュメント内の一致するエントリによって確認される必要があります。詳細は ハンドル仕様 をご覧ください。 - DID
- DID は、安定した安全な ID を提供するための新しい W3C 標準 です。これらは、ユーザーの安定した正規 ID として使用されます。AT プロトコルでの使用方法の詳細については、DID 仕様 をご覧ください。
- DID ドキュメント
DID ドキュメントは、DID レジストリによってホストされる標準化されたオブジェクトです。これらには次の情報が含まれます:
- DID に関連付けられたハンドル。
- 署名キー。
- ユーザーの PDS の URL。
DID メソッド
DID 標準 は、DID を DID ドキュメント に公開および解決するカスタム「メソッド」をサポートしています。さまざまな既存のメソッドが 公開 されているため、この提案に含めるための基準を確立する必要があります:
- 強力な一貫性。 特定の DID に対して、解決クエリによって生成される有効なドキュメントは常に 1 つだけである必要があります。 (一部のネットワークでは、これは確率的なトランザクションの最終性に左右される可能性があります。)
- 高可用性。解決クエリは確実に成功する必要があります。
- オンライン API。クライアントは、標準 API を介して新しい DID ドキュメントを公開できる必要があります。
- 安全。ネットワークは、オペレーター、MITM、およびその他のユーザーからの攻撃から保護する必要があります。
- 低コスト。DID ドキュメントの作成と更新は、サービスとユーザーにとって手頃な価格である必要があります。
- キー ローテーション。ユーザーは、ID を失うことなくキー ペアをローテーションできる必要があります。
- 分散型ガバナンス。ネットワークは単一の利害関係者によって管理されるべきではなく、オープン ネットワークまたはプロバイダーのコンソーシアムである必要があります。
プロジェクト開始時点で、DID 方式のいずれも当社の基準を完全に満たしていませんでした。 そのため、私たちはdid-webと、私たちが作成したDID PLCという新規の方法をサポートすることを選択しました。
ハンドル解決
atproto のハンドルは、DID に解決されるドメイン名です。DID は、ユーザーの署名公開鍵とホスティング サービスを含む DID ドキュメントに解決されます。
ハンドル解決では、com.atproto.identity.resolveHandle
XRPC メソッドを使用します。メソッド呼び出しは、ハンドルによって識別されるサーバーに送信され、ハンドルはパラメーターとして渡される必要があります。
疑似 TypeScript でのアルゴリズムは次のとおりです:
async function resolveHandle(handle: string) {
const origin = `https://${handle}`
const res = await xrpc(origin, 'com.atproto.identity.resolveHandle', {handle})
assert(typeof res?.did === 'string' && res.did.startsWith('did:'))
return res.did
}
例: ホスティング サービス
ホスティング サービスが PLC を使用していて、ユーザーのハンドルをサブドメインとして提供しているシナリオを考えてみましょう:
- ハンドル:
alice.pds.com
- DID:
did:plc:12345
- ホスティング サービス:
https://pds.com
まず、わかっているのはalice.pds.com
なので、alice.pds.com
で com.atproto.identity.resolveHandle()
を呼び出します。これにより、DID がわかります。
await xrpc.service('https://alice.pds.com').com.atproto.identity.resolveHandle() // => {did: 'did:plc:12345'}
次に、返された DID で PLC 解決メソッドを呼び出し、ホスティング サービスのエンドポイントとユーザーのキー マテリアルを確認します。
await didPlc.resolve('did:plc:12345') /* => {
id: 'did:plc:12345',
alsoKnownAs: `https://alice.pds.com`,
verifyMethod: [...],
service: [{serviceEndpoint: 'https://pds.com', ...}]
}*/
これで、https://pds.com
と通信して Alice のデータにアクセスできるようになりました。
例: 別のドメイン名を持つホスティング サービス
ユーザーが独自のドメイン名を指定していることを除いて、前と同じシナリオがあるとします:
- ハンドル:
alice.com
(これは前とは異なります) - DID:
did:plc:12345
- ホスティング サービス:
https://pds.com
alice.com
で com.atproto.identity.resolveHandle()
を呼び出して、DID を取得します。
await xrpc.service('https://alice.com').com.atproto.identity.resolveHandle() // => {did: 'did:plc:12345'}
次に、前と同じように DID を解決します:
await didPlc.resolve('did:plc:12345') /* => {
id: 'did:plc:12345',
alsoKnownAs: `https://alice.com`,
verifyMethod: [...],
service: [{serviceEndpoint: 'https://pds.com', ...}]
}*/
これで、https://pds.com
と通信して Alice のデータにアクセスできます。https://alice.com
エンドポイントは、com.atproto.identity.resolveHandle()
呼び出しを処理するためだけに機能します。実際のユーザー データは pds.com
にあります。
例: セルフ ホスト
セルフ ホスティングのシナリオを考えてみましょう。did:plc
を使用している場合は、次のようになります。
- ハンドル:
alice.com
- DID:
did:plc:12345
- ホスティング サービス:
https://alice.com
ただし、セルフ ホスティング側がドメイン名の所有権を保持できると確信している場合、did:plc
ではなく did:web
を使用できます。
- ハンドル:
alice.com
- DID:
did:web:alice.com
- ホスティング サービス:
https://alice.com
DID を取得するには、alice.com
で com.atproto.identity.resolveHandle()
を呼び出します。
await xrpc.service('https://alice.com').com.atproto.identity.resolveHandle() // => {did: 'did:web:alice.com'}
次に、did:web
を使用して解決します:
await didWeb.resolve('did:web:alice.com') /* => {
id: 'did:web:alice.com',
alsoKnownAs: `https://alice.com`,
verifyMethod: [...],
service: [{serviceEndpoint: 'https://alice.com', ...}]
}*/