目前在我的android应用程序是由DexGuard保护,以混淆字符串和敏感信息,如网络API密钥,这是存在于源代码内。
我已经使用了DexGuarsd,所以没有人可以逆向工程它。
但是我需要停止DexGuard订阅。
所以如果我使用Android Jetpack安全EncryptedSharedPreferences
和EncryptedFile.Builder
,那么它会帮助我实现像dexguard提供的安全吗?
例如:如果我像下面的代码一样使用EncryptedSharedPreferences
,那么如果有人访问我的源代码或.apk
,那么他/她是否能够看到敏感值密码- xxxxxxxx与否。
因为上面的密码存在于我的源代码文件中。
encryptedSharedPreferences.edit().apply {
putString("MY_KEY","PASSWORD-XXXXXXXX"
}.apply()
我的目标是确保即使有人得到了我的源代码,那么上面的值"PASSWORD-XXXXXXXX"不能被任何人解密或看到。
我需要你的指导来实现它。请指教一下前进的方向。
不管你做什么,如果有人想要他们的手在源代码中存储字符串你不能阻止他们
暴露网络api是很好的,因为在各种im应用程序中这是常见的做法,即使你可以使api从源代码中无法读取,网络流量可以简单地用适当的工具嗅探,使所有保护功能无效
存储密码是完全错误的,而是存储运行时生成的散列,在这里和那里添加一些盐和胡椒(使其辛辣)
使用ssl/tls使服务器客户端会话难以读取
记住,锁只会把诚实的人关在外面,把锁放在那里,但永远不要依赖它
将密码保存在应用级build.graldle
文件中,如:
android {
compileSdkVersion 30
buildToolsVersion = '29.0.3'
defaultConfig {
buildConfigField 'String', 'prefPass', '"YourPasswordHere"'
// rest of the code goes here..
并像这样使用:
BuildConfig.prefPass
由于build.gradle
文件不是APK源代码的一部分,所以没有人可以窃取它。
为什么要把密码保存在共享首选项中?为什么不能直接从BuildConfig中使用它呢?如果你真的想保存它,然后加密并保存它使用这个类:
import android.util.Log
import java.security.MessageDigest
import java.util.*
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
object CryptographyUtil {
private const val TAG: String = "CryptographyUtil"
private const val CIPHER_TRANSFORMATION = "AES/CBC/PKCS5PADDING"
private const val KEY_ALGORITHM = "AES"
// https://developer.android.com/guide/topics/security/cryptography#encrypt-message
fun encryptData(key: String, data: String): String {
try {
val secretKeySpec = generateSecretKey(key)
val cipher = Cipher.getInstance(CIPHER_TRANSFORMATION)
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, getIVSpecification(key))
val encryptValue = cipher.doFinal(data.toByteArray())
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Base64.getEncoder().encodeToString(encryptValue)
} else {
android.util.Base64.encodeToString(encryptValue, android.util.Base64.DEFAULT)
}
} catch (e: Exception) {
Log.d(TAG, "Error while encrypt ${e.message}")
}
return data
}
fun decryptData(key: String, encryptedData: String): String {
try {
val secretKeySpec = generateSecretKey(key)
val cipher = Cipher.getInstance(CIPHER_TRANSFORMATION)
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, getIVSpecification(key))
val decodeValue = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Base64.getDecoder().decode(encryptedData)
} else {
android.util.Base64.decode(encryptedData, android.util.Base64.DEFAULT)
}
return String(cipher.doFinal(decodeValue))
} catch (e: Exception) {
Log.d(TAG, "Error while decrypt ${e.message}")
}
return encryptedData
}
private fun generateSecretKey(key: String): SecretKeySpec {
val messageDigest = MessageDigest.getInstance("SHA-256")
val bytes = key.toByteArray(Charsets.UTF_8)
messageDigest.update(bytes, 0, bytes.size)
return SecretKeySpec(messageDigest.digest(), KEY_ALGORITHM)
}
private fun getIVSpecification(key: String): IvParameterSpec {
// concat string so that key has always size greater than 16 bytes & we can
// get first 16 character for generating IV specification.
// As documentation suggest that IV specification key can't be less or greater than 16 bytes
val concatKey = key + key
return IvParameterSpec(concatKey.substring(0, 16).toByteArray())
}
}
在EncryptedSharedPreferences
类中使用上述类:
val encryptData = encryptData(BuildConfig.prefPass,
BuildConfig.prefPass)
encryptedSharedPreferences.edit().apply {
putString("MY_KEY", encryptData)
}.apply()
注意:要使此工作,您需要启用最小化以隐藏BuildConfig
文件。
buildTypes {
release {
debuggable false
minifyEnabled true
shrinkResources true
zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
minifyEnabled true
shrinkResources true
zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
在这里核对答案
最小化步骤的另一个特性是常量的内联。这就解释了为什么BuildConfig消失了,而值仍然存在于需要的地方。一旦值被内联,就不再有对BuildConfig类的引用,并且minifier可以完全删除它
加密部分只是为了防止Key从应用程序中读取,根据定义,这是不可能的。如果你的应用程序可以使用密钥,它也可以被你的应用程序的修改版本使用,该版本会将密钥转储到LogCat或其他东西。像ProGuard, DexGuard和kin这样的工具使它更难访问,但它们无法阻止它。防止钥匙被访问的唯一方法是没有应用在第一时间。裁判:https://stackoverflow.com/a/30238695/2462531