APK安装时的过滤方式:包名白名单、证书认证
1.定义一些全局变量,文件位置:
Build.java (frameworks\base\core\java\android\os)
/** * 包管理方式名称<br> * whitelist: 白名单方式 * certificate: 证书认证方式 * none: 不进行管理 */ public static String packageManage = "none"; /** * 允许 Launch 显示的 APP 及 APP 白名单 */ public static String[] packageAllow = new String[]{ "com.baidu.searchbox", "com.thinta.product.thintazlib", "com.thinta.product.x4usertool"}; /** * 允许 Launch 显示的 APP的 证书存放路径 */ public static String certificatePath = "/system/etc/security/media.zip";
2.修改安装APK过程,在安装过程添加验证
修改文件的位置:
PackageManagerService.java (frameworks\base\services\core\java\com\android\server\pm)
首先添加一个函数:
private static HashSet<X509Certificate> getTrustedCerts(File keystore) throws IOException, GeneralSecurityException { HashSet<X509Certificate> trusted = new HashSet<X509Certificate>(); if (keystore == null) { return trusted; } ZipFile zip = new ZipFile(keystore); try { CertificateFactory cf = CertificateFactory.getInstance("X.509"); Enumeration<? extends ZipEntry> entries = zip.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); InputStream is = zip.getInputStream(entry); try { trusted.add((X509Certificate) cf.generateCertificate(is)); } finally { is.close(); } } } finally { zip.close(); } return trusted; }
修改的函数:private void installPackageLI(InstallArgs args, PackageInstalledInfo res)
第一处修改:
if(Build.ThintaCust.packageManage.equals("certificate")) tmp_flags = PackageManager.GET_SIGNATURES; final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | (onSd ? PackageParser.PARSE_ON_SDCARD : 0) | tmp_flags; 第二处修改: if(Build.ThintaCust.packageManage.equals("none")){ Log.d("XYP_DEBUG", "packageManage = none \n"); }else if(Build.ThintaCust.packageManage.equals("whitelist")){ Log.d("XYP_DEBUG", "packageManage = whitelist \n"); List<String> list = Arrays.asList(Build.ThintaCust.packageAllow); if(list.contains(pkg.packageName)){ Log.d("XYP_DEBUG", "can install \n"); }else{ Log.d("XYP_DEBUG", "forbid install \n"); res.setError(PackageManager.INSTALL_FAILED_USER_RESTRICTED, "installPackageLI, forbid install"); return; } }else if(Build.ThintaCust.packageManage.equals("certificate")){ int verify_pass = 0; try{ File file = new File(Build.ThintaCust.certificatePath); HashSet<X509Certificate> trusted = getTrustedCerts(file); CertificateFactory cf = CertificateFactory.getInstance("X.509"); for (X509Certificate c : trusted) { String tmp_public_key = c.getPublicKey().toString(); for(Signature sig : pkg.mSignatures) { X509Certificate cert = (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(sig.toByteArray())); String tmp_key = cert.getPublicKey().toString(); if(tmp_public_key.equals(tmp_key)){ verify_pass = 1; break; } } if(verify_pass == 1) break; } if(verify_pass != 1){ Log.d("XYP_DEBUG", "forbid install \n"); res.setError(PackageManager.INSTALL_FAILED_USER_RESTRICTED, "installPackageLI, forbid install"); return; } }catch(FileNotFoundException e){ Log.d("XYP_DEBUG", e.toString()); }catch(CertificateException e){ Log.d("XYP_DEBUG", e.toString()); }catch(IOException e){ Log.d("XYP_DEBUG", e.toString()); }catch(GeneralSecurityException e){ Log.d("XYP_DEBUG", e.toString()); } }
3.证书的压缩方式:
zip -r media.zip media.x509.pem
直接用命令把*.x509.pem 打包成zip文件,然后放到目标板的合适位置;
用第一步中的certificatePath指向存放该zip文件的位置。