2010-09-21 3 views
21

Ich entwickle gerade eine Anwendung, die ziemlich viele persönliche Benutzerinformationen enthält - Dinge wie Facebook-Kontakte, etc ... Nun, eines von Die Dinge, die ich tun möchte (und ziemlich effektiv getan habe), öffnen Teile der Anwendung für Anwendungen von "Drittanbietern", die das eingebaute Interprozesskommunikationsprotokoll (AIDL) von Android verwenden. So weit, ist es gut.Sicherheit auf Signaturebene für Android-Dienste mit mehr als einer erlaubten Signatur implementieren

Hier ist der Haken: Da wir eine ganze Reihe von persönlichen Informationen verarbeiten müssen, müssen wir sehr vorsichtig sein, wer und wie kann man nicht darauf zugreifen; Insbesondere sollten nur "vertrauenswürdige" Anwendungen dazu in der Lage sein. Daher können Sie in der Datei AndroidManifest.xml, in der wir die Dienste deklarieren, eine benutzerdefinierte Berechtigung verwenden. Mein Problem ist das: Ich möchte in der Lage sein, Signatur-Level-Schutz (ähnlich der normalen "Signatur" Berechtigungsstufe), aber mit einem bisschen ein catch:

Ich nicht nur wollen Anwendung signiert mit unserer internen Signatur, um auf die Dienste zugreifen zu können. Ich möchte in der Lage sein, eine Liste von "vertrauenswürdigen Signaturen" & zur Laufzeit (oder wenn es einen besseren Weg, dann vielleicht ein anderes Mal?) In der Lage sein, eingehende Anfragen gegen diese Liste der vertrauenswürdigen Schlüssel zu überprüfen.

Dies würde die Sicherheitsanforderungen auf die gleiche Weise erfüllen wie die normale "Signatur" Berechtigungsstufe Ich denke - nur Programme in der "trusted keys list" könnten auf die Dienste zugreifen, und Schlüssel sind schwer zu fälschen überhaupt möglich?) - aber mit dem zusätzlichen Vorteil, dass wir nicht jede Anwendung unterschreiben müssen, die die APIs mit dem Schlüssel unseres internen Teams nutzt.

Ist dies im Moment in Android möglich? Und wenn ja, gibt es spezielle Anforderungen?

Dank

Antwort

14

Ich habe festgestellt, nun die Antwort auf diese Frage, aber ich werde es im Interesse von niemandem in der Zukunft blicken lassen.

Ich eröffnete eine Diskussion über Android-Security-diskutieren, wo es beantwortet wurde. Link: http://groups.google.com/group/android-security-discuss/browse_thread/thread/e01f63c2c024a767

Kurze Antwort:

