みなさまこんにちは〜!
メモリアインクのすだです。
本日は、
KotlinのEncryptedSharedPreferencesやSQLCipherを使って
暗号化されたストレージを構築する方法を、
実際のコードを利用して徹底解説していきます!
この記事を読んでわかること…
・暗号化されたストレージとは?
・EncryptedSharedPreferencesを使った暗号化されたストレージを構築する方法
・SQLCipherを使った暗号化データベースを構築する方法
環境
- Kotlin (ver 1.9.0)
 - Android Studio (Giraffe | 2022.3.1 Patch 3)
 
暗号化されたストレージとは?
暗号化されたストレージとは、保存されるデータを暗号化することで、第三者からデータを保護する仕組みです。
これにより、万が一ストレージが漏洩してもデータが読み取られることはありませ
- 用途 例:
- ユーザーの個人情報の保護。
 - パスワードやトークンなど、機密情報の安全な保存。
 - コンプライアンス(GDPR、HIPAAなど)の遵守。
 
 
EncryptedSharedPreferencesを使った暗号化
EncryptedSharedPreferencesは、Androidが提供する暗号化されたSharedPreferencesです。
データをファイル単位で暗号化して保存でき、簡単にセットアップできるのが特徴です。
EncryptedSharedPreferencesのセットアップ
EncryptedSharedPreferencesを使用するには、build.gradle ファイルに以下のように依存関係を追加します。
dependencies {
    implementation "androidx.security:security-crypto:1.1.0-alpha05"
}セットアップが完了したら、早速実装していきましょう!
import android.content.Context
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys
fun getEncryptedSharedPreferences(context: Context): SharedPreferences {
    val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
    return EncryptedSharedPreferences.create(
        "secure_prefs", // ファイル名
        masterKeyAlias,
        context,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )
}
// データの保存
fun saveData(context: Context, key: String, value: String) {
    val encryptedPrefs = getEncryptedSharedPreferences(context)
    encryptedPrefs.edit().putString(key, value).apply()
}
// データの取得
fun getData(context: Context, key: String): String? {
    val encryptedPrefs = getEncryptedSharedPreferences(context)
    return encryptedPrefs.getString(key, null)
}6行目:
MasterKeys.getOrCreate- 暗号化キーを作成または取得します。
 AES256_GCM_SPECに基づく安全な暗号化キーを利用しています。
8行目:
EncryptedSharedPreferences.create- 暗号化されたSharedPreferencesを作成します。
 - キーと値の両方が暗号化されます。
 
18行目、23行目:
- データの保存・取得
- 通常の
SharedPreferencesと同様に、putStringやgetStringを使用できます。 
 - 通常の
 
SQLCipherを使った暗号化データベース
SQLCipherは、SQLiteデータベースを暗号化するライブラリで、データベース全体を暗号化し、高いセキュリティを提供します。
特に、大量のデータを扱う場合に最適です。
SQLCipherのセットアップ
SQLCipherを使用するには、build.gradle ファイルに以下のように依存関係を追加します。
dependencies {
    implementation 'net.zetetic:android-database-sqlcipher:4.5.3'
}セットアップが完了したら、早速実装していきましょう!
まずは EncryptedDatabaseHelper クラスを定義していきます ▼
import android.content.Context
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SQLiteOpenHelper
class EncryptedDatabaseHelper(context: Context) : SQLiteOpenHelper(
    context, "encrypted_database.db", null, 1
) {
    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL("CREATE TABLE secure_table (id INTEGER PRIMARY KEY, data TEXT)")
    }
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        db.execSQL("DROP TABLE IF EXISTS secure_table")
        onCreate(db)
    }
}
fun getEncryptedDatabase(context: Context, password: String): SQLiteDatabase {
    SQLiteDatabase.loadLibs(context)
    return EncryptedDatabaseHelper(context).writableDatabase.apply {
        openOrCreateDatabase("encrypted_database.db", password, null)
    }
}5〜16行目:
EncryptedDatabaseHelperクラス- SQLiteOpenHelperを継承したクラスで、データベースの作成やアップグレードの処理を定義しています。
 onCreate: データベースが初めて作成されるときに呼び出されます。- この中でテーブル 
secure_tableを作成するSQL文を実行します。▼CREATE TABLE secure_table (id INTEGER PRIMARY KEY, data TEXT)idは主キー、dataはテキストデータを保存するためのカラムです。
 
- この中でテーブル 
 onUpgrade: データベースのバージョンが更新されたときに呼び出されます。- 既存のテーブルを削除(
DROP TABLE IF EXISTS)し、新しいテーブルを再作成する処理を行います。 
- 既存のテーブルを削除(
 
18〜23行目:
getEncryptedDatabaseクラス- SQLCipherを使って暗号化されたデータベースを取得します。
 SQLiteDatabase.loadLibs(context):SQLCipherのライブラリをロードし、暗号化・復号化の機能を使えるようにします。openOrCreateDatabase:指定したパスワードを使ってデータベースを開きます。データベースが存在しない場合は新しく作成します。
(apply ブロック内でデータベース操作を実行することで、暗号化された状態で処理が行われます。)
そして
データの追加や取得に関しては、以下のように実装してください。 ▼
// データの追加
fun insertData(context: Context, password: String, data: String) {
    val db = getEncryptedDatabase(context, password)
    db.execSQL("INSERT INTO secure_table (data) VALUES (?)", arrayOf(data))
    db.close()
}
// データの取得
fun getData(context: Context, password: String): List<String> {
    val db = getEncryptedDatabase(context, password)
    val cursor = db.rawQuery("SELECT data FROM secure_table", null)
    val results = mutableListOf<String>()
    while (cursor.moveToNext()) {
        results.add(cursor.getString(0))
    }
    cursor.close()
    db.close()
    return results
}2〜6行目:
insertData関数- 暗号化されたデータベースにデータを挿入します。
 getEncryptedDatabaseを使って暗号化されたデータベースを開き、execSQLメソッドでSQL文を実行し、データを挿入していきます。▼db.execSQL("INSERT INTO secure_table (data) VALUES (?)", arrayOf(data))?はプレースホルダーで、arrayOf(data)で指定されたデータが埋め込まれます。
- 挿入後にデータベースを閉じてください(
db.close())。 
9〜19行目:
getData関数- 暗号化されたデータベースからデータを取得し、リスト形式で返します。
 getEncryptedDatabaseを使って暗号化されたデータベースを開き、rawQueryメソッドを使ってデータを取得していきます。▼db.rawQuery("SELECT data FROM secure_table", null)dataカラムの全データを取得します。
- 取得したデータをカーソル (
Cursor) でループ処理してリストに追加、最後にデータベースを閉じてください。 
選択のポイント:どちらを使うべきか
それぞれに以下の特徴がありますので、状況に応じて使い分けてください。
| 項目 | EncryptedSharedPreferences | SQLCipher | 
|---|---|---|
| データ量 | 少量のキーと値のペア | 大量のデータ | 
| 使いやすさ | 設定が簡単 | 若干複雑 | 
| セキュリティ | Android標準の暗号化 | 高い暗号化レベル | 
| パフォーマンス | 小規模データでは高速 | データ量が多いとやや遅い | 
まとめ
おつかれさまでした。いかがでしたでしょうか!
どちらも用途に応じて選択し、アプリのセキュリティを強化するのに活用してください!
技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】![]()
![]()
自分の市場価値をさらに向上させてみませんか?


			







コメント