2013-03-20 2 views
5

Я работаю в компании, которая выпускает несколько приложений, не все те приложения имеют одну и ту же подпись или больше, как будто у нас есть как минимум 5-6 сертификатов приложений.android: подтвердите идентификатор отправителя намерения

Мы попытались создать механизм, в котором все приложения компаньона на одном и том же устройстве будут одинаковыми: Например, если пользователь установил с рынка приложение A и приложение не установлено, будет создан новый идентификатор, если теперь он устанавливает приложение A, приложение B должно иметь тот же идентификатор, что и приложение A (идентификатор - только сгенерированный тип UUID № 4) и т. д.

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

Я попытался написать намерение трансляции и восстановления, у которого может быть свой собственный механизм защиты, который не будет ограничен только одной подписью, но несколько, проблема в том, что такие вещи, как Binder.getSenderUID(), не работают для трансляций и я получаю свой собственный uid. похоже, что у меня нет способа получить личность моего snder, если он сам не записывает свой идентификатор в намерении, что НЕ является чем-то, чему я могу доверять, поскольку его можно легко подделать. Использование шифрования требует, чтобы приложения поставлялись с ключом на них, который еще не защищен, обращение к серверу для проверки требует слишком много времени, а на мобильном телефоне не гарантируется успех, поскольку на 100% не существует сети.

Кто-нибудь знает, как получить достоверное \ безопасное сообщение из одного приложения в другое? (Все мои приложения, но могут иметь разные подписи).

ответ

2

Извините за поздний ответ ...

Bind занимает много времени, и, что более важно, его асинхронно. Однако есть способ сделать синхронное связывание - если, конечно, служба, с которой вы пытаетесь связаться, уже запущена в то время. Android разрешил это для BroadcastReceivers (которые носят асинхронный характер и, следовательно, не могут использовать обычный bindService), BroadcastReceiver имеет метод «peekService».

Если вы хотите использовать его без прослушивания радиопередач, вы можете, выполнив:

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

обратите внимание, что вы не связываться с сервисом, поэтому убедитесь, что поглядеть на каждом использовании.

+0

это хак, bnut это чертовски хорошо, и я предполагаю, что сервис должен быть локальным, однако, насколько я знаю, BR должны получать сообщения от службы и отправить его обратно или отправить его на мероприятие, используя намерение, оно не предназначено для привязки к службе ... так что этот метод действительно нарушает идею BR ... – codeScriber

4

Как всегда со сложным вопросом здесь я никогда не получаю должного, если ЛЮБОЙ! " ответ, поэтому я вынужден сам найти его.

Проблема с намерениями заключается в том, что получить отправителя невозможно, поскольку они являются параллельными с мулистатом в сети, где адрес отправителя не важен.

Если я хочу получить UID от snder, мне нужно сделать «удаленный» процесс, даже если он локальный, вместо использования IPC вещания мне нужно использовать AIDL с внедрением IBInder. Как только у меня есть объект Binder, я могу позвонить в свою службу getCallingUid() и получить uid вызывающего, это позволит мне попросить PackageManager предоставить мне этот открытый сертификат (без запроса самого процесса, я спрашиваю ОС) и сравните его с набором сертификатов, которые я заранее подготовил в apk.

Вызывающее приложение с другой стороны (другой процесс, который отправляет мне его ID) просто использует метод bindService (service, conn, flags) для привязки ко мне. Недостатком этого подхода является, конечно же, длительный процесс, Bind требует времени, это асинхронный вызов, который проходит через ядро ​​и не так быстро, как привязка к локальной службе. Более того, поскольку у меня может быть несколько приложений, мне нужно синхронизировать доступ к внутреннему ID, поэтому только первый вызов привязки, который не сработает, будет установлен и ID для меня. Мне все еще нужно проверить, могу ли я использовать метод Messenger, который предотвращает проблемы с несколькими потоками.

Надеюсь, это поможет кому-то еще.

0

Как уже говорилось, связывание, вероятно, является лучшим решением для этого. Тем не менее, вы можете рассмотреть возможность переключения на активность, а не на BroadcastReceiver, тогда вы можете использовать getCallingActivity(), предполагая, что вы запустили с startActivityForResult().

Признаться активность следующим образом, чтобы сделать это «молчание», как BroadcastReceiver:

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

Вдохновение: How to get the sender of an Intent?

+1

Мы работаем над библиотекой для проверки отправителя и получателя «Intent's», который использует эту технику для начала, поскольку ее простейшая. Вы можете узнать больше здесь https://dev.guardianproject.info/projects/trustedintents/wiki –

+0

@ Hans-ChristophSteiner Выглядит хорошо. Странно, что они не включали отправителя во все вызовы Intent (а не только те, которые требуют результата), поскольку стоимость предположительно была бы минимальной. –

-1

Я искал способ проверки имени пакета приложения, отправляющего полученное моим фильтром намерения. Эта активность в моем приложении, которая обрабатывает фильтр намерений, требует, чтобы отправитель намерения включал свой идентификатор процесса в поле Intent Extras. Затем моя получающая активность может получить связанное имя пакета приложений из ActivityManager.

Вот пример кода, который я нашел при перемещении через StackOverflow.

Константы, необходимые как для приложения

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

Calling активность

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."); 
    } 

Прием App

манифеста

 <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 класс

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 ""; 
    } 
Смежные вопросы