private boolean checkAuthorised(){ 
     PackageManager pm = getPackageManager(); 
     try { 
      for (Signature sig : 
       pm.getPackageInfo(pm.getNameForUid(getCallingUid()), 
         PackageManager.GET_SIGNATURES).signatures){ 
       LogUtils.logD("Signature: " + sig.toCharsString()); 
       if (Security.trustedSignatures.get(sig.toCharsString()) != null) { 
        return true; 
       } 
      } 
     } catch (NameNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     LogUtils.logD("Couldn't find signature in list of trusted keys! Possibilities:"); 
     for(String sigString : Security.trustedSignatures.keySet()){ 
      LogUtils.logD(sigString); 
     } 

     /* Crash the calling application if it doesn't catch */ 
     throw new SecurityException(); 

    } 

Wo Security.trustedSignatures ist eine Karte von der Form:

Map<String,String>().put("public key","some description eg. name"); 

Setzen Sie diese Methode in jedem Code, der durch den externen Prozess aufgerufen wird (dh innerhalb Ihrer Schnittstelle). Beachten Sie, dass dies nicht den gewünschten Effekt innerhalb der OnBind() -Methode Ihres RemoteService haben wird.

+0

Ausgezeichnete Informationen, danke. –

+0

können wir nicht einfach den Paketnamen in der Onbind überprüfen und wenn die nicht autorisierte App. Das Paket versucht, auf den Wert zuzugreifen und dann den Nullwert zurückzugeben, der das ibinder-Objekt zurückgibt. –

+1

@kamal_tech_view Leider glaube ich nicht, dass dieser Ansatz wie erwartet funktioniert, da 'onBind()' nur einmal vom Betriebssystem aufgerufen wird (siehe hier: https://groups.google.com/d/msg/ android-security-discuss/4B9jwsAkp2c/QJc4A5FSWCMJ). Hinweis zu dem Hinweis, eine Fabrik zu verwenden, um den empfindlichen Teil des Systems am _first_-Call-Point zu schützen, habe ich nicht untersucht, aber ich denke, dass Sie die Einstellungen auf dem aktuellen 'SecurityManager' überprüfen möchten (Sie könnten finden, dass die Angerufenen Ihre versteckten Felder über Introspektion bekommen können und vermeiden Sie Ihren Scheck). – jelford

1

Große Info Jelford, aber ich würde vorschlagen, anstatt die gesamte Zeichenfolge der Signatur zu speichern, um die SHA-1 des Zertifikats zu speichern/vergleichen, wie in dieser answer from matreshkin gezeigt.

Dies ist ähnlich wie Google handles the Maps Android API, und dies entspricht der Ausgabe über keytool angezeigt.

private boolean checkAuthorized() throws SecurityException { 
    PackageManager pm = getPackageManager(); 
    try { 
     PackageInfo packageInfo = pm.getPackageInfo(pm.getNameForUid(getCallingUid()), 
      PackageManager.GET_SIGNATURES); 
     Signature[] signatures = packageInfo.signatures; 
     byte[] certBytes = signatures[0].toByteArray(); 
     CertificateFactory cf = CertificateFactory.getInstance("X509"); 
     X509Certificate cert = (X509Certificate)cf.generateCertificate(
      new ByteArrayInputStream(certBytes)); 
     MessageDigest md = MessageDigest.getInstance("SHA1"); 
     byte[] encodedCert = md.digest(cert.getEncoded()); 
     String hexString = byte2HexFormatted(encodedCert); 

     Log.d("public certificate SHA-1: " + hexString); 

     String trustedAppName = trustedCerts.get(hexString); 
     if (trustedAppName != null) { 
      Log.d("Found public certificate SHA-1 for " + trustedAppName); 
      return true; 
     } 
    } catch (Exception e) { 
     Log.e(e, "Unable to get certificate from client"); 
    } 

    Log.w("Couldn't find signature in list of trusted certs!"); 
    /* Crash the calling application if it doesn't catch */ 
    throw new SecurityException(); 
} 

public static String byte2HexFormatted(byte[] arr) { 
    StringBuilder str = new StringBuilder(arr.length * 2); 
    for (int i = 0; i < arr.length; i++) { 
     String h = Integer.toHexString(arr[i]); 
     int l = h.length(); 
     if (l == 1) h = "0" + h; 
     if (l > 2) h = h.substring(l - 2, l); 
     str.append(h.toUpperCase()); 
     if (i < (arr.length - 1)) str.append(':'); 
    } 
    return str.toString(); 
} 
+0

Ich würde vorschlagen, dass es keinen Grund gibt, den gesamten öffentlichen Schlüssel nicht zu speichern. SHA-in (oder die Verwendung eines Hash vor der Speicherung) führt zu der Möglichkeit einer Schlüsselkollision (die unwahrscheinlich ist, zufällig zu passieren, leicht von einem bösartigen Dritten verursacht zu werden). Da öffentliche Schlüssel nicht empfindlich sind, gewinnen Sie dadurch nicht wirklich viel. – jelford

+0

Mein Verständnis ist, dass der ganze Sinn der Verwendung einer kryptografischen Hash-Funktion wie SHA-1 darin besteht, es schwierig/undurchführbar zu machen, eine andere Eingabe zu finden, die mit der Ausgabe übereinstimmt. Obwohl es sinnvoll wäre, zu diesem Zeitpunkt zu SHA-2/3 anstatt zu SHA-1 zu wechseln, zeigt das aktuelle Keytool von Java auch SHA-256 des Zertifikats. 'MessageDigest md = MessageDigest.getInstance (" SHA-256 ");' Der Hauptgewinn, den ich sehe, ist in der Lesbarkeit des Codes, der Verwaltung der vertrauenswürdigen Zertifikate und einem gewissen Grad an Verschleierung durch Vermeiden einer langen Zeichenfolge App wird dekompiliert. – PRIZ3

+0

Ich würde vorschlagen, dass es bessere Möglichkeiten gibt, die Lesbarkeit und Schlüsselverwaltung von Schlüsseln zu verbessern, als Ihre Schlüssel zu hashen - setzen Sie sie in geeignete Datenstrukturen und verwenden Sie die verfügbaren Werkzeuge. Der Grund dafür, dass Schlüssel oft als Hashes angezeigt werden, ist, dass sie - wie Sie sagen - einfacher zu lesen und zu erkennen sind. Für kryptografische Zwecke ist es jedoch keine gute Idee, die zusätzlichen N Bits Ihres Schlüssels, die Sie verlieren, zu verwerfen. Öffentliche Schlüssel sind - wie der Name schon sagt - vollständig öffentlich; Es gibt nichts, was man gewinnen könnte, wenn man sie verschleiert oder verdunkelt. – jelford

Verwandte Themen