KeyStore (Android): 基本概念、API、暗号ストレージの仕組み

著者: IT Sectr 公開日: 2026-03-14 読了時間: 10 分

KeyStore (Android) は、Java Cryptography Architecture (JCA) 暗号プロバイダの実装であり、ハードウェア分離機能を備えた安全なキーストレージのためにAndroidに統合されています。Android 4.3(API 18)以降、KeyStoreはKeymaster HALを介してハードウェアキーをサポートし、Android 9(API 28)以降は、専用のSecure Element内のキーに対してStrongBox Keymasterをサポートしています。Androidセキュリティドキュメントによると、“AndroidKeyStore”プロバイダは標準のBouncy CastleやOpenSSL KeyStoreを置き換え、不正なキー抽出に対するシステムレベルの保護を提供します。

重要なポイント

  • Android KeyStore は、TEE、StrongBox、生体認証保護をサポートするキーストレージ用のJCAプロバイダです
  • KeyGenParameterSpec は、キー作成時にアルゴリズム、目的、ダイジェスト、パディング、生体認証を定義します
  • Keymaster HAL は、Software、TEE、StrongBoxの各レベルでハードウェア暗号操作を実装します
  • Key Attestation(API 28+)により、サーバーはキーがAndroid KeyStoreのハードウェア環境で作成されたことを検証できます
  • キーエイリアス は、アプリケーションがKeystore内のキーにアクセスするための文字列であり、1つのエイリアスが1つのキーに対応します

AndroidのKeyStoreとは?

AndroidのKeyStore は、独立したアプリケーションやファイルではなく、java.security.KeyStore インターフェースを実装する暗号プロバイダです。秘密鍵、対称鍵、信頼できるCA証明書を保存および使用するための統一APIを提供します。プロバイダは “AndroidKeyStore” という名前で登録され、標準の KeyStore.getInstance() を介してアクセス可能です。

Android KeyStoreの進化

Android 4.3以前は、暗号操作はBouncy Castleを介して実行されていました。Android 4.3でKeymaster HAL 1.0が導入され、ARM TrustZoneでのTEE使用が可能になりました。Android 6.0(API 23)では、ハードウェアベースの指紋認証を備えたKeymaster 2.0が追加されました。Android 9(API 28)では、専用のSecure Element向けにKeymaster 4.0とStrongBox Keymasterが導入されました。

Keymasterの各バージョンは、新機能を追加し、キーの分離を改善します。最新のデバイス(2022年以降)は、Google Mobile Services認定のためにKeymaster 4.0をサポートする必要があり、すべてのAndroidアプリケーションにTEEの可用性を保証します。

アーキテクチャとコンポーネント

Android KeyStoreは3つのレイヤーで構成されています:Java API(KeyStore、KeyPairGenerator)、システムプロセスkeystore(C++、システムサービスとして実行)、Keymaster HAL(TEEまたはSecure Element内のライブラリ)。アプリケーションがAPIを呼び出し、keystoreサービスがリクエストをKeymasterにルーティングし、操作が安全な環境で実行されます。

すべての秘密鍵はTEEに保存され、ユーザースペースから読み取ることはできません。システムのkeystoreサービスでさえ、生のキーにアクセスすることはできず、Keymaster内部のキーを指すハンドルにのみアクセスできます。

KeyStoreは暗号プロバイダとしてどのように機能するか?

Android KeyStoreは、標準のJCAサービスプロバイダインターフェースを実装します。アプリケーションが Cipher.getInstance(“RSA/ECB/PKCS1Padding”, “AndroidKeyStore”) を呼び出すと、Androidセキュリティプロバイダはチェーンを介して操作をKeymasterに委任します:Java → JNI → keystoreサービス → Keymaster HAL。

プロバイダの登録

AndroidKeyStore プロバイダは、プロセス起動時に自動的に登録されます。その優先順位はBouncy CastleやConscryptよりも高いため、プロバイダを指定せずにKeyStore.getInstance()を呼び出すと、ほとんどの場合AndroidKeyStoreが返されます。明示的に呼び出すには、KeyStore.getInstance(“AndroidKeyStore”) を使用します。

各Androidアプリケーションは、KeyStore内に分離されたコンテナを持ちます。同じUID(shared userId)を持つアプリケーションは特定のキーへの共有アクセスを持つことができますが、標準設定ではアプリケーションAがアプリケーションBのキーを読み取れないことが保証されています。

KeyStoreのメソッドとその特徴

load(null) — KeyStoreの初期化。AndroidKeyStoreの場合、パラメータは常にnullです。setEntry — 指定されたKeyProtection(目的、ダイジェスト、パディング)でキーを保存します。getEntry — KeyStore.PrivateKeyEntry、SecretKeyEntry、またはTrustedCertificateEntryを取得します。containsAlias — キーの存在を確認します。deleteEntry — キーを完全に削除します。

