Windows実行ファイルでAPIキーをどう保持するか
対象
本稿は、Windows向けのデスクトップ実行ファイルでAPIキーをローカル保持する場合の実装方式を比較する。対象は次の5方式に限定する。
- 実行ファイルへのコード埋め込み
- 平文ファイル保存
- DPAPI
- Credential Manager
- Credential Locker(
PasswordVault)
ここで比較するのは、ローカル保存時の保護方式である。サーバ経由設計、OAuthフロー、トークン短寿命化、通信路保護は扱わない。
要点
- 配布型のWindows実行ファイルに共通APIキーを埋め込む方式は、秘密保持方式としては成立しにくい。RFC 8252は、複数ユーザーに配布されるネイティブアプリに静的に含まれる共有シークレットを、機密として扱うべきではないとしている。1
- 平文ファイル保存は実装が最も容易だが、秘密情報の保存方式としては避けるべきである。NIST SP 800-57 Part 2は、秘密鍵や秘密メタデータを暗号モジュール外に保存する場合、少なくとも機密性と完全性の保護を要件化している。MicrosoftもCredential Lockerのベストプラクティスで、資格情報を平文で保存しないよう明記している。23
- DPAPIは「任意のバイト列をOSに保護させる方式」であり、保存先はアプリ側が管理する。Windowsデスクトップアプリでは扱いやすく、APIキー1件や少数の秘密情報を保護する用途に向く。456
- Credential Managerは「OS管理の資格情報ストアに汎用資格情報として格納する方式」であり、Win32デスクトップアプリとの親和性が高い。APIキーが1件の文字列として表現できるなら、DPAPIより実装が簡潔になることが多い。789
- Credential LockerはWinRTの
PasswordVaultによる資格情報保管方式で、UWP/WinUI/パッケージ化デスクトップアプリ寄りのAPIである。Microsoftはパスワード向けの利用を前提に説明しており、一般的なWin32実行ファイルの第一候補とは言いにくい。310
評価軸
本稿では、次の観点で比較する。
- 配布物解析に対する強さ
- ローカルファイル持ち出しに対する強さ
- 同一Windowsユーザー権限で動く別プロセスに対する強さ
- 実装のしやすさ
- Windowsデスクトップアプリとの適合性
なお、同一ユーザー権限で動作する不正プロセスへの耐性は、DPAPI / Credential Manager / Credential Locker のいずれでも限定的とみなすべきである。
これは、Microsoft文書がそれぞれ CurrentUser、current token のログオンセッション、user-specific なロッカーという単位でアクセス境界を定義しているためである。これは文書上のアクセス境界からの評価であり、本稿の推論を含む。6810
1. コード埋め込み
コード埋め込みの方式
APIキーを、EXE/DLL本体、リソース、定数テーブル、設定の初期値などに直接埋め込む。
コード埋め込みの特性
- 配布物だけで完結するため、実装は最も簡単
- 初回設定やユーザー入力が不要
- ただし、秘密情報は配布物の一部になる
RFC 8252は、複数ユーザーに配布されるネイティブアプリに静的に含まれる共有シークレットは、機密として扱うべきではないと整理している。1
この考え方はOAuthクライアントシークレットの文脈だが、配布済みネイティブアプリに共通秘密を持たせる設計一般にもそのまま当てはまる。
コード埋め込みの評価
- 配布物解析に弱い
- ローテーション時に再配布が必要になりやすい
- 共通キーを入れると、1件の漏えいが全利用者に波及しやすい
コード埋め込みが向くケース
- 機密ではない識別子
- 公開前提の
client_id - サンプルコードや検証用の一時実装
機密なAPIキーの保持方式としては不適切である。
2. 平文ファイル保存
平文ファイル保存の方式
APIキーをjson、ini、SQLite、レジストリなどに平文のまま保存する。
平文ファイル保存の特性
- 実装が容易
- 外部編集やサポートが容易
- バックアップ、同期、誤送信、端末共有、スクリーンショットなどで露出しやすい
NIST SP 800-57 Part 2は、秘密情報を暗号モジュール外に保存する場合、完全性を保護し、秘密情報の機密性も保護すべきとする。高・中インパクトの情報では暗号学的保護を要求している。2
またMicrosoftはCredential Lockerのベストプラクティスとして、資格情報をアプリデータやローミング設定に平文保存しないよう明記している。3
平文ファイル保存の評価
- 配布物解析よりはましだが、ファイル入手だけで読める
- OSのファイルACLに依存しやすい
- 監査上も説明しにくい
平文ファイル保存が向くケース
- 開発環境限定の一時用途
- 非機密情報
本番用の機密APIキーには不適切である。
3. DPAPI
DPAPIの方式
WindowsのData Protection APIで、アプリが平文をOSに渡し、暗号化済みのBLOBを受け取る。Win32ではCryptProtectData / CryptUnprotectData、.NETではProtectedDataから利用できる。45
DPAPIに関するMicrosoft文書上のポイント
CryptProtectDataは平文DATA_BLOBを暗号化する。4- 通常は、暗号化したユーザーと同じログオン資格情報を持つユーザーだけが復号できる。4
CRYPTPROTECT_LOCAL_MACHINEを使うと、同じコンピューター上の任意のユーザーが復号できる。4- DPAPIは改ざん検知のためにMACを付与する。4
- .NETの
ProtectedDataはDPAPIのラッパーであり、CurrentUserとLocalMachineのスコープを選べる。LocalMachineは「そのコンピューター上の任意のプロセスが復号できる」ため、Microsoftは通常CurrentUserの利用を推奨している。56
DPAPIの実装上の意味
DPAPIは保存場所そのものではなく保護手段である。
つまり、実装は通常次の形になる。
- APIキーを
CryptProtectDataまたはProtectedData.Protectで暗号化する - 返ってきた暗号化
BLOBをファイル、レジストリ、ローカルDBなどに保存する - 必要時に復号する
DPAPIの利点
- Win32/.NETデスクトップアプリで使いやすい
- 任意のバイト列を保護できる
- アプリが独自の暗号鍵を保持しなくてよい
CurrentUserを使えば、別ユーザーによる単純なファイル持ち出しに強い
DPAPIの制約
- 暗号化済みデータの保管場所、命名、削除、バックアップはアプリ側の責務
LocalMachineはクライアント端末では広すぎることが多い- Microsoftは、ユーザープロファイルが読み込まれていない状態や偽装実行時には復号で問題が出る可能性があるとしている。5
- 同一ユーザー権限の別プロセスは、同じユーザーコンテキストで復号できる前提で考えるべきである。これは文書上のスコープ定義からの推論である。6
DPAPIが向くケース
- 典型的なWin32/.NETデスクトップアプリ
- APIキー以外も含めて少量の秘密設定をまとめて保護したい場合
- 保存先はアプリ側で管理したいが、鍵管理はOSに任せたい場合
4. Credential Manager
Credential Managerの方式
Win32のCredWrite / CredReadで、Windowsのユーザー資格情報セットに資格情報を書き込む。APIキー用途では通常CRED_TYPE_GENERICを使う。789
Credential Managerに関するMicrosoft文書上のポイント
CredWriteは、現在のトークンのログオンセッションに紐づくユーザーの資格情報セットに新規作成または更新を行う。7CredReadは、その資格情報セットから資格情報を読み出す。8CREDENTIAL構造体では、CRED_TYPE_GENERICのCredentialBlobはアプリケーション定義である。9CredentialBlobSizeの上限は5*512バイトであり、通常のAPIキー文字列なら十分収まる。9- 永続化スコープとして
CRED_PERSIST_SESSION、CRED_PERSIST_LOCAL_MACHINE、CRED_PERSIST_ENTERPRISEを選べる。9
Credential Managerの実装上の意味
Credential Managerは、DPAPIのように「暗号化してどこかに保存する」のではなく、OSが管理する資格情報ストアに1レコードとして保存する方式である。
APIキー用途では、例えば以下のように扱う。
TargetName: サービス名や環境名Type:CRED_TYPE_GENERICCredentialBlob: APIキー本体Persist: セッション限定、ローカル永続、エンタープライズ永続
Credential Managerの利点
- Win32デスクトップアプリから直接使える
- ファイル形式や暗号化済みBLOBの管理が不要
- APIキー1件を「名前付き資格情報」として扱う用途に向く
- 永続化スコープをAPIで明示できる
Credential Managerの制約
- データモデルは資格情報レコード前提であり、複数設定をまとめて保存する用途には向きにくい
- 読み出し時には平文がプロセスに返る
CredReadのアクセス単位は現在のトークンのログオンセッションであるため、同一ユーザー権限プロセスへの耐性は限定的と考えるべきである。これはMicrosoft文書のアクセス境界からの推論である。8CRED_PERSIST_ENTERPRISEは構成によって他コンピューターのログオンセッションにも見えるため、ローミング要件を確認すべきである。9
Credential Managerが向くケース
- Win32/.NETクライアントで、APIキーを1件または少数の資格情報として保存したい場合
- アプリ独自の暗号化ファイルを持ちたくない場合
- Windowsネイティブの資格情報ストアに寄せたい場合
5. Credential Locker(PasswordVault)
Credential Lockerの方式
WinRTのWindows.Security.Credentials.PasswordVaultを使って、Credential Lockerに資格情報を保存する。310
Credential Lockerに関するMicrosoft文書上のポイント
- MicrosoftはCredential Lockerを、資格情報を安全に保存・取得し、Microsoftアカウントでデバイス間ローミングさせる仕組みとして説明している。3
- このAPIは元々UWP向けだが、WinUIアプリやパッケージ化デスクトップアプリでも使えるとしている。3
- Microsoftはベストプラクティスとして、Credential Lockerはパスワード用途にのみ使い、大きなデータ
BLOBには使わないよう案内している。3 - Microsoftは同じ記事で、平文で保存しないことを明記している。3
PasswordVault文書では、ロッカーはユーザー単位であり、AppContainer内アプリは自分のロッカーだけにアクセスできる一方、通常のデスクトップアプリはそのユーザーのすべてのロッカーにアクセスできるとしている。10
Credential Lockerの実装上の意味
Credential Lockerは、Windowsの現代アプリモデル寄りの資格情報ストアである。
保存単位もresource、userName、passwordという形で、パスワード型の資格情報に寄っている。
そのため、APIキーが単なる短い文字列であれば保存自体は可能だが、次の点を意識する必要がある。
- Win32/WinForms/WPFの一般的なEXEでは、DPAPIやCredential Managerより自然とは言いにくい
- ローミングが要件に合うか確認が必要
- AppContainer外のデスクトップアプリでは、アプリ単位の強い分離を前提にしにくい
Credential Lockerの利点
- WinRTアプリモデルに沿った資格情報保存API
- 保存・取得・削除のAPIが単純
- パスワード型の資格情報保存には適合する
Credential Lockerの制約
- APIキー保存の第一候補というより、サインイン資格情報保存の延長として理解するほうが自然
- AppContainer外デスクトップアプリではアクセス境界が広い
- Microsoft文書上も大きなデータBLOB用途は想定していない
Credential Lockerが向くケース
- UWP / WinUI / パッケージ化デスクトップアプリ
- すでに
PasswordVaultを使う設計がある場合 - APIキーというより、ユーザーの保存済み資格情報に近いデータを扱う場合
比較表
| 方式 | 保存実体 | Windows API / モデル | 配布物解析への強さ | ファイル持ち出しへの強さ | 同一ユーザー権限への強さ | Windowsデスクトップアプリでの適合性 |
|---|---|---|---|---|---|---|
| コード埋め込み | EXE/DLL/リソース | 特になし | 低 | 低 | 低 | 実装は容易だが、機密保持方式としては不適 |
| 平文ファイル | json/ini/DB/レジストリ | 特になし | 低 | 低 | 低 | 実装は容易だが、本番の機密APIキーには不適 |
| DPAPI | アプリ管理の暗号化BLOB | CryptProtectData / .NET ProtectedData | 中 | 高 | 低 | 高。典型的なWin32/.NETクライアント向け |
| Credential Manager | OS管理の資格情報レコード | CredWrite / CredRead | 中 | 高 | 低 | 高。APIキー1件を資格情報として保存しやすい |
| Credential Locker | OS管理のWinRT資格情報ロッカー | PasswordVault | 中 | 高 | 低 | 中。UWP/WinUI/パッケージ化アプリ寄り |
選び方
一般的なWin32 / .NET実行ファイル
候補はDPAPIまたはCredential Managerでよい。
- APIキー以外の秘密設定もまとめて保護したい
→ DPAPI - APIキーを「1件の資格情報」としてOSストアに保存したい
→ Credential Manager
LocalMachineを使うか
クライアントPCでは、原則として避けるほうがよい。
MicrosoftはLocalMachineについて、そのコンピューター上の任意のプロセスまたは任意のユーザーが復号できると説明している。46
Credential Lockerを選ぶ場面
次の条件を満たす場合に限定して検討すればよい。
- すでにWinRT / UWP / WinUI / packaged desktopの文脈にある
- 保存対象がパスワード型の小さな文字列である
- ローミングやアクセス境界の仕様を理解している
選ばない方式
- コード埋め込み: 配布後に秘密として扱えない
- 平文ファイル: 機密情報のローカル保存方式として弱い
まとめ
Windows実行ファイルで機密APIキーを保持する前提なら、比較対象の中で現実的なのはDPAPI、Credential Manager、状況限定でCredential Lockerである。
- コード埋め込みは、配布型ネイティブアプリの共有秘密として扱うべきではない
- 平文ファイルは、機密情報の保存方式として弱い
- DPAPIは、任意データをアプリ側保存先に暗号化して置く方式
- Credential Managerは、OSの資格情報ストアに名前付き資格情報として保存する方式
- Credential Lockerは、WinRTアプリモデル寄りのパスワード保存方式
Windowsデスクトップアプリでの第一候補は、通常 DPAPI(CurrentUser) か Credential Manager(CRED_TYPE_GENERIC) である。