---
# System prepended metadata

title: 加密解密
tags: [Android, Kotlin]

---

###### tags: `Android` `Kotlin`
# 加密解密

Jetpack 提供了 security 的套件，可以用於加密資料，以下將用它來製作加密的檔案

## 實作
gradle 加入套件
```
implementation "androidx.security:security-crypto:1.0.0-rc02"
```

> [官方最新版本資訊](https://developer.android.com/jetpack/androidx/releases/security)

建立一個存放加解密擴展函式的檔案
```kotlin=
enum class EncryptedFileType {
    Password
}

fun Context.setEncryptedFile(type: EncryptedFileType, content: String) {
    try {
        val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
        val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

        val dir = File(filesDir.absolutePath+"/encrypt")
        if (!dir.exists()) { dir.mkdirs() }

        val fileName = when(type) {
            EncryptedFileType.Password -> "password.txt"
        }

        val file = File(dir, fileName)
        if (file.exists()) file.delete()

        val encryptedFile = EncryptedFile.Builder(
            file,
            this,
            masterKeyAlias,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        ).build()

        encryptedFile.openFileOutput().bufferedWriter().use {
            it.write(content)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

fun Context.getEncryptedFile(type: EncryptedFileType): String {
    try {
        val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
        val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
        val path = filesDir.absolutePath+"/encrypt"
        val fileName = when(type) {
            EncryptedFileType.Password -> "password.txt"
        }

        val file = File(path, fileName).takeIf { it.exists() } ?: return  ""
        val encryptedFile = EncryptedFile.Builder(
            file,
            this,
            masterKeyAlias,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        ).build()

        return encryptedFile.openFileInput().bufferedReader().readLine() ?: ""
    } catch (e: Exception) {
        e.printStackTrace()
        return ""
    }
}
```

使用方式
```kotlin=
//加密後可以在 Device File Explorer 中找到檔案
setEncryptedFile(EncryptedFileType.Password, "abc123")

val pwd = getEncryptedFile(EncryptedFileType.Password)
Toast.makeText(this, pwd, Toast.LENGTH_SHORT).show()
```

## 參考文章
[使用AndroidX安全库加密SharedPreferences](https://yuweiguocn.github.io/androidx-security/)
[Encryption on Android with Jetpack Security](https://five.agency/encryption-on-android-with-jetpack-security/)
[官方文件](https://developer.android.com/guide/topics/security/cryptography)

[使用Android KeyStore 儲存敏感性資料](https://medium.com/joe-tsai/%E4%BD%BF%E7%94%A8keystore-%E5%84%B2%E5%AD%98%E6%95%8F%E6%84%9F%E6%80%A7%E8%B3%87%E6%96%99-92ad9b236e58)