前回の記事でIONのDIDを登録したので↓
techmedia-think.hatenablog.com
今回は、登録したDIDの鍵を更新するUpdate操作をアンカリングしてみる。
Update操作
Update操作は、現在DIDに紐付けられているUpdate Keyを使ってDID Documentの更新(署名鍵やserviceの追加、削除など)を行う操作になる。更新の対象や内容は、DID State Patchesで定義する。
今回は、DIDに署名鍵として登録した公開鍵を新しい公開鍵に更新するreplaceアクションを行うことにする(Patchは複数設定することも可能)。
今回のUpdate操作に必要な手順は↓
- 新しい署名用の鍵ペアを生成する。
- 1の公開鍵のデータを元に、replaceを行うDID State Patcheを生成する。
- DIDに紐付ける新しいUpdate Keyを生成する(このUpdate Keyは、この更新後のDIDのステートを更新する際に使用されるUpdate Keyになる)。なので、更新用の鍵はワンタイムの鍵ということになる。
- 3の新しいUpdate Keyのコミットメントを生成する。
- 2と4のデータからUpdate Operation Delta Objectを生成する。
- 現在のUpdate Keyを使って、JWSデータを生成する。
- 6のJWSのデータを使って、(Create操作では不要だった)Provisional Proof Fileを生成して、IPFSにアンカリングする。
- 5のdeltaファイルからChunk Fileを生成して、IPFSにアンカリングする。
- 以下のデータからProvisional Index Fileを生成して、IPFSにアンカリングする。
- 9のProvisional Index FileのURIを指定して、Core Index Fileを生成し、IPFSにアンカリングする。
- 10のCore Index FileのURIからAnchor Stringを生成し、それをBitcoinにアンカリングする。
前回のCreate操作と違うのは、Update操作が可能なことを暗号学的に証明するためのJWSの生成と、それをCASにアンカリングするためのProvisional Proof Fileの作成。
実際に操作を実行
前回登録したDIDを更新しようとしたんだけど、いろいろ試行錯誤して試してたら、
{ code: "canonicalized_object_hash_mismatch", message: "Canonicalized update request update key object hash does not match expected hash 'EiDBQ56irlBskr7ZawFLcoH131ZvSLbfa2jK1MOny-feIQ'." }
というエラー以降、更新できなくなってしまったので、新しいDIDを作成して(did:ion:test:EiBRrmEha_Q30GieEwLB-XM8CZd_b49dQ7znhaBxfAHTsQ)↓
こちらを更新することにする。Update処理のサポートをsidetreerbに実装して、↓を実行
require 'sidetree' Sidetree::Params.network = Sidetree::Params::Network::TESTNET did = generate_did # ↑で新規作成したSidetree::DIDオブジェクト(作成方法は前回の記事参照) # DID新規作成時に設定したUpdate Key update_key = Sidetree::Key.new( private_key: 30_922_012_418_511_471_117_584_821_339_133_667_644_396_117_517_409_218_592_473_694_736_410_013_586_765 ) # 新しい署名鍵を生成 new_signing_key = Sidetree::Key.generate(id: "signing-key") # 置き換えるDID Documentを生成 document = Sidetree::Model::Document.new(public_keys: [new_signing_key]) # 次のUpdate Keyを生成 next_update_key = Sidetree::Key.generate # Update delta objectを生成 delta = Sidetree::Model::Delta.new( [document.to_replace_patch], next_update_key.to_commitment ) # JWSを生成して署名 claim = { updateKey: update_key.to_jwk.normalize, deltaHash: delta.to_hash } jws = Sidetree::Util::JWS.sign(claim, update_key) ipfs = Sidetree::CAS::IPFS.new # Provisional Proof Fileを作成 provisional_proof = Sidetree::Model::ProvisionalProofFile.new([jws]) provisional_proof_uri = ipfs.write(provisional_proof.to_compress) # Update operationを作成 update_op = Sidetree::OP::Update.new(did.suffix, delta, jws, update_key.to_reveal_value) # Chunk Fileを作成 chunk_file = Sidetree::Model::ChunkFile.create_from_ops(update_ops: [update_op]) chunk_file_uri = ipfs.write(chunk_file.to_compress) # Provisional Index Fileを作成 provisional_index_file = Sidetree::Model::ProvisionalIndexFile.new( proof_file_uri: provisional_proof_uri, chunks: [Sidetree::Model::Chunk.new(chunk_file_uri)], operations: [update_op] ) provisional_index_file_uri = ipfs.write(provisional_index_file.to_compress) # Core Index Fileを作成 core_index_file = Sidetree::Model::CoreIndexFile.new( provisional_index_file_uri: provisional_index_file_uri ) core_index_file_uri = ipfs.write(core_index_file.to_compress) anchor_str = Sidetree::Util::AnchoredDataSerializer.serialize(1, core_index_file_uri)
最終的なAnchor Stringは、
ion:1.QmVKryfVemjT3Nxnea4aJpJRXFJkLpFjNfti1tJngJwBWs
Bitcoinにアンカリングしたトランザクションが40ba3f1d10456be725ac176a333e42b0ef9fdf47cb9f325f8f5c4f69b2e931df。
ブロックが承認され、IONで取り込まれると、先程のDIDを解決すると、↓のようにdid:ion:test:EiBRrmEha_Q30GieEwLB-XM8CZd_b49dQ7znhaBxfAHTsQの署名鍵が新しく生成した鍵で更新されていることが分かる。