3

对于我正在开发的应用程序,我需要能够在他或她不知情的情况下安装 CA 和用户证书和私钥。

我将拥有完整的系统特权,并且可以公平地假设用户在此之前将拥有密码。如果是 CA 证书,我将拥有 x509,如果是用户证书 + 私钥文件,我将拥有 pk12,如果是用户证书 + 私钥,我将拥有密码。我需要这样做才能自动设置 WPA-EAP wifi 配置,并且最好我希望在员工不必注意任何事情的情况下发生这种情况。

如果有人也知道如何列出所有已安装的证书,我将不胜感激。

我已经检查了一整天,并使用keystore_cli进行了一些测试,但没有成功,而且我还通读了 CertInstaller 代码,但没有得到任何更明智的结果。那里的所有东西都是包范围的,所以我不能直接调用这些方法,+ 它似乎将东西发送到更远的地方 com.android.settings"、"com.android.settings.CredentialStorage"。

任何建议都会非常棒。


编辑对于那些想知道的人,这是我使用 CA 证书的方式。应用程序需要能够以系统用户身份运行(android:sharedUserId="android.uid.system"在 android manifest 中)。

            // Android...why do you enjoy doing my life so difficult...
            try {
                Class<?> keyStoreClass = WifiConfiguration.class.getClassLoader().loadClass("android.security.KeyStore");

                Method getInstanceMethod = keyStoreClass.getMethod("getInstance");
                Object keyStore = getInstanceMethod.invoke(null);

                Log.d("DeviceManager", "Got keystore" + keyStore.toString());

                // Put(Key, Value)
                Method putCertificateMethod = keyStoreClass.getMethod("put", String.class, byte[].class);

                Log.d("DeviceManager", "Putting...");

                RandomAccessFile file = new RandomAccessFile("/data/ca.crt", "r");
                byte[] b = new byte[(int)file.length()];
                file.read(b);
                byte[] cacert = b;

                Log.d("DeviceManager", "Certificate is bytes long: " + b.length);

                putCertificateMethod.invoke(keyStore, "CACERT_name", cacert);


            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
4

2 回答 2

1

幸运的是,这在库存设备上是不可能的。否则,任何流氓应用都可以在未经用户同意的情况下安装 CA 证书。如果您有少量设备,则可能需要预先配置它们。至于 PKCS#12 文件,它们受密码保护,因此需要有人输入密码。

不确定“完全系统权限”是什么意思,但是如果您可以将应用程序与平台代码链接并使用系统证书对其进行签名,则可以KeyChainService直接调用方法。这将允许您安装证书。此外,CA 证书只是存储为文件,因此您可以将它们复制到正确的位置。这里的一些细节:http: //nelenkov.blogspot.jp/2011/11/ics-credential-storage-implementation.html

于 2012-06-22T03:26:20.000 回答
0

以下方法将使用 CA 证书和用户证书配置 WPA/EAP-TLS wifi 配置。您也可以将它用于其他 EAP 配置。

公共静态无效createEapConfig(上下文上下文,字符串ssid,字符串密码,布尔自动连接,布尔隐藏网络,
                                   整数 eapMethod、整数 phase2、字符串身份、字符串匿名身份、字符串 caCertificateData、
                                   字符串 clientCertificateData,字符串 clientCertPass) {
    if (ssid == null || eapMethod == null) {
        返回;
    }
    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    布尔连接 = 自动连接;
    布尔 isWifiReceiverRegistered = false;
    尝试 {
        Logger.logEnteringOld();

        WifiConfiguration 配置 = 新 WifiConfiguration();
        配置.SSID = "\"" + ssid + "\"";
        config.hiddenSSID = hiddenNetwork;//false; //隐藏网络总是设置为假。
        config.status = WifiConfiguration.Status.ENABLED;
        config.priority = 40;
        尝试 {
            wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class).invoke(wifiManager, config, false);
        } 捕捉(异常 e){
            Logger.logError(e);
        }
        Settings.isWifiHotspotEnabled(false);
        如果(!wifiManager.isWifiEnabled()){
            wifiManager.setWifiEnabled(true);
            线程.sleep(5000);
        }

        如果(连接){
            lastActNetId = wifiManager.getConnectionInfo().getNetworkId();
            wifiManager.disableNetwork(lastActNetId);
            wifiManager.disconnect();
        }
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);

        // 设置默认值
        if (phase2 == null) phase2 = WifiEnterpriseConfig.Phase2.NONE;
        如果(身份==空)身份=“”;
        if (anonymousIdentity == null) 匿名身份 = "";
        if (caCertificateData == null) caCertificateData = "";
        if (clientCertificateData == null) clientCertificateData = "";
        if (Build.VERSION.SDK_INT >= 18) {
            如果(Util.isNullOrEmpty(密码)){
                config.enterpriseConfig.setPassword(密码);
            }

            config.enterpriseConfig.setEapMethod(eapMethod);

            如果(阶段2!= null){
                config.enterpriseConfig.setPhase2Method(phase2);
            }
            if (!Util.isNullOrEmpty(identity)) {
                config.enterpriseConfig.setIdentity(identity);
            }
            如果(!Util.isNullOrEmpty(anonymousIdentity)){
                config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
            }
            输入流是 = null;
            如果(!Util.isNullOrEmpty(caCertificateData)){
                尝试 {
                    byte[] decodedCaCert = Base64.decode(caCertificateData);
                    //is = new FileInputStream(Environment.getExternalStorageDirectory()+"/local-root(1).cer" );
                    CertificateFactory cf = CertificateFactory.getInstance("X.509");
                    尝试 {

                        is = new ByteArrayInputStream(decodedCaCert);
                        X509Certificate caCert = (X509Certificate) cf.generateCertificate(is);
                        config.enterpriseConfig.setCaCertificate(caCert);
                    } 捕捉(CertificateException ex){
                        Logger.logError(ex);
                    } 最后 {
                        如果(是!= null){
                            is.close();
                        }
                    }
                } 捕捉(可投掷的 t){
                    Logger.logError(t);
                }
            }
            if (!Util.isNullOrEmpty(clientCertificateData) && !Util.isNullOrEmpty(clientCertPass)) {
                尝试 {
                    byte[] decodeClientCert = Base64.decode(clientCertificateData);
                    KeyStore p12 = KeyStore.getInstance("pkcs12");
                    is = new ByteArrayInputStream(decodedClientCert);
                    //is = new FileInputStream(Environment.getExternalStorageDirectory()+"/createdDERCert(1).pfx");
                    p12.load(is, clientCertPass.toCharArray());
                    枚举别名 = p12.aliases();
                    for(字符串别名:Collections.list(别名)){

                        如果(别名 == null){
                            继续;
                        }

                        PrivateKey privateKey = (PrivateKey) p12.getKey(alias, clientCertPass.toCharArray());
                        if (privateKey == null) {
                            继续;
                        }

                        X509Certificate clientCert = (X509Certificate) p12.getCertificate(alias);

                        if (clientCert != null) {
                            config.enterpriseConfig.setClientKeyEntry(privateKey, clientCert);
                        }
                    }
                } 捕捉(可投掷的 t){
                    Logger.logError(t);
                } 最后 {
                    如果(是!= null){
                        尝试 {
                            is.close();
                        } 捕捉(IOException e){
                            e.printStackTrace();
                        }
                    }
                }
            }
        }

        int networkId = -1;
        networkId = wifiManager.addNetwork(config);

        wifiManager.enableNetwork(networkId, true);
        wifiManager.saveConfiguration();

        如果(连接){
            wifiManager.reconnect();
            IntentFilter filter = new IntentFilter();
            filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
            Settings.cntxt.registerReceiver(wifiReceiver, filter);
            isWifiReceiverRegistered = true;
            线程.sleep(15000);
        }
    } 捕捉(InterruptedException 即){
        if (NetworkStateReceiver.activeConnection(Settings.cntxt)) {
            lastActNetId = wifiManager.getConnectionInfo().getNetworkId();
        }
    } 捕捉(异常前){
        Logger.logError(ex);
    } 最后 {
        //注销wifi状态接收器
        if (connect && isWifiReceiverRegistered) {
            isWifiReceiverRegistered = 假;
            Settings.cntxt.unregisterReceiver(wifiReceiver);
        }
    }

    Logger.logEnteringOld();
}

于 2017-12-21T12:09:04.643 回答