セキュリティ ライブラリでは、保存データの読み取りと書き込みに加え、キーの作成と検証に関連するセキュリティに関するおすすめの方法の実装が提供されます。
このライブラリはビルダー パターンを使用して、以下のセキュリティ レベルの安全なデフォルト設定を提供します。
- 高度な暗号化と優れたパフォーマンスを両立する強力なセキュリティ。このセキュリティ レベルは、銀行アプリやチャットアプリなどの一般向けアプリや、証明書失効チェックを行う企業向けアプリに適しています。
- 最高セキュリティ。このセキュリティ レベルは、キーへのアクセスにハードウェア格納型キーストアとユーザー操作を必要とするアプリに適しています。
このガイドでは、セキュリティ ライブラリの推奨セキュリティ設定の利用方法のほか、ファイルに保存されている暗号化されたデータと共有設定を読み書きする方法を説明します。
キーの管理
セキュリティ ライブラリは、キー管理に 2 部構成のシステムを使用します。
-
ファイルまたは共有設定データを暗号化するための、1 つ以上のキーを含むキーセット。キーセット自体は
SharedPreferences
に格納されます。 -
すべてのキーセットを暗号化する主(
master
)キー。 このキーは Android キーストア システムを使用して保存されます。
ライブラリに含まれるクラス
セキュリティ ライブラリに含まれる以下のクラスを使用すると、データをより安全に保存できます。
EncryptedFile
-
FileInputStream
とFileOutputStream
のカスタム実装を使って、アプリによるストリーミング読み取り操作とストリーミング書き込み操作のセキュリティを強化できます。ファイル ストリームの安全な読み取り操作と書き込み操作を実現するため、セキュリティ ライブラリではストリーミング認証付き暗号(AEAD)プリミティブを使用します。このプリミティブの詳細については、GitHub の Tink ライブラリのドキュメントをご覧ください。
EncryptedSharedPreferences
-
SharedPreferences
クラスをラップし、2 つの方式を使用してキーと値を自動的に暗号化します。- キーは、暗号化された状態でも検索できるように、決定性暗号化アルゴリズムを使用して暗号化されます。
- 値は、AES-256 GCM を使用して暗号化されます。これは非決定性です。
以下のセクションでは、これらのクラスを使用して、ファイルと共有設定に一般的な操作を行う方法を示します。
プロジェクトにライブラリを組み込む
セキュリティ ライブラリを使用するには、必要に応じて、アプリ モジュールの build.gradle
ファイルに次の依存関係を追加します。
Groovy
dependencies { implementation "androidx.security:security-crypto:1.0.0" // For Identity Credential APIs implementation "androidx.security:security-identity-credential:1.0.0-alpha03" // For App Authentication APIs implementation "androidx.security:security-app-authenticator:1.0.0-alpha02" // For App Authentication API testing androidTestImplementation "androidx.security:security-app-authenticator:1.0.0-alpha01" }
Kotlin
dependencies { implementation("androidx.security:security-crypto:1.0.0") // For Identity Credential APIs implementation("androidx.security:security-identity-credential:1.0.0-alpha03") // For App Authentication APIs implementation("androidx.security:security-app-authenticator:1.0.0-alpha02") // For App Authentication API testing androidTestImplementation("androidx.security:security-app-authenticator:1.0.0-alpha01") }
ファイルを読み取る
次のコード スニペットは、EncryptedFile
を使用して、ファイルの内容を読み取る方法を示しています。
Kotlin
// Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) val fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(DIRECTORY, fileToRead), applicationContext, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val inputStream = encryptedFile.openFileInput() val byteArrayOutputStream = ByteArrayOutputStream() var nextByte: Int = inputStream.read() while (nextByte != -1) { byteArrayOutputStream.write(nextByte) nextByte = inputStream.read() } val plaintext: ByteArray = byteArrayOutputStream.toByteArray()
Java
Context context = getApplicationContext(); // Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC; String mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec); String fileToRead = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder( new File(DIRECTORY, fileToRead), context, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); InputStream inputStream = encryptedFile.openFileInput(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int nextByte = inputStream.read(); while (nextByte != -1) { byteArrayOutputStream.write(nextByte); nextByte = inputStream.read(); } byte[] plaintext = byteArrayOutputStream.toByteArray();
ファイルを書き込む
次のコード スニペットは、EncryptedFile
を使用して、ファイルの内容を書き込む方法を示しています。
Kotlin
// Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) // Create a file with this name or replace an entire existing file // that has the same name. Note that you cannot append to an existing file, // and the filename cannot contain path separators. val fileToWrite = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(DIRECTORY, fileToWrite), applicationContext, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val fileContent = "MY SUPER-SECRET INFORMATION" .toByteArray(StandardCharsets.UTF_8) encryptedFile.openFileOutput().apply { write(fileContent) flush() close() }
Java
Context context = getApplicationContext(); // Although you can define your own key generation parameter specification, it's // recommended that you use the value specified here. KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC; String mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec); // Create a file with this name or replace an entire existing file // that has the same name. Note that you cannot append to an existing file, // and the filename cannot contain path separators. String fileToWrite = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder( new File(DIRECTORY, fileToWrite), context, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); byte[] fileContent = "MY SUPER-SECRET INFORMATION" .getBytes(StandardCharsets.UTF_8); OutputStream outputStream = encryptedFile.openFileOutput(); outputStream.write(fileContent); outputStream.flush(); outputStream.close();
さらに強化されたセキュリティが必要なユースケースでは、次の手順を実行します。
KeyGenParameterSpec.Builder
オブジェクトを作成して、true
をsetUserAuthenticationRequired()
に、0 より大きい値をsetUserAuthenticationParameters()
の最初の引数として渡します。createConfirmDeviceCredentialIntent()
を使用して、ユーザーに認証情報の入力を求めます。鍵を使用するためのユーザー認証のリクエスト方法をご確認ください。onActivityResult()
をオーバーライドして、確認済み認証情報のコールバックを取得します。
共有設定を編集する
次のコード スニペットは、EncryptedSharedPreferences
を使用して、ユーザーの共有設定のセットを編集する方法を示しています。
Kotlin
val sharedPrefsFile: String = FILE_NAME val sharedPreferences: SharedPreferences = EncryptedSharedPreferences.create( sharedPrefsFile, mainKeyAlias, applicationContext, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) with (sharedPreferences.edit()) { // Edit the user's shared preferences... apply() }
Java
String sharedPrefsFile = FILE_NAME; SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( sharedPrefsFile, mainKeyAlias, getApplicationContext(), EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ); SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit(); // Edit the user's shared preferences... sharedPrefsEditor.apply();
Android 5.0 デバイスと Android 5.1 デバイスをサポートする
セキュリティ ライブラリのバージョン 1.1.0 では、Android 5.0(API レベル 21)以降を搭載しているデバイスをサポートできます。Android 5.0 と Android 5.1(API レベル 22)では、Android キーストアを使用してキーセットを保存することはできません。
ファイルを読み取る
次のコード スニペットは、EncryptedFile
を使用して、セキュリティ ライブラリのバージョン 1.1.0 でファイルの内容を読み取る方法を示しています。
Kotlin
val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder(applicationContext, File(DIRECTORY, fileToRead), mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val inputStream = encryptedFile.openFileInput() val byteArrayOutputStream = ByteArrayOutputStream() var nextByte: Int = inputStream.read() while (nextByte != -1) { byteArrayOutputStream.write(nextByte) nextByte = inputStream.read() } val plaintext: ByteArray = byteArrayOutputStream.toByteArray()
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); String fileToRead = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder(context, new File(DIRECTORY, fileToRead), mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); InputStream inputStream = encryptedFile.openFileInput(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); int nextByte = inputStream.read(); while (nextByte != -1) { byteArrayOutputStream.write(nextByte); nextByte = inputStream.read(); } byte[] plaintext = byteArrayOutputStream.toByteArray();
ファイルを書き込む
次のコード スニペットは、EncryptedFile
を使用して、セキュリティ ライブラリのバージョン 1.1.0 でファイルの内容を書き込む方法を示しています。
Kotlin
val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() // Creates a file with this name, or replaces an existing file // that has the same name. Note that the file name cannot contain // path separators. val fileToWrite = File(DIRECTORY, "my_sensitive_data.txt") val encryptedFile = EncryptedFile.Builder(applicationContext, fileToWrite, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() // File cannot exist before using openFileOutput if (fileToWrite.exists()) { fileToWrite.delete() } val fileContent = "MY SUPER-SECRET INFORMATION" .toByteArray(StandardCharsets.UTF_8)) encryptedFile.openFileOutput().apply { write(fileContent) flush() close() }
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); // Creates a file with this name, or replaces an existing file // that has the same name. Note that the file name cannot contain // path separators. File fileToWrite = new File(DIRECTORY, "my_sensitive_data.txt"); EncryptedFile encryptedFile = new EncryptedFile.Builder(context, fileToWrite, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); // File cannot exist before using openFileOutput if (fileToWrite.exists()) { fileToWrite.delete(); } byte[] fileContent = "MY SUPER-SECRET INFORMATION" .getBytes(StandardCharsets.UTF_8); OutputStream outputStream = encryptedFile.openFileOutput(); outputStream.write(fileContent); outputStream.flush(); outputStream.close();
共有設定を編集する
次のコード スニペットは、EncryptedSharedPreferences
を使用して、セキュリティ ライブラリのバージョン 1.1.0 でユーザーの共有設定のセットを編集する方法を示しています。
Kotlin
val context = applicationContext val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val sharedPreferences = EncryptedSharedPreferences.create( applicationContext, FILE_NAME, mainKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) with (sharedPreferences.edit()) { // Edit the user's shared preferences... apply() }
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); SharedPreferences sharedPreferences = EncryptedSharedPreferences .create( context, FILE_NAME, mainKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ); SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit(); // Edit the user's shared preferences... sharedPrefsEditor.apply();
あなたへのおすすめ
- 注: JavaScript がオフになっている場合はリンクテキストが表示されます
- APK から埋め込み DEX コードを直接実行する
- タップジャッキング
- android:exported