Created
September 12, 2022 07:32
-
-
Save ghasemdev/293d90d33c20286c537ca423c1fb29ee to your computer and use it in GitHub Desktop.
App Signature for OTP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.annotation.SuppressLint | |
import android.content.Context | |
import android.content.ContextWrapper | |
import android.content.pm.PackageManager | |
import android.content.pm.Signature | |
import android.os.Build | |
import android.util.Base64 | |
import timber.log.Timber | |
import java.security.MessageDigest | |
import java.security.NoSuchAlgorithmException | |
import java.util.* | |
/** | |
* ## App signature | |
* generate hash secret keys for different build variants. | |
* (release, debug, and play store release version). | |
*/ | |
class AppSignatureHelper(context: Context) : ContextWrapper(context) { | |
val signatures: List<String> | |
get() { | |
val appCodes = mutableListOf<String>() | |
try { | |
// For each signature create a compatible hash | |
for (signature in getSignatures()) { | |
val hash = hash(packageName, signature.toCharsString()) | |
if (hash != null) { | |
appCodes.add(String.format("%s", hash)) | |
} | |
} | |
} catch (e: PackageManager.NameNotFoundException) { | |
Timber.tag(TAG).e(e, "Unable to find package to obtain hash.") | |
} | |
return appCodes | |
} | |
@SuppressLint("PackageManagerGetSignatures") | |
@Suppress("DEPRECATION") | |
@JvmName("getSignaturesList") | |
/** Get all package signatures for the current package */ | |
private fun getSignatures(): Array<Signature> { | |
try { | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { | |
val packageInfo = packageManager | |
.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES) | |
if (packageInfo?.signingInfo != null) { | |
return if (packageInfo.signingInfo.hasMultipleSigners()) { | |
packageInfo.signingInfo.apkContentsSigners | |
} else { | |
packageInfo.signingInfo.signingCertificateHistory | |
} | |
} | |
} else { | |
val packageInfo = packageManager | |
.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) | |
if (packageInfo?.signatures != null && | |
packageInfo.signatures.isNotEmpty() && packageInfo.signatures[0] != null | |
) { | |
return packageInfo.signatures | |
} | |
} | |
} catch (_: PackageManager.NameNotFoundException) { | |
} | |
return emptyArray() | |
} | |
private fun hash(packageName: String, signature: String): String? { | |
val appInfo = "$packageName $signature" | |
try { | |
val messageDigest = MessageDigest.getInstance(HASH_TYPE) | |
messageDigest.update(appInfo.encodeToByteArray()) | |
var hashSignature = messageDigest.digest() | |
// truncated into NUM_HASHED_BYTES | |
hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES) | |
// encode into Base64 | |
var base64Hash = | |
Base64.encodeToString(hashSignature, Base64.NO_PADDING or Base64.NO_WRAP) | |
base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR) | |
Timber.tag(TAG).d(TAG, String.format("pkg: %s -- hash: %s", packageName, base64Hash)) | |
return base64Hash | |
} catch (e: NoSuchAlgorithmException) { | |
Timber.tag(TAG).e(e, "Unable to find package to obtain hash.") | |
} | |
return null | |
} | |
companion object { | |
private val TAG = AppSignatureHelper::class.java.simpleName | |
private const val HASH_TYPE = "SHA-256" | |
private const val NUM_HASHED_BYTES = 9 | |
private const val NUM_BASE64_CHAR = 11 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment