mcpField
D
dmk-business-logic

dmk-business-logic

github.com/ledgerhq開発7100 回インストール2 週間前に更新
リポジトリ

dmk-business-logic について

Ledger Device Management Kit(DMK)を実装する開発者向けのリファレンススキルです。API 設計の概念、デバイス操作、通信上の制約、署名、安全性に関わる挙動を解説します。

主な機能

  1. 01クリア署名とブラインド署名の概念
  2. 02セキュアチャネルの要件
  3. 03デバイスアクションとコマンド
  4. 04セッションのライフサイクルと通信方式
  5. 05導出パスの指針
  6. 06デバイスの真正性確認

活用シーン

  1. 01デバイスアクションとコマンドの選択
  2. 02トランザクション署名フローの設計
  3. 03Ledger 接続セッションの管理
  4. 04チェーンの導出パス設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ledgerhq/agent-skills --skill dmk-business-logic

インストール後、Claude Code で/dmk-business-logicを入力して読み込まれたか確認します。

詳細

DMK のビジネスロジックと概念

このスキルでは、DMK API の設計上の決定に至った背景(ドメインモデル、セキュリティ上の制約、トレードオフ)を説明し、開発者が呼び出し方だけでなく、その理由も理解できるようにします。また、実装中に用語や概念の確認が必要になった際、ledger-dmk-implementation/SKILL.md によってコネクターとして読み込まれます。


Clear Signing と Blind Signing

意味

Blind signing では、ユーザーに Ledger の画面上で生の 16 進数バイト列が表示されます。ユーザーが確認できない、長くて判読不能な文字列です。内容を実質的に確認できないまま、承認を求められます。

Clear Signing では、デバイスの画面に、人が読めるトランザクションの詳細(送信先アドレス、金額、トークン名、コントラクト名、手数料)が表示されます。ボタンを押す前に、実際に承認する内容を確認できます。

重要な理由

デバイスの画面は、唯一の信頼できる表示画面です。侵害されたホスト(マルウェア、フィッシングサイト)は、ブラウザーやデスクトップの UI 上にユーザーが見たいものを何でも表示できます。デバイスの画面は偽装できません。Clear Signing によってデバイスの画面が意味のあるものになります。Blind Signing では画面が役に立ちません。

DMK での仕組み

DMK は Clear Signing がなくても完全に機能します。Clear Signing は必須要件ではなく、機能を強化するものです。Ethereum で有効にするには、次のようにします。

  • @ledgerhq/context-module は必ずインストールする必要があります。ETH signer kit の必須 peer dependency であり、デバイスが人に読めるフィールドを表示するために必要なメタデータ(ABI、トークン情報、NFT の詳細)の取得を担います。
  • originToken は、SignerEthBuilder に渡す任意のパートナートークンです。指定しなくても signer は機能しますが、デバイスには生の 16 進数が表示されます。実行時エラーは発生せず、エクスペリエンスは気づかないうちに Blind Signing に劣化します。トークンを取得するには、Ledger のパートナープログラムに登録してください:https://developers.ledger.com/docs/clear-signing/for-wallets。
// Clear Signing enabled (requires partner token):
new SignerEthBuilder({ dmk, sessionId, originToken: "your-partner-token" }).build();

// Blind signing — works but users see raw hex on device:
new SignerEthBuilder({ dmk, sessionId }).build();

Bitcoin と Solana では、Clear Signing はアプリレベルで処理されます。originToken は不要ですが、デバイス上の Ledger アプリがそのトランザクションの種類に対応している必要があります。

開発者向けチェックリスト
  • originToken は任意です。まずはこれを使わずに統合してリリースし、本番環境で Clear Signing を有効にする準備ができたら Ledger のパートナープログラムに登録してください
  • ETH signer kit を使用する場合は、開発中も必ず @ledgerhq/context-module をインストールしてください
  • getAddress() のフローでは、必ず checkOnDevice: true を使用してください。これは、受取フローにおける Clear Signing に相当するアドレス検証です

セキュアチャネル

概要

セキュアチャネルは、Ledger デバイスと Ledger の HSM(ハードウェアセキュリティモジュール)バックエンド間の、暗号化され認証された接続です。バックエンドはこの接続を通じて、ローカルでは実行できない特権操作をデバイス上で実行できます。

