
みなさまこんにちは〜!
メモリアインクのすだです。
本日は、
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エンジニアを目指すなら【ユニゾンキャリア】
自分の市場価値をさらに向上させてみませんか?
コメント