7
1

More than 3 years have passed since last update.

DID Method 探訪:The did:key Method

Last updated at Posted at 2020-12-21

本記事ではThe did:key Method v0.7の実装を見ていく。

The did:key Method

DID Methodとはなんぞや、という話は省略する。DID-COREのリンクを貼るので参照して欲しい。

The did:key Method (以下did:key) はエフェメラル用途向けに考案されたDID Methodで、DID Documentの名前解決にDLTや共有ストレージのようなバックエンドを必要としない。「key」という名前の通り、did:keyのDID文字列は単一の公開鍵と全く同じ情報量を持ち、DID DocumentはDID文字列(⇔公開鍵)から一意に導出される。DID文字列に情報が全て含まれるので、誰でも、たとえオフラインでも名前解決が可能なのが最大の特徴だ。

導出方法

ここからは実際の導出の過程を見ていこう。

公開鍵 ←→ DID文字列

DID文字列は公開鍵から次のように一意に導出される:

didString pubKeyType rawPubKeyBytes =
  "did:key:" ++ multibase base58btc (multicodec pubKeyType rawPubKeyBytes)

ここでmultibaseは文字列をbase変換してから基数(及びアルファベット)を表すプレフィックスを付与する関数で、base58-bitcoinの場合は"z"がプレフィックスになる。また、multicodecはバイナリデータにコーデックを表すプレフィックスを付与する関数で、例えばEd25519公開鍵の場合は0xedがプレフィックスになる(unsigned varintの形式で付与するため、バイナリ上は0xed01)。

did:keyのspecificationに書いてある例で実際に導出してみよう。pubKeyTypeはEd25519VerificationKey2018、pubKeyはbase58-bitcoinで B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u とする。Hexで書けば0x94966b7c08e405775f8de6cc1c4508f6eb227403e1025b2c8ad2d7477398c5b2だ。

Ed25519VerificationKey2018のmulticodecプレフィックスは0xed、unsigned varintだと0xed01になる。これをバイナリの先頭に付与するので、0xed0194966b7c08e405775f8de6cc1c4508f6eb227403e1025b2c8ad2d7477398c5b2 がmulticodec後のバイナリとなる。

これのbase58-bitcoinを取ると6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH となる。multibaseのプレフィックス"z"と"did:key"を先頭につければ、did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH。これで完成だ。specificationの例と一致することを確認して欲しい。

DID文字列に公開鍵の情報が完全に入っているので、逆変換するだけでDIDから公開鍵を得ることも可能だ。つまりdid:keyにおいては、DID文字列と元となった公開鍵は等価である

DID文字列 → DID Document

ところで、

  1. DID文字列と公開鍵は等価である
  2. did:keyにおいて、DID Documentの導出にDID文字列以外の情報は使えない

のだから、did:keyではDID Documentも公開鍵と等価であるということになる。あるいはDID Documentに公開鍵一つ分の情報しか載せられないと言い換えても良い。

となるとわざわざDID Documentを導出する必要もあまりないように思うが、まあフォーマット変換のようなものだと思って見ていこう。他のDID Methodと互換なのは大事だ。

実際の例を見る前に、まずどんな形式になるかを予想してみよう。先程のDIDでいえば、だいたい次のような感じになるはずだ:

予想されるDIDDocument
{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
  "verificationMethod": [
    {
      "id": "#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
      "publicKeyBase58": "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u"
    }
  ],
  "authentication": ["did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"],
  "assertionMethod": ["did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"],
  "capabilityDelegation": ["did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"],
  "capabilityInvocation": ["did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"]
  "keyAgreementKey": ["did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"]
}

verificationMethodに元の公開鍵を入れておき、すべてのverification relationshipでそれを参照する。verification relationshipを限定したりはできないので、did-coreで定義されているものを全部入れるしかないだろう。まさしく公開鍵一つ分の情報しかないDID Documentと言える。

さて、実際のspecificationではどうなっているのか?

The did:key Method v0.7 EXAMPLE 2より引用

{
  "@context": "https://w3id.org/did/v1",
  "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
  "publicKey": [{
    "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
    "type": "Ed25519VerificationKey2018",
    "controller": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
    "publicKeyBase58": "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u"
  }],
  "authentication": [ "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" ],
  "assertionMethod": [ "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" ],
  "capabilityDelegation": [ "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" ],
  "capabilityInvocation": [ "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" ],
  "keyAgreement": [{
    "id": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#zBzoR5sqFgi6q3iFia8JPNfENCpi7RNSTKF7XNXX96SBY4",
    "type": "X25519KeyAgreementKey2019",
    "controller": "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
    "publicKeyBase58": "JhNWeSVLMYccCk7iopQW4guaSJTojqpMEELgSLhKwRr"
  }]
}

あれ、なんかちょっと違う……

まず、publicKeyプロパティはverificationMethodプロパティの古い表現だ。将来的にverificationMethodに置き換えられるとのことなので一旦置いておこう。

問題はkeyAgreementになぜか生えているもう一つの公開鍵である。何だこれは?

調べたところ、Ed25519VerificationKey2018はそのまま鍵交換には使えないため、X25519KeyAgreementKey2019に変換する必要があるらしい。この変換は比較的安全だが、数学的な証明を欠いていると考える実装者もいるとのことだ(参考:https://w3c-ccg.github.io/did-method-key/#key-derivation-lacks-proof) 。

ここがdid:keyで一番もやもやするところで、どうやら元となる公開鍵の種類によって利用可能なverification relationshipが変わるらしい。例えばX25519KeyAgreementKey2019でもDIDを作ることができるが、その場合のDID Documentはこんな感じになる:

X25519KeyAgreementKey2019で作ったDIDのDocument
{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F",
  "keyAgreement": [
    {
      "id": "#z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F",
      "type": "X25519KeyAgreementKey2019",
      "controller": "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F",
      "publicKeyBase58": "4Dy8E9UaZscuPUf2GLxV44RCNL7oxmEXXkgWXaug1WKV"
    }
  ]
}

見ての通り、鍵交換にしか使えないDIDだ。これでいいのなら、正直Ed25519の場合も単にkeyAgreementを省けば良いように思うが……。

この辺りのさじ加減は導出する人(あるいはDID→DID Documentの変換ライブラリ)の鍵への理解度に拠るところが大きそうに思う。今の所「その鍵はどのverification relationshipに使えるか」というリストは出ていないように思うので、ここが現状最も大きな課題になりそうだ。

まとめ

did:keyでは、DID、公開鍵、DID Documentはすべて同値となる。公開鍵と同値なので、DIDの寿命は公開鍵の寿命と同じだし、他のDID MethodのようなDocument更新・非有効化といったアクションは非対応だ。また、DID DocumentをDID単体から導出できるので、DLTのようなバックエンドは必要ない。オフラインでも使える軽量かつ使い捨てのDIDと考えれば良さそうだ。

実装を追ってみた感想としては、DID Documentの生成が実はそんなに自明じゃないな……と感じた。verification relationshipは元となる公開鍵のタイプに依存するので、どの鍵タイプがどのverification relationshipをサポートするのかがわかる一覧がないと実際の実装は難しいように思う。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1