必要な操作
操作セキュアチャネルが必要か
GenuineCheckDeviceActionはい
ListInstalledAppsDeviceActionはい
InstallAppDeviceActionはい
UninstallAppDeviceActionはい
すべての signer 操作(署名、アドレス取得)いいえ
OpenAppDeviceActionいいえ
仕組み
  1. DMK は Ledger の HSM(wss://manager.live.ledger.com)への WebSocket 接続を開きます
  2. デバイスと HSM が相互認証のハンドシェイクを行います
  3. デバイスの画面に AllowSecureConnection が表示され、ユーザーに接続の許可を求めます。ユーザーは実際に操作して接続を承認する必要があります
  4. 承認されると、そのデバイスが再起動するまでセッションが信頼されます
実際の影響
  • インターネット接続が必要です。 オフラインではセキュアチャネル操作に失敗し、ローカルでの代替手段はありません。

デバイスアクションとコマンド

2 段階の API

DMK は、デバイスとのやり取りに 2 つのレベルを提供します。

コマンド(dmk.sendCommand())は、低レベルの単一 APDU の往復処理です。デバイスに 1 つの命令を送信し、結果を同期的に返します。ユーザーとのやり取りは処理されないため、それ以外のすべては呼び出し側の責任です。

デバイスアクション(dmk.executeDeviceAction()、または署名者キットのメソッド)は、高レベルでオーケストレーションされたフローです。ロック解除の検出、アプリの起動、ユーザー確認のプロンプト、再試行、終了状態の通知まで、一連の処理全体を単一のオブザーバブルを通じて扱います。

使い分け
ユースケース使用するもの
トランザクションへの署名、アドレスの取得署名者キットのデバイスアクション(署名者ビルダー経由)
正規品チェック、アプリのインストール/アンインストール適切な DeviceAction クラスを指定した dmk.executeDeviceAction()
ユーザー確認 UI を伴うアプリの起動dmk.executeDeviceAction() 経由の OpenAppDeviceAction
ファームウェアバージョンの確認、現在のアプリ名の取得sendCommand() — シンプルで、ユーザーとのやり取りは不要です
カスタム/未対応のチェーン、raw APDUApduBuilder を指定した sendCommand() — 署名者キットがない場合に限ります
デバイスアクションがある理由

デバイスアクションがなければ、開発者はそれぞれ以下を再実装する必要があります。

  • デバイスのロック解除を検出して待機する
  • アクティブなアプリを検出して切り替える
  • ConfirmOpenApp プロンプトを処理する
  • ステータスワードのエラーをユーザー向けメッセージに変換する
  • タイムアウトとキャンセルを管理する

デバイスアクションは、これらすべてをカプセル化します。返されるオブザーバブルは、UI プロンプトに直接対応する状態を通知します。UserInteractionRequired.SignTransaction は「ユーザーにプロンプトを表示する」、DeviceActionStatus.Completed は「完了したので、出力を取り出す」を意味します。


セッションと SessionId

セッションとは

セッションは、特定の Ledger デバイスとのアクティブな USB/BLE 接続を表します。dmk.connect() によって作成され、dmk.disconnect() によって破棄されます。sessionId は、DMK インスタンス内でセッションを識別する不透明な文字列です。

セッションではないもの
  • チェーンごとのものではありません。 同じ sessionId を、再接続せずに ETH、BTC、SOL、その他の署名者で使用できます。
  • 認証ではありません。 署名操作のたびに、デバイスは引き続きユーザーに確認を求めます。セッションは単なるトランスポートハンドルです。
  • ページの読み込みをまたいで永続するものではありません。 ブラウザーを更新すると、セッションは破棄されます。
セッションの有効期間

セッションは、次のいずれかが起きるまで有効です。

  • dmk.disconnect({ sessionId }) が呼び出される
  • USB ケーブルが抜かれる(セッション状態が Disconnected になる)
  • ブラウザーのタブが閉じられる

既存の sessionId を使って再接続しようとしないでください。Disconnected になったら、startDiscovering() から新しいフローを開始してください。

セッションリフレッシャー

DMK は、セッションの状態(現在のアプリ、デバイスの状態)を最新に保つため、定期的にデバイスをポーリングします。これがセッションリフレッシャーです。複数のタブで 2 つのインスタンスが同じ物理デバイスを共有する場合、ポーリングの競合を避けるために無効にしてください。

dmk.connect({ device, sessionRefresherOptions: { isRefresherDisabled: true } });

トランスポート

抽象化されるもの

トランスポート層は、ホストと Ledger デバイス間の物理通信プロトコルを処理します。DMK の API はトランスポートにかかわらず同一で、初期化方法だけが異なります。

トランスポートプロトコル環境
WebHIDUSB HID、64 バイトフレームブラウザー(Chromium のみ)
WebBLEBluetooth GATTブラウザー
Node-HIDネイティブアドオン経由の USB HIDNode.js、Electron
React Native HIDUSB HIDReact Native
React Native BLEBluetoothReact Native
Speculosエミュレーターへの TCP ソケット開発/CI のみ
ブラウザーの制約

WebHID には、以下が必要です。

  • Chromium ベースのブラウザー(Chrome、Edge、Brave)— Firefox と Safari は WebHID をサポートしていません
  • HTTPS または localhost — 通常の HTTP では WebHID がブロックされます
  • ユーザーの操作 — startDiscovering() と connect() は、ボタンクリックなどの操作から呼び出す必要があります。ページ読み込み時に呼び出した場合、通知なく失敗します。
DMK インスタンスごとに 1 つのトランスポート

各 DeviceManagementKitBuilder は 1 つ以上のトランスポートを受け取ります。実際には、1 つを使用してください。DMK は登録された順にトランスポートを試します。


派生パス

派生パスとは

派生パスは、デバイスに保存されたルートシードから派生するキーを指定するインデックスの並びです。同じシードフレーズを指定した場合、同じパスからは常に同じキーが生成されます。一方、異なるパスからは、実行時エラーが発生することなく、まったく異なるキーが生成されます。

ユーザー入力ではなく、開発者が定数として定義する理由

デバイスの観点では、「誤ったパス」はありません。どのパスからも有効なキーが生成されます。ユーザーが 1 つでも異なるセグメントを含むパスを入力すると、別のアドレスが生成されます。そのアドレスに送金された資金は、正しいパスが分からない限りアクセスできません。これは、気づかれないまま取り返しのつかない事態につながるミスです。

パスは、ユーザーが使用するウォレットの標準に合わせて、アプリケーションコード内に定数としてハードコードする必要があります。

パス形式のルール
  • m/ 接頭辞は付けません。 DerivationPathUtils.splitPath は / 区切りのセグメントを解析します。先頭の m は有効なセグメントではありません。parseInt("m") は NaN を返し、「invalid number provided」というエラーが発生します。"m/44'/60'/0'/0/0" ではなく "44'/60'/0'/0/0" を使用してください。
  • ハード化されたセグメントには ' の接尾辞を使用します(例:44')。これはインデックスに 0x80000000 を加算する省略表記です。
  • アカウントとインデックスは別の概念です。account はウォレットを選択します(ほとんどのユーザーは 0 を使用します)。index は、そのウォレット内のアドレスを選択します。
チェーンごとの標準パス
チェーンLedger Live のパス備考
Ethereum44'/60'/0'/0/0BIP44、アカウント 0、インデックス 0
Bitcoin Native SegWit84'/0'/0'BIP84、ウォレットポリシーに渡します
Solana44'/501'/0'/0'コミュニティ標準
Cosmos44'/118'/0'/0/0BIP44

一覧にないチェーンについては、SLIP-0044 でコインタイプが定義されています(github.com/satoshilabs/slips/blob/master/slip-0044.md)。


BOLOS

BOLOS(Blockchain Open Ledger Operating System)は、現在は Ledger OS と呼ばれる、Ledger デバイスのオペレーティングシステムです。アプリが開かれておらず、デバイスがホーム画面(ダッシュボード)にある場合、state.currentApp.name は "BOLOS" を返します。

アプリが開かれていないことを検出する方法は次のとおりです。

const isOnDashboard =
  state.currentApp.name === "BOLOS" || state.currentApp.name === "Dashboard";

署名キットのデバイスアクションを使用する場合、アプリの切り替えは自動的に処理されるため、これを明示的に検出する必要はありません。操作前に UX フィードバックを表示する場合(「アプリが開かれていません。続行すると適切なアプリが開きます」など)に役立ちます。


正規品チェック

正規品チェックでは、実物の Ledger デバイスが Ledger 製の正規ハードウェアであり、偽造品ではないことを確認します。デバイスに、対応する証明書が Ledger のルート CA によって署名された秘密鍵の所有を証明させ、セキュアチャネルを通じて検証します。

output.isGenuine: boolean を返します。

使用する場面: 企業向けの鍵管理のセットアップや、デバイスの初回オンボーディングフローなど、処理を続行する前にデバイスの真正性を確認する必要がある、高セキュリティのフローで使用します。通常の署名操作では必要ありません。

証明されないこと: 製造後にデバイスが改ざんされていないことや、シードフレーズが正しくバックアップされていることは証明されません。


Ledger Wallet / Ledger Live

Ledger Live は Ledger Wallet の旧名称です。どちらも同じデスクトップおよびモバイルアプリケーションを指します。ドキュメント、スキルファイル、SDK の参照ではいずれかの名称が使われることがありますが、同じものとして扱ってください。

デバイスアクション(OpenAppDeviceAction、InstallAppDeviceAction、UninstallAppDeviceAction)で使用するアプリ名は、Ledger のアプリカタログに表示される名称(Ledger Wallet に表示される名称と同じ)と完全に一致させる必要があります。タイプミスや大文字・小文字の違いがあると、何が問題だったのか分からないまま、無言で失敗するか、分かりにくいエラーが発生します。

コメント