2011-05-25 11 views
13

के साथ वर्तमान पैकेज के हस्ताक्षर की तुलना करें, जैसा कि हम करते हैं मेरे पास ऐसा एप्लीकेशन है जो डीबग.कीस्टोर (डिफ़ॉल्ट रूप से) द्वारा हस्ताक्षरित है जब यह विकास मोड (बिल्ड) में होता है। जब यह उत्पादन हो जाता है तो हम इसे अपनी निजी कुंजी के साथ साइन करते हैं। क्या रनटाइम पर निर्धारित करने का कोई तरीका है कि वर्तमान पैकेज 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 हस्ताक्षर कैसे प्राप्त करें?

मुझे पता है कि एमडी 5 फिंगरप्रिंट keytool -list -keystore ~/.android/debug.keystore मौजूद है लेकिन हस्ताक्षर वर्ग में "md5 फिंगरप्रिंट" जैसी विधि नहीं है। मै मैप व्यू कुंजी, लॉगिंग, लाइसेंस चेकर और इस तरह की चीजों के कारण ऐसा करना चाहता हूं।

+0

आजकल मैं 1 स्थिर बूलियन मान का उपयोग करता हूं जिसे हर बार जब मैं उत्पादन रिलीज करता हूं तो मुझे बदलना पड़ता है। ऐसा हुआ है कि मैं भूल गया। :( – zmeda

उत्तर

15

PackageInfo में हस्ताक्षर अच्छी तरह से नामित नहीं प्रतीत होता है क्योंकि था फ़ील्ड में पैकेज हस्ताक्षर नहीं है लेकिन हस्ताक्षरकर्ता X509 प्रमाणपत्र श्रृंखला है। ध्यान दें कि (अधिकांश समय) यह श्रृंखला एक एकल स्व-हस्ताक्षरित प्रमाणपत्र तक ही सीमित है।

Android डेवलपर पेज Signing Your Applications डिबग हस्ताक्षर प्रमाण पत्र इस डीएन साथ उत्पन्न होता है के अनुसार: 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); 
+0

मुझे लगता है कि 'DEBUG_DN'' X509 प्रिंसिपल 'का प्रकार सही है? – zmeda

+0

'DEBUG_DN' प्रकार' X500 प्रिंसिपल 'है। जो X.500 नाम – Jcs

+0

के लिए एक कंटेनर है, यह उस पर चलने के लिए पर्याप्त कुशल है आवेदन कक्षा? –

3

आधारित Jcs' answer पर, हम रनटाइम पर पता लगाने के लिए इसका उपयोग करते हैं जिन्होंने चल रहे पैकेज का निर्माण किया:

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; 
} 

किसी भी शामिल प्रमाणपत्र के लिए, आपको बस एक बार हैश ढूंढना होगा और इसे सूची में जोड़ना होगा।

"हैश एक बार ढूंढने" का सबसे आसान तरीका केवल modulusHash प्रदर्शित करने वाले स्विच स्टेटमेंट से पहले पॉपअप टोस्ट जोड़ना है, अपने ऐप को संकलित करें, इसे चलाएं, हैश लिखो, टोस्ट कोड हटाएं और हैश जोड़ें सूची में।

@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 बदलने के लिए:

वैकल्पिक रूप से, जब मैं इस लागू किया, मैं एक ही गतिविधि है और एक भी TextView मुख्य लेआउट में आईडी tv साथ साथ एक छोटी सी बॉयलरप्लेट एप्लिकेशन बनाया है, गतिविधि में डाल अपने ऐप के नाम पर), इस मिनी-ऐप को संकलित किया, और एपीके को सभी शामिल डेवलपर्स को भेज दिया, उन्हें अपने देव डिवाइस पर चलाने के लिए कहा और मुझे प्रदर्शित हैश बताएं।

+0

जानकारी के लिए धन्यवाद ... लेकिन प्रमाणपत्र के हैश को कैसे ढूंढें? क्या यह प्रमाणपत्र में 'कुंजी उपनाम' स्ट्रिंग का हैश है? –

+0

@ विजयासी मैंने अपने उत्तर पर विस्तार किया है, अद्यतन संस्करण देखें। – balpha

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^