2013-03-20 17 views
5

Lavoro in un'azienda che produce diverse app, non tutte quelle app hanno la stessa firma o più come se avessimo almeno 5-6 certificati di app per il momento.android: convalidare l'identità del mittente di intent

Abbiamo provato a creare un meccanismo in cui tutte le app della stessa condividono lo stesso dispositivo, Ad esempio se l'utente ha installato dall'app di mercato A e nessuna app verrà generata, se verrà generato un nuovo ID installa l'App A, l'app B deve avere lo stesso id dell'App A (id è solo un UUID generato # 4) ecc ...

Stiamo utilizzando la trasmissione al momento e solo le app con il nostro permesso possono riceverlo trasmetti e rispedisci l'id con un'altra trasmissione (esplicita questa volta). La trasmissione e le risposte sono protette con il nostro permesso a livello di firma, questo naturalmente non aiuta poiché abbiamo più di una firma.

Ho provato a scrivere una trasmissione di intenti e recuperare che può avere il proprio meccanismo di protezione che non sarà limitato a una sola firma ma diversi, il problema è che cose come Binder.getSenderUID() non funzionano per le trasmissioni e ho il mio uid. sembra che non abbia modo di ottenere l'identità del mio snder a meno che non scriva il suo id nell'intento, che NON è qualcosa di cui mi posso fidare in quanto può essere facilmente falsificato. L'uso della crittografia richiede che le app siano provviste di una chiave, che non è protetta ancora una volta, il passaggio a un server per la convalida richiede troppo tempo e sul cellulare non è garantito il successo poiché non è sicuro al 100% che ci sia una rete.

Chiunque ha idea di come si possa ottenere un messaggio sicuro \ convalidato da un'app all'altra? (Tutte le mie app, ma potrebbero avere firme diverse).

risposta

2

dispiace per la risposta tardiva ...

Bind richiede tempo, e ancora più importante, la sua asincrono. Tuttavia, esiste un modo per creare un bind sincrono, presupponendo ovviamente che il servizio che si tenta di contattare sia già avviato al momento. Android consentito per questo più per BroadcastReceivers (che sono asincroni in natura, e quindi non può utilizzare bindService normale) un BroadcastReceiver ha un metodo "peekService".

Se si desidera utilizzarlo senza ascolto di una trasmissione, è possibile da fare:

final IBinder[] b = new IBinder[1]; 
new BroadcastReceiver() { 
    public void onReceive(Context context, Intent intent) { 
     b[0] = peekService(context, intent); 
    } 
}.onReceiver(context, intent); 

