티스토리 뷰
안녕하세요, 안드로이드 앱 개발자 여러분! 이번 글에서는 안드로이드 앱에서의 보안 강화를 위해 사용되는 AES/CBC 암호화에 대해 자세히 알아보겠습니다. 또한, Android Keystore를 활용하여 안전하게 SecretKey를 관리하는 방법에 대해서도 알아보겠습니다.
1. AES: 고급 암호화 표준
AES는 현대적인 대칭 키 알고리즘 중 하나로, NIST(미국 국립 표준 기술 연구소)에서 고안된 고급 암호화 표준입니다. 이 알고리즘은 안전성, 효율성, 간결성 등의 측면에서 우수한 성능을 보여주어 다양한 분야에서 널리 사용되고 있습니다.
1.1. AES의 주요 특징
- 대칭 암호화: AES는 대칭 암호화 방식으로, 동일한 키를 암호화와 복호화에 사용합니다. 이는 암호화된 데이터를 안전하게 전송하고 보관하기 위한 강력한 방법 중 하나입니다.
- 키 길이 다양성: AES는 키의 길이에 따라 다양한 보안 수준을 제공합니다. 주로 128, 192, 256 비트의 키 길이를 지원하며, 키의 길이가 길수록 높은 수준의 보안을 제공합니다.
- 블록 암호화: 데이터를 블록 단위로 처리하는 블록 암호화 방식을 채택하고 있습니다. CBC(Cipher Block Chaining) 및 기타 모드를 사용하여 데이터의 무결성을 보장합니다.
- 서브 바이트 대치 : AES는 비트 단위가 아니라 바이트 단위로 데이터를 처리합니다. 서브 바이트 대치는 각 바이트를 다른 바이트로 치환하는 단계로, 비선형성을 추가하여 공격에 대한 강력한 저항력을 제공합니다.
1.2. AES 암호화 모드
- ECB (Electronic Codebook):
- 특징: 가장 간단한 암호화 모드로, 평문 블록을 독립적으로 암호화합니다. 동일한 평문 블록이 동일한 암호문 블록으로 변환되기 때문에 패턴이나 구조가 유출될 수 있습니다. 따라서, 보안성이 상대적으로 낮아 일반적으로 권장되지 않습니다.
- CBC (Cipher Block Chaining):
- 특징: 이전 블록의 암호문이 현재 블록의 암호화에 사용되는 암호화 모드입니다. 초기 벡터(Initialization Vector, IV)라는 무작위의 값을 사용하여 첫 블록을 암호화합니다. CBC 모드는 패딩이 필요하며, 병렬 처리에 어려움이 있습니다.
- CFB (Cipher Feedback):
- 특징: 암호문의 일부를 피드백하여 다음 블록을 암호화하는 모드입니다. 블록 단위로 암호화되는 것이 아니라 비트 단위로 암호화되며, 패딩이 필요하지 않습니다. CFB는 스트림 암호화에 유용하며, 동기화에 대한 강점이 있습니다.
- OFB (Output Feedback):
- 특징: 이전 출력 블록이 다음 블록을 암호화하는 모드로, 블록 단위로 동작합니다. OFB는 병렬 처리에 적합하며, 스트림 암호화에 사용됩니다. 패딩이 필요하지 않습니다.
- CTR (Counter):
- 특징: 카운터 값을 사용하여 평문과 암호문을 연결하는 모드입니다. 각 블록은 독립적으로 암호화되므로 병렬 처리가 용이하며, 패딩이 필요하지 않습니다. 카운터 값을 적절히 관리해야 합니다.
2. CBC (Cipher Block Chaining) 모드의 중요성
CBC 모드는 암호화된 블록이 이전 블록의 암호문에 의존하는 방식으로, 데이터의 무결성을 강화합니다. 각 블록은 암호화된 이전 블록과 현재 블록의 XOR 결과로 계산되기 때문에 패턴이 예측되기 어렵습니다. 이를 통해 암호문이 변경되었을 때 해당 블록 뿐만 아니라 이후의 모든 블록이 영향을 받아 데이터의 안전성이 보장됩니다. 이 과정은 Initialization Vector (IV)라 불리는 무작위의 값과 XOR 연산을 활용하여 이루어집니다. IV는 매번 다르게 생성되어 암호문 패턴을 예측하기 어렵게 만듭니다.
3. AES/CBC 알고리즘과 암호문 관리
AES/CBC 알고리즘을 사용하여 데이터를 암호화하고 복호화하는 과정을 알아봅시다.
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import java.security.Key
import java.security.SecureRandom
class AESEncryption {
private val algorithm = "AES"
private val transformation = "AES/CBC/PKCS7Padding"
private val keySize = 256
fun encrypt(data: ByteArray, key: Key): Pair<ByteArray, ByteArray> {
// Initialization Vector 생성
val iv = ByteArray(16)
SecureRandom().nextBytes(iv)
val ivParameterSpec = IvParameterSpec(iv)
// AES 암호화
val cipher = Cipher.getInstance(transformation)
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec)
val encryptedData = cipher.doFinal(data)
return Pair(encryptedData, iv)
}
fun decrypt(encryptedData: ByteArray, iv: ByteArray, key: Key): ByteArray {
val ivParameterSpec = IvParameterSpec(iv)
// AES 복호화
val cipher = Cipher.getInstance(transformation)
cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec)
return cipher.doFinal(encryptedData)
}
}
코드 설명
- Initialization Vector (IV) 생성: SecureRandom().nextBytes(iv)를 통해 16바이트의 무작위 IV를 생성합니다.
- AES 암호화: Cipher.ENCRYPT_MODE로 초기화된 Cipher 객체를 사용하여 데이터를 암호화합니다.
- 복호화: Cipher.DECRYPT_MODE로 초기화된 Cipher 객체를 사용하여 암호문을 복호화합니다.
4. Android Keystore를 활용한 키 관리
안드로이드 Keystore는 키를 안전하게 생성, 저장 및 관리하기 위한 시스템 수준의 보안 저장소입니다. 안드로이드 Keystore를 사용하여 키를 생성하고 안전하게 관리함으로써 데이터의 무결성과 기밀성을 유지할 수 있습니다.
아래는 Android Keystore를 사용하여 AES 키를 생성하고 관리하는 코드의 예시입니다.
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.Key
import java.security.KeyStore
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
class KeyStoreManager {
private val keystoreAlias = "my_keystore_alias"
fun generateSecretKey(): SecretKey {
val keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore"
)
val keyGenParameterSpec = KeyGenParameterSpec.Builder(
keystoreAlias,
KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build()
keyGenerator.init(keyGenParameterSpec)
return keyGenerator.generateKey()
}
fun getSecretKey(): SecretKey? {
val keystore = KeyStore.getInstance("AndroidKeyStore")
keystore.load(null)
return keystore.getKey(keystoreAlias, null) as? SecretKey
}
}
5. RoomDatabase에 Encrypt된 정보 저장 및 노출
마지막으로, RoomDatabase를 사용하여 암호화된 정보를 저장하고, 저장된 정보를 복호화하여 노출하는 코드입니다.
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class RoomDatabaseActivity : AppCompatActivity() {
private lateinit var database: AppDatabase
private lateinit var encryption: AESEncryption
private lateinit var keystoreManager: KeyStoreManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
database = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "app_database"
)
.build()
encryption = AESEncryption()
keystoreManager = KeyStoreManager()
GlobalScope.launch(Dispatchers.IO) {
// 키 생성
val secretKey = keystoreManager.generateSecretKey()
// 데이터 암호화
val originalData = "Hello, RoomDatabase!".toByteArray()
val (encryptedData, iv) = encryption.encrypt(originalData, secretKey)
// 암호화된 데이터를 RoomDatabase에 저장
database.dataDao().insertData(DataEntity(encryptedData, iv))
// RoomDatabase에서 데이터 가져오기
val encryptedDataEntity = database.dataDao().getData()
// 암호화된 데이터 복호화
val decryptedData = encryption.decrypt(
encryptedDataEntity.encryptedData,
encryptedDataEntity.iv,
secretKey
)
// 결과 확인
val result = String(decryptedData)
println("Decrypted Data: $result")
}
}
}
6. 평문에서 암호화 Flow
7. 마무리
보안은 안드로이드 앱의 핵심 요소 중 하나로, 사용자의 민감한 데이터를 안전하게 보호해야 합니다. AES/CBC와 KeyStore를 활용하면 안전한 데이터 보호를 위한 강력한 기반을 마련할 수 있습니다. 데이터의 암호화는 물론, 안전한 키 관리 역시 중요한 부분이므로 주의 깊게 다루어져야 합니다.
앞으로도 계속해서 안드로이드 보안에 대한 심도 있는 이해와 적용을 통해 안전한 앱을 개발해 나가시기를 바랍니다. Happy coding! Skill UP!! 🚀
'안드로이드 세번째 걸음' 카테고리의 다른 글
Kotlin: 안드로이드 앱 개발의 깊은 이해와 응용 (11. MVVM 아키텍처의 고급 적용, LiveData) (0) | 2024.02.21 |
---|---|
Kotlin: 안드로이드 앱 개발의 깊은 이해와 응용 (10. SSL 통신과 데이터 암호화) (0) | 2024.02.20 |
Kotlin: 안드로이드 앱 개발의 깊은 이해와 응용 (8. 앱 보안 취약점 분석) (0) | 2024.02.18 |
Kotlin: 안드로이드 앱 개발의 깊은 이해와 응용 (7. JobIntentService 및 WorkManager 활용) (0) | 2024.02.17 |
Kotlin: 안드로이드 앱 개발의 깊은 이해와 응용 (6. 안드로이드 생명주기 깊이 이해) (0) | 2024.02.16 |
- Total
- Today
- Yesterday
- kotlin
- 디자인패턴
- 코틀린
- 사이버보안
- 비동기처리
- 기초
- 안드로이드
- 모듈화
- 앱개발
- RoomDatabase
- 비동기
- Fragment
- UI스레드
- 부동산
- cipher
- 내부데이터베이스
- coroutine
- MVVM패턴
- 생명주기
- 코루틴
- 안드로이드개발
- fragment생명주기
- 안드로이드앱개발
- 안드로이드 앱 개발
- 클린아키텍처
- Android
- RxJava
- 안드로이드기초
- 부동산 경매
- 경매
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |