Android сравнить подпись текущего пакета с debug.keystore

Как и все, что мы делаем, у меня есть приложение, которое подписывается debug.keystore (по умолчанию), когда оно находится в режиме разработки (сборка). Когда он идет, мы подписываем его с помощью нашего закрытого ключа. Есть ли способ определить во время выполнения, что текущий пакет подписан с debug.keystore (находится в режиме разработки) или подписан с нашим личным ключом (находится в режиме производства).

Я пробовал что-то вроде

PackageManager packageManager = getPackageManager(); try { Signature[] signs = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures; for (Signature signature : signs) { Log.d(TAG, "sign = " + signature.toCharsString()); } } catch (NameNotFoundException e) { e.printStackTrace(); } 

Я не знаю, что делать дальше? Правильно ли это? Как получить сопоставимую подпись debug.keystore?

Я знаю, что существует MD5 Fingerprint keytool -list -keystore ~/.android/debug.keystore но в классе Signature не существует метода «md5 fingerprint». Я хочу сделать это из-за MapView Key, Logging, LicenseChecker и тому подобного.

Solutions Collecting From Web of "Android сравнить подпись текущего пакета с debug.keystore"

Подпись в PackageInfo выглядит не так хорошо, поскольку в этом поле не содержится подпись пакета, а цепочка сертификатов подписчика X509. Обратите внимание, что (большую часть времени) эта цепочка, по-видимому, ограничивается одним самозаверяющим сертификатом.

Согласно странице разработчиков Android Signing Your Applications сертификат подписи отладки создается с помощью этого DN: CN=Android Debug,O=Android,C=US

Поэтому легко проверить, было ли приложение подписано в режиме отладки:

 private static final X500Principal DEBUG_DN = new X500Principal("CN=Android Debug,O=Android,C=US"); /* ... */ Signature raw = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures[0]; CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray())); boolean debug = cert.getSubjectX500Principal().equals(DEBUG_DN); 

Основываясь на ответе Jcs , мы используем это, чтобы узнать во время выполнения, который создал исполняемый пакет:

 private enum BuildSigner { unknown, Joe, Carl, Linda } private BuildSigner whoBuiltThis() { try { PackageManager packageManager = getPackageManager(); PackageInfo info = packageManager.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES); Signature[] signs = info.signatures; CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate)cf.generateCertificate( new ByteArrayInputStream(signs[0].toByteArray())); PublicKey key = cert.getPublicKey(); int modulusHash = ((RSAPublicKey)key).getModulus().hashCode(); switch (modulusHash) { case 123456789: return BuildSigner.Joe; case 424242424: return BuildSigner.Carl; case -975318462: return BuildSigner.Linda; } } catch (Exception e) { } return BuildSigner.unknown; } 

Для любого задействованного сертификата вам просто нужно найти хэш один раз и добавить его в список.

Самый простой способ «найти хэш один раз» может состоять в том, чтобы просто добавить всплывающий тост перед оператором switch, который отображает modulusHash , компилирует ваше приложение, запускает его, записывает хэш, удаляет код тоста и добавляет хэш в список.

В качестве альтернативы, когда я это осуществил, я создал небольшое приложение шаблонов с одним действием и одним TextView с ID- tv в главном макете, включив его в действие:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); int hash = 0; try{ PackageManager packageManager = getPackageManager(); PackageInfo info = packageManager.getPackageInfo( "com.stackexchange.marvin", PackageManager.GET_SIGNATURES); Signature[] signs = info.signatures; CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate( new ByteArrayInputStream(signs[0].toByteArray())); PublicKey key = cert.getPublicKey(); hash = ((RSAPublicKey) key).getModulus().hashCode(); }catch(Exception e){} TextView tv = ((TextView)findViewById(R.id.tv)); tv.setText("The Stack Exchange app's signature hash is " + hash + "."); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 24); } 

( com.stackexchange.marvin на имя вашего приложения), скомпилировали это мини-приложение и отправили APK всем участвующим разработчикам, попросив их запустить его на своем устройстве и сообщить мне отображаемый хеш.

Начиная с версии 17 инструментария SDK, мы можем просто написать это:

 if (BuildConfig.DEBUG) { //Your debug code goes here } else { //Your release code goes here }