Reputation: 620
In my Android project, I encountered a frustrating issue where the certificate fingerprint SHA-256 of the installed APK does not contain the SHA-256 fingerprint of the app's certificate for some users. This mismatch is causing problems with my app's functionality, and I'm not sure how to resolve it.
I've verified that the certificate and keystore used to sign the app are the same for all users. I've also ensured that I'm using the correct signing configuration.
Here's the code which I used to compare the SHA-256
// Get list of Installed APK's Signature's SHA-256
private fun getSignatures(): List<String>? {
val packageInfo = getPackageInfo() ?: return null
return try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (packageInfo.signingInfo == null) {
return null
}
if (packageInfo.signingInfo.hasMultipleSigners()) {
signatureDigest(packageInfo.signingInfo.apkContentsSigners)
} else {
signatureDigest(packageInfo.signingInfo.signingCertificateHistory)
}
} else {
val signatures = packageInfo.signatures
if (signatures.isNullOrEmpty() || signatures[0] == null) {
null
} else {
signatureDigest(signatures)
}
}
} catch (exception: PackageManager.NameNotFoundException) {
Utility.sendException(exception)
null
}
}
private fun getPackageInfo(): PackageInfo? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
packageManager.getPackageInfo(
PACKAGE_NAME,
PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES.toLong())
)
} else {
packageManager.getPackageInfo(
PACKAGE_NAME,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
PackageManager.GET_SIGNING_CERTIFICATES
} else {
PackageManager.GET_SIGNATURES
}
)
}
// Method to create a list of SHA256 APK signatures
private fun signatureDigest(sigList: Array<Signature>?): List<String>? {
if (sigList.isNullOrEmpty()) {
return null
}
return mutableListOf<String>().also {
sigList.forEach { signature ->
it.add(getSignatureSha256(signature.toByteArray()))
}
}
}
private fun getSignatureSha256(certificate: ByteArray): String {
val md: MessageDigest
try {
md = MessageDigest.getInstance("SHA256")
} catch (exception: NoSuchAlgorithmException) {
Utility.sendException(exception)
return ""
}
md.update(certificate)
return md.digest().joinToString(":") { String.format("%02x", it) }
}
// Test method to compare APK's fingerprint with the Public key of the signing credentials of the app
fun test(): Boolean {
return getSignatures()?.contains(APP_SHA256)
}
This is working fine for all my test devices, but when I put this APK for some real users, it returned false for many of them, while also being successful for most of them. I don't think so these many users would be using a modified version of the app.
Has anyone else encountered this problem before, and if so, how did you resolve it? Any insights or suggestions would be greatly appreciated. Thank you!
Upvotes: 0
Views: 453