kotlin
import java.security.KeyStore
import java.security.KeyPairGenerator
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties

object KeyStoreManager {
    private val keyStore by lazy {
        KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
    }

    fun createRsaKey(alias: String) {
        val spec = KeyGenParameterSpec.Builder(alias,
            KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_VERIFY
        ).setKeySize(2048)
         .setDigests(KeyProperties.DIGEST_SHA256)
         .setSignaturePaddings(KeyProperties.SIGN_PADDING_RSA_PKCS1)
         .build()

        val kpg = KeyPairGenerator.getInstance(
            KeyProperties.KEY_ALGORITHM_RSA,
            "AndroidKeyStore"
        )
        kpg.initialize(spec)
        kpg.generateKeyPair()
    }
}

サポートされるアルゴリズムとキータイプ

Android KeyStoreは、デバイスのKeymaster HALバージョンに応じて異なる幅広い暗号アルゴリズムをサポートしています。開発者は、生成を試みる際にKeyGenParameterSpec.Builderを介してサポートされるアルゴリズムのリストを取得できます。互換性のないパラメータはInvalidAlgorithmParameterExceptionをスローします。

非対称アルゴリズム

RSA(1024~4096ビット)— 署名(SHA-1/SHA-256/SHA-384/SHA-512を使用したPKCS1、PSS)および暗号化(SHA-1/SHA-256を使用したOAEP)用。EC(P-224、P-256、P-384、P-521)— ECDSA署名およびECDH鍵共有用。X25519 および Ed25519 — Android 12(API 31)以降の最新暗号プロトコル用。

非対称キーの場合は、常にKeymaster内で生成し、秘密鍵をインポートしないでください。インポートされた秘密鍵はハードウェアで保護されず、ソフトウェア層に保存されるため、アプリケーションプロセスが侵害されると脆弱になります。

対称アルゴリズム

AES(128、256ビット)— CBC、CTR、GCMモードでの対称暗号化用。HMAC(SHA-1、SHA-256、SHA-512)— メッセージ認証用。ChaCha20(Android 12+)— Poly1305認証付きの高性能ストリーム暗号化用。

アルゴリズムKeymaster目的API
RSAKM 1.0+署名、暗号化18+
ECKM 1.0+ECDSA、ECDH18+
AESKM 2.0+対称暗号化23+
HMACKM 2.0+認証コード23+
ChaCha20KM 3.0+ストリーム暗号化31+
X25519/Ed25519KM 3.0+鍵交換31+

キータイプとそのシリアライゼーション

KeyStore.PrivateKeyEntry — 秘密鍵(エクスポート不可)と証明書チェーンを含みます。KeyStore.SecretKeyEntry — 対称鍵用。KeyStore.TrustedCertificateEntry — 信頼できるCA証明書用。公開鍵は keyStore.getCertificate(alias).publicKey を介してエクスポート可能です。

キーの生成と使用例

完全なシナリオを見てみましょう:データ暗号化用のAESキーの生成と、生体認証保護付き署名用のECキーの生成。両方のキーは、ハードウェアサポートとともにAndroid KeyStore内で作成されます。

暗号化用のAESキーの生成

AESキーは、KeyGenParameterSpecを指定してKeyGeneratorを介して作成されます。パラメータ:PURPOSE_ENCRYPT + PURPOSE_DECRYPT、BLOCK_MODE_GCM(認証付きの推奨モード)、ENCRYPTION_PADDING_NONE(GCMにはパディング不要)。

kotlin
import javax.crypto.KeyGenerator
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec

fun generateAndEncrypt(alias: String, plainText: ByteArray): ByteArray {
    val spec = KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
    ).setBlockModes(KeyProperties.BLOCK_MODE_GCM)
     .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
     .setKeySize(256)
     .build()

    val kg = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")
    kg.initialize(spec)
    kg.generateKey()

    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    cipher.init(Cipher.ENCRYPT_MODE, getKeyFromStore(alias))
    return cipher.doFinal(plainText)
}

生体認証保護付き署名

userAuthenticationRequired=true のECキーは、署名操作のたびにユーザー認証を必要とします。このためには、Signatureオブジェクトを含むCryptoObjectを指定したBiometricPromptが使用されます。生体認証が成功すると、Keymasterが操作を許可します。

kotlin
fun createBiometricSignKey(alias: String) {
    val spec = KeyGenParameterSpec.Builder(alias,
        KeyProperties.PURPOSE_SIGN
    ).setAlgorithmParameterSpec(
        ECGenParameterSpec("secp256r1")
    ).setDigests(KeyProperties.DIGEST_SHA256)
     .setUserAuthenticationRequired(true)
     .setInvalidatedByBiometricEnrollment(true)
     .build()

    val kpg = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_EC,
        "AndroidKeyStore"
    )
    kpg.initialize(spec)
    kpg.generateKeyPair()
}

