2013-08-24 3 views
0

Я создаю приложение для Android, которое общается с интернет-сервисом. Я планирую выпустить исходный код приложения на GitHub. Для моей производственной версии, которая будет использовать мой личный веб-сервис, я хочу разрешить подключение только моей подписываемой цифровой подписью apk.Подтвердить идентификатор APK с keystore

Можно ли запросить хранилище ключей APK и подтвердить имя пользователя/пароль из этого хранилища ключей?

Если это невозможно, как еще я могу создать эту функцию?

Edit:

Я прочитал в классе Certificate Это выглядит, как я мог бы быть в состоянии пользовательских государственных/частных ключей для подтверждения идентичности. Но я все еще не уверены в реализации

+0

имя пользователя/пароль в хранилище ключей? Если я правильно вас понимаю, вы хотите ограничить свой веб-сервис подпиской, подписанной вами? – dst

+0

Правильно, сейчас единственный способ, который я мог себе представить, - подтвердить, что apk была подписана мной с помощью моего имени пользователя/пароля. – KDEx

+0

Вы подписываетесь с именем пользователя? Как? – dst

ответ

1

я использую это -

static public String getPackageFingerPrint(Context ctx) { 
     PackageManager pm = ctx.getPackageManager(); 
     String packageName = ctx.getPackageName(); 
     int flags = PackageManager.GET_SIGNATURES; 

     PackageInfo packageInfo = null; 

     try { 
       packageInfo = pm.getPackageInfo(packageName, flags); 
     } catch (NameNotFoundException e) { 
       return ""; 
     } 
     Signature[] signatures = packageInfo.signatures; 

     byte[] cert = signatures[0].toByteArray(); 

     InputStream input = new ByteArrayInputStream(cert); 

     CertificateFactory cf = null; 
     try { 
       cf = CertificateFactory.getInstance("X509"); 


     } catch (CertificateException e) { 
       return ""; 
     } 
     X509Certificate c = null; 
     try { 
       c = (X509Certificate) cf.generateCertificate(input); 
     } catch (CertificateException e) { 
       return ""; 
     } 


     try { 
      MessageDigest md = MessageDigest.getInstance("SHA1"); 
      byte[] publicKey = md.digest(c.getPublicKey().getEncoded()); 


      StringBuffer hexString = new StringBuffer(); 
      for (int i=0;i<publicKey.length;i++) { 
       String appendString = Integer.toHexString(0xFF & publicKey[i]); 
       if(appendString.length()==1)hexString.append("0"); 
       hexString.append(appendString); 
       } 


      return hexString.toString(); 

     } catch (NoSuchAlgorithmException e1) { 
      return ""; 
     } 
    } 

Проблема, которую я вижу с вашим подходом является то, что кто-то может определить пакет отпечатков пальцев или пакет и отправить его на свой веб-сервис , Лучшей возможностью было бы использовать механизм ответа на запрос: ваш веб-сервис отправляет вам уникальный токен сеанса, который ваше приложение шифрует или переваривает с использованием общего алгоритма, а затем отправляет этот зашифрованный токен обратно в вашу службу для проверки. Конечно, вы не захотите публиковать этот алгоритм для github.

+0

Этот метод выглядит действительно полезным.Однако за то, что вы предлагаете по поводу использования общего алгоритма, я не решаюсь поставить какой-либо «секрет» в apk, так как это настолько тривиально декомпилировать и выяснить, как закодирован почти любой раздел приложения. – KDEx

+0

Это правда, конечно - - вы можете немного запутать свой код, но, в конце концов, нет такой вещи, как защищенная Java. Но даже если вы используете ключ или отпечаток пальца, как только он перейдет через провод, это честная игра. – 323go

0

Вы не можете ограничить веб-сервис apks, подписанный определенным ключом.

Подпись вашего apk проверяется операционной системой Android и напрямую не используется совместно с веб-сервисами, к которым подключается устройство. Даже если вы прочтете свою подпись из хранилища ключей и отправите ее вместе с запросами, злоумышленник может просто отправить одну и ту же подпись (например, тот же поток байтов), не имея доступа к вашему закрытому ключу. Ему просто нужно захватить подписанный apk, прочитать байты из хранилища ключей (или послушать законный запрос) и испортить данные.

Вам необходимо будет подписать индивидуальные запросы на уровень безопасности. Но если вы сохраняете закрытый ключ в версиях выпуска (ключ, не распределенный по gitHub), и подписывайте запросы с использованием этого ключа, вы небезопасны, так как закрытый ключ распространяется как часть вашего apk и, таким образом, может быть легко извлечен.

В любом случае ваш API может получить доступ другими apks.

Однако может быть другой способ ограничить ваш API, например, с помощью лицензионных токенов и т. Д. В этом случае вам, вероятно, не понравится, если пользователь сам построит apk, если у него есть действительная лицензия маркер. Если токен лицензии используется и распространяется, вы можете реагировать на большой объем трафика на этом токен лицензии и, например, блокировать его из дальнейших запросов. Поскольку я не использую Google Play, я не уверен, насколько они могут быть проверены с вашего сервера, но, возможно, application licensing portal является хорошей отправной точкой для поиска подходящих токенов.