6.6.3 - Alpha5 - 提升 APK 文件签名信息检测效率
This commit is contained in:
@@ -44,6 +44,8 @@
|
||||
* `优化` 已忽略更新记录及客户端模式连接地址记录支持清空操作
|
||||
* `优化` 版本更新信息支持多语言显示 (与当前显示语言同步)
|
||||
* `优化` 使用异步加载方式一定程度提升文件管理器列表滑动流畅性
|
||||
* `优化` APK 文件签名信息提升检测效率
|
||||
* `优化` APK 文件类型信息及媒体文件类型信息优化对话框显示效率及信息展示逻辑
|
||||
* `优化` Gradle 构建脚本提升版本自适应能力 _[`discussion #369`](http://discussions.autojs6.com/369)_
|
||||
* `依赖` 本地化 Material Dialogs 版本 0.9.6.0
|
||||
* `依赖` 本地化 Material Date Time Picker 版本 4.2.3
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
* `优化` 已忽略更新记录及客户端模式连接地址记录支持清空操作
|
||||
* `优化` 版本更新信息支持多语言显示 (与当前显示语言同步)
|
||||
* `优化` 使用异步加载方式一定程度提升文件管理器列表滑动流畅性
|
||||
* `优化` APK 文件签名信息提升检测效率
|
||||
* `优化` APK 文件类型信息及媒体文件类型信息优化对话框显示效率及信息展示逻辑
|
||||
* `优化` Gradle 构建脚本提升版本自适应能力 _[`discussion #369`](http://discussions.autojs6.com/369)_
|
||||
* `依赖` 本地化 Material Dialogs 版本 0.9.6.0
|
||||
* `依赖` 本地化 Material Date Time Picker 版本 4.2.3
|
||||
|
||||
@@ -13,7 +13,6 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
import com.afollestad.materialdialogs.DialogAction
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.android.apksig.ApkVerifier
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@@ -34,8 +33,6 @@ import org.autojs.autojs.util.IntentUtils.ToastExceptionHolder
|
||||
import org.autojs.autojs6.R
|
||||
import org.autojs.autojs6.databinding.ApkFileInfoDialogListItemBinding
|
||||
import java.io.File
|
||||
import java.util.jar.JarEntry
|
||||
import java.util.jar.JarFile
|
||||
|
||||
object ApkInfoDialogManager {
|
||||
|
||||
@@ -229,37 +226,17 @@ object ApkInfoDialogManager {
|
||||
}
|
||||
|
||||
private fun getApkSignatureInfo(apkFile: File): String? = runCatching {
|
||||
ApkVerifier.Builder(apkFile).build().verify().run {
|
||||
listOfNotNull(
|
||||
"V1".takeIf { isVerifiedUsingV1Scheme || hasV1Signature(apkFile) },
|
||||
"V2".takeIf { isVerifiedUsingV2Scheme },
|
||||
"V3".takeIf { isVerifiedUsingV3Scheme },
|
||||
"V4".takeIf { isVerifiedUsingV4Scheme },
|
||||
).takeUnless { it.isEmpty() }?.joinToString(" + ")
|
||||
}
|
||||
// ApkVerifier.Builder(apkFile).build().verify().run {
|
||||
// listOfNotNull(
|
||||
// "V1".takeIf { isVerifiedUsingV1Scheme || hasV1Signature(apkFile) },
|
||||
// "V2".takeIf { isVerifiedUsingV2Scheme },
|
||||
// "V3".takeIf { isVerifiedUsingV3Scheme },
|
||||
// "V4".takeIf { isVerifiedUsingV4Scheme },
|
||||
// ).takeUnless { it.isEmpty() }?.joinToString(" + ")
|
||||
// }
|
||||
ApkSignatureDetector.detectSchemes(apkFile)
|
||||
}.getOrNull()
|
||||
|
||||
private fun hasV1Signature(apkFile: File): Boolean {
|
||||
if (!apkFile.isFile) return false
|
||||
JarFile(apkFile).use { jar ->
|
||||
var hasManifest = false
|
||||
var hasSF = false
|
||||
var hasRSA = false
|
||||
for (entry: JarEntry in jar.entries()) {
|
||||
val name = entry.name.uppercase()
|
||||
when {
|
||||
name == "META-INF/MANIFEST.MF" -> hasManifest = true
|
||||
name.endsWith(".SF") && name.startsWith("META-INF/") -> hasSF = true
|
||||
name.endsWith(".RSA") && name.startsWith("META-INF/") -> hasRSA = true
|
||||
}
|
||||
if (hasManifest && hasSF && hasRSA) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private data class ApkInfo(
|
||||
val label: String?,
|
||||
val packageName: String?,
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package org.autojs.autojs.ui.main.scripts
|
||||
|
||||
import com.android.apksig.apk.ApkUtils
|
||||
import com.android.apksig.internal.apk.ApkSigningBlockUtils
|
||||
import com.android.apksig.util.DataSources
|
||||
import java.io.File
|
||||
import java.io.RandomAccessFile
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.util.jar.JarEntry
|
||||
import java.util.jar.JarFile
|
||||
|
||||
object ApkSignatureDetector {
|
||||
|
||||
private const val BLOCK_ID_V2 = 0x7109871a
|
||||
private const val BLOCK_ID_V3 = 0xF05368C0.toInt()
|
||||
private const val BLOCK_ID_V4 = 0x2b09189e
|
||||
|
||||
fun detectSchemes(apkFile: File): String? {
|
||||
if (!apkFile.isFile) return null
|
||||
|
||||
RandomAccessFile(apkFile, "r").use { raf ->
|
||||
val dataSource = DataSources.asDataSource(raf, 0, raf.length())
|
||||
val signingBlock = ApkUtils.findApkSigningBlock(dataSource).contents
|
||||
val signingBlockBuffer = signingBlock.getByteBuffer(0, signingBlock.size().toInt())
|
||||
|
||||
// Duplicate() is called for each detection to prevent position being modified by previous checks.
|
||||
// zh-CN: 每次检测都 duplicate(), 防止 position 被前一次修改.
|
||||
val hasV2 = hasScheme(signingBlockBuffer.duplicateAndOrderSignBuffer(), BLOCK_ID_V2)
|
||||
val hasV3 = hasScheme(signingBlockBuffer.duplicateAndOrderSignBuffer(), BLOCK_ID_V3)
|
||||
val hasV4 = hasScheme(signingBlockBuffer.duplicateAndOrderSignBuffer(), BLOCK_ID_V4)
|
||||
val hasV1 = hasV1Signature(apkFile)
|
||||
|
||||
return listOfNotNull(
|
||||
"V1".takeIf { hasV1 },
|
||||
"V2".takeIf { hasV2 },
|
||||
"V3".takeIf { hasV3 },
|
||||
"V4".takeIf { hasV4 },
|
||||
).takeUnless { it.isEmpty() }?.joinToString(" + ")
|
||||
}
|
||||
}
|
||||
|
||||
private fun ByteBuffer.duplicateAndOrderSignBuffer(): ByteBuffer {
|
||||
return duplicate().order(ByteOrder.LITTLE_ENDIAN)
|
||||
}
|
||||
|
||||
private fun hasScheme(buf: ByteBuffer, id: Int): Boolean = runCatching {
|
||||
ApkSigningBlockUtils.findApkSignatureSchemeBlock(buf, id, null)
|
||||
}.isSuccess
|
||||
|
||||
private fun hasV1Signature(apkFile: File): Boolean {
|
||||
JarFile(apkFile).use { jar ->
|
||||
var hasManifest = false
|
||||
var hasSF = false
|
||||
var hasRSA = false
|
||||
for (entry: JarEntry in jar.entries()) {
|
||||
val n = entry.name.uppercase()
|
||||
when {
|
||||
n == "META-INF/MANIFEST.MF" -> hasManifest = true
|
||||
n.startsWith("META-INF/") && n.endsWith(".SF") -> hasSF = true
|
||||
n.startsWith("META-INF/") && n.endsWith(".RSA") -> hasRSA = true
|
||||
}
|
||||
if (hasManifest && hasSF && hasRSA) return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user