IMyInterface i = IMyInterface.Stub.asInterface(b[0); 

nota che non si associa al servizio, in modo da assicurarsi a sbirciare su ogni utilizzo.

+0

questo è un hack, BNUT questo è dannatamente bene, anche Suppongo che il servizio deve essere locale, ma per quanto ne so, BR dovrebbe essere ricevere messaggi dal servizio e inviarlo o inviarlo a un'attività utilizzando un intento, non è destinato a legarsi a un servizio ... quindi avere quel metodo sta violando l'idea di un BR ... – codeScriber

4

Come sempre con una domanda stimolante qui non ho mai ottenere un adeguato, se NESSUNO! ' rispondi, quindi sono costretto a trovarlo da solo.

Il problema con Intents è che non è possibile ottenere il mittente in quanto sono paralleli a mulicast in una rete in cui l'indirizzo del mittente non è importante.

Se desidero ottenere l'UID di sniff ho bisogno di fare un processo "remoto" anche se è locale, invece di usare IPC broadcast ho bisogno di usare AIDL con implementazione IBInder. Una volta che ho un oggetto Binder posso chiamare il mio servizio getCallingUid() e ottenere l'uid del chiamante, questo mi permetterà di chiedere a PackageManager di darmi il suo certificato pubblico (senza chiedere il processo stesso, chiedo al sistema operativo) e confrontarlo con una serie di certificati che ho preparato in anticipo nell'apk.

L'applicazione chiamante sull'altro lato (l'altro processo che mi invia il suo ID) deve solo utilizzare il metodo bindService (servizio, conn, flag) per collegarsi a me. Lo svantaggio di questo approccio è naturalmente il processo che richiede tempo, Bind richiede tempo, è una chiamata asincrona che passa attraverso il kernel e non è veloce come vincolante per un servizio locale. Inoltre, poiché potrei avere diverse applicazioni, ho bisogno di sincronizzare l'accesso con il mio ID interno in modo che solo la prima chiamata vincolante che non ha esito negativo verrà impostata e ID per me. Ho ancora bisogno di controllare se posso usare il metodo Messanger che impedisce i problemi multi-thread.

Si spera che questo aiuti qualcun altro.

0

Come già indicato, il binding è probabilmente la soluzione migliore. Tuttavia, si potrebbe considerare di passare a un'attività anziché a BroadcastReceiver, quindi è possibile utilizzare getCallingActivity(), assumendo che si sia avviato con startActivityForResult().

dichiari di attività come segue per rendere più "silenzioso" come un BroadcastReceiver:

<activity 
    android:name=".FauxReceiver" 
    android:theme="@android:style/Theme.NoDisplay" 
    android:excludeFromRecents="true" 
    android:noHistory="true" 
> 
    <intent-filter> 
     ... 
    </intent-filter> 
</activity> 

Ispirazione: How to get the sender of an Intent?

+1

Stiamo lavorando su una libreria per verificare il mittente e il destinatario di 'Intent's che usa questa tecnica per iniziare, dal momento che è la più semplice. Puoi saperne di più qui https://dev.guardianproject.info/projects/trustedintents/wiki –

+0

@ Hans-ChristophSteiner Sembra buono. È strano che non abbiano incluso il mittente in tutte le invocazioni di Intent (non solo quelle che richiedono un risultato) in quanto il costo sarebbe presumibilmente minimo. –

-1

ero alla ricerca di un modo per verificare il nome del pacchetto dell'applicazione che ha inviato il intento ricevuto dal mio filtro intent. Quella attività nella mia app che gestisce il filtro intent richiede che il mittente dell'intenzione includa l'id del processo in un campo Intent Extras. La mia attività di ricezione può quindi ottenere il nome del pacchetto dell'applicazione associato da ActivityManager.

Ecco un codice di esempio che ho trovato mentre si spostava su StackOverflow.

Costanti necessari per entrambe le applicazioni

public static final String EXTRA_APP_ID; 
public static final String ACTION_VERIFY = "com.example.receivingapp.action.VERIFY"; 

Calling Attività

Intent verifyIntent = new Intent(); 
    verifyIntent.setAction(Consts.ACTION_VERIFY); 
    verifyIntent.putExtra(EXTRA_APP_ID, android.os.Process.myPid()); 
    // Verify that the intent will resolve to an activity 
    if (verifyIntent.resolveActivity(getPackageManager()) != null) { 
    startActivityForResult(verifyIntent, Consts.REQUEST_VERIFY); 
    } else { 
     Log.d(TAG, "Application not found."); 
    } 

Ricezione App

manifesto

 <activity 
      android:name="com.example.receivingapp.ReceivingActivity" 
      android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="com.example.receivingapp.VERIFY" /> 
       <category android:name="android.intent.category.DEFAULT" /> 
      </intent-filter> 
     </activity> 

ReceivingActivity

if (getIntent().hasExtra(OnyxCoreConsts.EXTRA_APP_ID)) { 
    string appName = null; 
    // Resolve intent 
    if (getIntent().getAction().equals(ACTION_VERIFY) {  
     int appPid = getIntent().getIntExtra(EXTRA_APP_ID, -1); 
     if (-1 != mAppPid) { 
      appName = Utils.getAppNameByPID(mContext, mAppPid); 
     } 
     if (null != appName && !"".equalsIgnoreCase(appName)) { 
       // Do something with the application package name 
     } 
    } 
} 

Utils classe

public static String getAppNameByPID(Context context, int pid){ 
     ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 

     for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { 
      if (processInfo.pid == pid) { 
       return processInfo.processName; 
      } 
     } 
     return ""; 
    } 
Problemi correlati