在具有多个允许签名的Android服务上实现签名级安全性

我正在开发一个应用程序,其中包含了很多个人用户信息,比如Facebook联系人等等。现在,我希望能够做的事情之一(相当有效)使用Android内置的进程间通信协议(AIDL),将部分应用程序开放给“第三方”应用程序。 到现在为止还挺好。

这里有一个问题:因为我们涉及处理相当多的个人信息,所以我们必须非常小心谁可以访问它, 具体而言,只有“可信”应用程序才能够这样做。 所以自然而然的做法是在我们声明服务的AndroidManifest.xml文件中使用自定义权限。 我的问题是这样的:我想能够制定签名级别的保护(类似于正常的“签名”权限级别),但有一点问题:

不仅希望用我们的内部签名签名的应用程序能够访问这些服务。 我希望能够在运行时(或者如果有更好的方法,那么也许是其他时间?)build立一个“可信签名”列表,能够检查这个可信密钥列表的入局请求。

这与我认为的正常的“签名”权限级别一样满足安全限制 – 只有“可信密钥列表”上的程序才能够访问这些服务,并且密钥很难被欺骗(如果可能的话, ) – 但是还有额外的好处,就是我们不需要用我们内部团队的密钥来签署每个使用API​​的应用程序。

这在Android目前可能吗? 如果是这样,有什么特殊要求吗?

谢谢

Related of "在具有多个允许签名的Android服务上实现签名级安全性"

我现在已经find了这个问题的答案,但是为了未来的任何人,我会放弃这个答案。

我打开了关于android安全性的讨论 – 讨论它的答案。 链接: http : //groups.google.com/group/android-security-discuss/browse_thread/thread/e01f63c2c024a767

简短的回答:

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

其中Security.trustedSignatures是一个窗体的地图:

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

把这个方法放到外部进程正在调用的代码中(即在你的接口中)。 请注意,这不会在RemoteService的onBind()方法内产生所需的效果。

伟大的信息jelford,但我会build议,而不是存储签名的整个string,以存储/比较证书的SHA-1 从matreshkin这个答案中显示 。

这与Google处理Maps Android API的方式类似,这将与通过keytool显示的输出相匹配。

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