KeyStoreとデバイスセキュリティ

Android KeyStoreは、ソフトウェアベースのKeyStore(JKS、BKS)には提供できないハードウェアレベルのセキュリティ保証を提供します。キーはSoCレベルで保護されており、Androidユーザースペースを完全に制御しても秘密鍵を抽出することはできません。

Key Attestation(Android 8.1+)

Key Attestation は、アプリケーション(およびサーバー)がキーが作成された環境を検証できるようにするメカニズムです。Android Keystoreは、キーの特性(アルゴリズム、サイズ、目的、ハードウェアバックアップの有無、生成元)のリストを含む証明書に署名します。サーバーは、Googleルート証明書までの証明書チェーンを検証します。

これは金融アプリケーションにとって重要です。サーバーはキーがハードウェア環境で作成されたことを要求し(Hardware-Backed = True)、ソフトウェアKeystoreで作成されたキーを拒否できます。Key Attestationは、攻撃者がKeystoreをエミュレーターに置き換える攻撃を防ぎます。

生体認証変更時のキー無効化

setInvalidatedByBiometricEnrollment(true) は、生体認証テンプレートが変更または削除されたときにKeymasterが自動的にキーを削除することを意味します。これは、攻撃者が既存のアカウントに自分の指紋を追加する攻撃から保護します。新しい指紋が追加されると、古いキーはアクセスできなくなります。

生体認証失敗の試行回数カウンターもKeymasterによって管理されます。maxBiometricAttempt(メーカーが設定可能、通常5回)後、Keymasterは生体認証キーを使用したすべての操作を30秒間ブロックします。10回失敗すると、デバイスのパスワード(秘密のPIN)が入力されるまでブロックされます。

よくある質問

Android KeyStoreとBouncy Castle KeyStoreの違いは何ですか?

Bouncy Castle(BKS)は、パスワードで保護されたファイルにキーを保存するソフトウェアベースのKeyStoreです。Android KeyStoreはハードウェア分離TEE/StrongBoxを使用します。BKSのキーはrootアクセスで抽出できますが、Android KeyStoreのキーは抽出できません。BKSはCA証明書に適しており、Android KeyStoreは秘密鍵に適しています。

暗号化と署名の両方に同じキーを使用できますか?

はい、生成時にPURPOSE_ENCRYPTまたはPURPOSE_DECRYPTまたはPURPOSE_SIGNまたはPURPOSE_VERIFYを指定すれば可能です。ただし、ベストプラクティスは異なる操作に別々のキーを作成することです。これにより、1つのキーが侵害された場合の損害を制限し、最小権限の原則に従います。

Android KeyStoreでキーがハードウェアバックアップされているかどうかを確認するには?

android.security.keystoreを介して利用可能な KeyStore.getKeyCharacteristics(alias) を使用します。このメソッドはフラグのセットを返します:FLAG_HARDWARE — TEE内のキー、FLAG_SECURE_ELEMENT — StrongBox内のキー。フラグがない場合、キーはソフトウェアのみです。

すべての生体認証テンプレートが削除されるとどうなりますか?

setInvalidatedByBiometricEnrollment(true) で作成されたすべてのキーは、Keymasterによって自動的に無効化されます。使用しようとすると、アプリケーションはKeyPermanentlyInvalidatedExceptionを受け取ります。これらのキーで暗号化されたデータは永久に失われます。

Android KeyStoreはキーのバックアップをサポートしていますか?

ハードウェアキー(TEE/StrongBox内)はバックアップをサポートしていません。これらは特定のデバイスに結びついています。ソフトウェアベースのキーはGoogle Driveバックアップに含めることができます。デバイス間でデータを転送するには、サーバー上でデータを暗号化し、新しいデバイスで復号化します。

まとめ

  • Android KeyStore — TEE/StrongBox内のKeymaster HALを介したハードウェア分離キーストレージ用のJCAプロバイダ
  • KeyGenParameterSpec は、アルゴリズム、サイズ、目的、ダイジェスト、生体認証、キーの時間制限を構成
  • RSA(KM 1.0+)、EC(KM 1.0+)、AES(KM 2.0+)、ChaCha20(KM 3.0+)— 異なるKeymasterレベルでサポートされるアルゴリズム
  • Key Attestation(API 28+)により、サーバー側でキーのハードウェア起源を検証可能
  • CryptoObjectを使用したsetUserAuthenticationRequired + BiometricPromptによる生体認証キー保護
  • 生体認証変更時のキー無効化により、追加された指紋の不正使用を防止
  • Androidアプリケーションでハードウェア保護付きの暗号キーを生成および保存するにはAndroid KeyStoreを使用

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください