目次
公開鍵暗号方式
- 暗号化に公開鍵、復号に秘密鍵を使う暗号方式
- アプリ側では公開鍵を保持してデータの暗号化のみを行い、復号を異なる安全な場所(サーバーなど)で秘密鍵によって行うような用途には公開鍵暗号を使う
- SharedPreferncesを自前で暗号化する時などにAndroid KeyStoreを使った実装がこちらに該当する
共通鍵暗号方式
- 暗号化や復号する際、同じキー(共通鍵)を使う暗号方式
暗号方式の比較
Android Keystoreを用いた公開鍵暗号方式での暗号化・復号化
@Singleton
class KeyStore @Inject constructor() {
private var keyStore: KeyStore = KeyStore.getInstance(KEY_PROVIDER)
init {
keyStore.load(null)
if (!keyStore.containsAlias(kEY_STORE_ALIAS)) {
val keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, KEY_PROVIDER)
keyPairGenerator.initialize(
KeyGenParameterSpec.Builder(
kEY_STORE_ALIAS,
KeyProperties.PURPOSE_DECRYPT
)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.build()
)
keyPairGenerator.generateKeyPair()
}
}
fun encrypt(value: String): String {
return try {
val publicKey = keyStore.getCertificate(kEY_STORE_ALIAS)?.publicKey
val cipher = Cipher.getInstance(TRANSFORMATION)
cipher.init(Cipher.ENCRYPT_MODE, publicKey)
Base64.encodeToString(cipher.doFinal(value.toByteArray(Charsets.UTF_8)), Base64.NO_WRAP)
} catch (e: GeneralSecurityException) {
""
}
}
fun decrypt(value: String): String {
return try {
val privateKey = keyStore.getKey(kEY_STORE_ALIAS, null)
val cipher = Cipher.getInstance(TRANSFORMATION)
val decoded = Base64.decode(value, Base64.NO_WRAP)
cipher.init(Cipher.DECRYPT_MODE, privateKey)
cipher.doFinal(decoded).toString(Charsets.UTF_8)
} catch (e: GeneralSecurityException) {
""
}
}
companion object {
private const val KEY_PROVIDER = "AndroidKeyStore"
private const val kEY_STORE_ALIAS = "operation-check-alias"
private const val TRANSFORMATION = "RSA/ECB/PKCS1Padding"
}
}
共通鍵暗号方式を使った暗号化・復号化
@Singleton
class EncryptionWithPreSharedKey @Inject constructor() {
private var mIV: ByteArray? = null
// TODO EncryptedValueやPreSharedKeyのような値オブジェクトを作った方が良い
fun encrypt(
value: String,
key: String,
): String {
var encrypted: ByteArray? = null
val cipher = Cipher.getInstance(TRANSFORMATION)
val secretKey = generateKey(key.toByteArray(Charsets.UTF_8))
if (secretKey != null) {
try {
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
mIV = cipher.iv
encrypted = cipher.doFinal(value.toByteArray(Charsets.UTF_8))
} catch (e: Exception) {
Log.d("EncryptionWithPreSharedKey encrypt", "$e")
}
}
return Base64.encode(encrypted, Base64.NO_WRAP).toString(Charsets.UTF_8)
}
fun decrypt(
value: String,
key: String,
): String {
var decrypted: ByteArray? = null
try {
val cipher = Cipher.getInstance(TRANSFORMATION)
val secretKey = generateKey(key.toByteArray(Charsets.UTF_8))
if (secretKey != null) {
val ivParameterSpec = IvParameterSpec(mIV)
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec)
val decodedValue = Base64.decode(value.toByteArray(), Base64.NO_WRAP)
decrypted = cipher.doFinal(decodedValue)
}
} catch (e: Exception) {
Log.d("EncryptionWithPreSharedKey decrypt", "$e")
}
return decrypted?.toString(Charsets.UTF_8) ?: ""
}
private fun generateKey(key: ByteArray): SecretKey? {
var secretKey: SecretKey? = null
try {
secretKey = SecretKeySpec(key, KEY_ALGORITHM)
} catch (e: IllegalArgumentException) {
Log.d("EncryptionWithPreSharedKey generateKey", "$e")
}
return secretKey
}
companion object {
private const val TRANSFORMATION = "AES/CBC/PKCS7Padding"
private const val KEY_ALGORITHM = "AES"
}
}
この記事へのコメントはありません。