Как программно установить сертификат CA на Android без взаимодействия с пользователем - программирование
Подтвердить что ты не робот

Как программно установить сертификат CA на Android без взаимодействия с пользователем

Я пытаюсь установить сертификаты, не запрашивая пользователя. Я знаю, что это не хорошая практика, а то, что хочет PM.

Используя KeyChain.createInstallIntent(), я могу заставить Android запустить диалог установки сертификата, вызвав startActivity. Однако, когда я передаю намерение sendBroadcast, ничего не происходит. Может быть, платформа не поддерживает это по соображениям безопасности?

String CERT_FILE = Environment.getExternalStorageDirectory() + "/test/IAT.crt";
Intent intent = KeyChain.createInstallIntent();
try {
    FileInputStream certIs = new FileInputStream(CERT_FILE);
    byte [] cert = new byte[(int)certFile.length()];
    certIs.read(cert);
    X509Certificate x509 = X509Certificate.getInstance(cert);
    intent.putExtra(KeyChain.EXTRA_CERTIFICATE, x509.getEncoded()); 
    intent.putExtra(KeyChain.EXTRA_NAME, "IAT Cert");
    EapActivity.this.startActivityForResult(intent, 0);  // this works but shows UI
    EapActivity.this.sendBroadcast(intent);  // this doesn't install cert
} catch (IOException e) {
4b9b3361

Ответ 1

Вы можете устанавливать сертификаты только при наличии системных привилегий. Отображение диалогового окна подтверждения является преднамеренным, так как доверенные сертификаты могут иметь серьезные последствия - Android может с радостью открывать фишинговые сайты без предупреждения и т.д. Тем не менее, диалог в ICS/JB довольно плох - он не говорит вам, что сертификат, который вы устанавливаете, и кто его выпустил, просто это сертификат CA, который является очевидным.

Итак, используйте общедоступный API KeyChain и используйте startActivity(), чтобы получить диалоговое окно подтверждения или предустановить устройства, прежде чем обращаться с ними для пользователей.

Обновление. В Android 4.4 у DevicePolicyManager есть скрытый API (installCaCert), который позволяет устанавливать сертификаты молча. Вам нужно разрешение MANAGE_CA_CERTIFICATES, которое signature|system, поэтому все еще не выполнимо для установленных пользователем приложений.

Ответ 2

Используя KeyChain.createInstallIntent(), я могу заставить Android запустить диалог установки сертификата, вызвав startActivity. Однако, когда я передаю намерение sendBroadcast, ничего не происходит.

Мало, если любые объекты Intent, которые вы передадите в startActivity(), будут работать с sendBroadcast(). Они являются независимыми каналами шины квази-сообщений, которая является системой Intent.

Ответ 3

Для разработчиков, не относящихся к системным приложениям, простой ответ заключается в том, что он не может быть выполнен без взаимодействия с пользователем.

Для разработчиков системного приложения я нашел следующее решение: NB вы должны запустить приложение с идентификатором пользователя системы и подписать приложение с помощью системного ключа или служба отклонит ваши попытки установить сертификат.

Шаг 1 - создать интерфейс

Создайте новый пакет в своем проекте: android.security, затем скопируйте IKeyChainService.aidl в этот пакет.

Шаг 2 - привязка к сервису и установке сертификата

В действии приведен пример установки сертификата CA:

public class KeyChainTest extends Activity {

    private final Object mServiceLock = new Object();
    private IKeyChainService mService;
    private boolean mIsBoundService =false;

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override public void onServiceConnected(ComponentName name, 
                                                    IBinder service) {
            synchronized (mServiceLock) {
                mService = IKeyChainService.Stub.asInterface(service);
                mServiceLock.notifyAll();
                try {

                    byte[] result = YOUR_CA_CERT_AS_BYTE_ARRAY

                    //The next line actually installs the certificate
                    mService.installCaCertificate(result);

                } catch (Exception e) {
                    //EXception handling goes here
                }
            }
        }

        @Override public void onServiceDisconnected(ComponentName name) {
            synchronized (mServiceLock) {
                mService = null;
            }
        }
    };

    private void bindService() {
        mIsBoundService = bindService(new Intent(IKeyChainService.class.getName()),
                mServiceConnection,
                Context.BIND_AUTO_CREATE);
    }

    private void unbindServices() {
        if (mIsBoundService) {
            unbindService(mServiceConnection);
            mIsBoundService = false;
        }
    }

    @Override public void onDestroy () {
        unbindServices();
    }


    @Override
    protected void onStart() {
        super.onStart();
        // Bind to KeyChainService
        bindService();
    }
}

Я надеюсь, что это кому-то поможет - мне потребовалось много времени, чтобы решить эту проблему:)

Ответ 4

Если у вас есть привилегия root, вы можете скопировать файл сертификатов в /data/misc/user/0/cacerts-added/

Ответ 5

Только системное пользовательское приложение может тихо установить сертификат ЦС. Тем не менее, на Lollipop компания Google внедрила API-интерфейс управления сертификатами через DevicePolicyManager, но вы должны либо быть владельцем профиля Android-for-Work, либо владельцем устройства.

Ответ 6

Основываясь на ответе @ospider, мне удалось успешно установить сертификат следующим образом:

adb shell mkdir -p /data/misc/user/0/cacerts-added
adb push certificate.cer /data/misc/user/0/cacerts-added/807e3b02.0

# Maybe these two lines are not strictly necessary...
adb shell chmod 644 /data/misc/user/0/cacerts-added/807e3b02.0
adb shell chown system:system /data/misc/user/0/cacerts-added/807e3b02.0

Я получил имя скопированного файла (807e3b02.0), установив вручную сертификат, который я хотел автоматизировать, и увидев, как Android его сохранил (с помощью adb shell ls -l/data/misc/user/0/cacerts-added/)


Надеюсь, это поможет.

С уважением.

Ответ 7

Основываясь на этом и всех связанных ресурсах (отличных!), Я пробовал 2 подхода для установки сертификата CA в систему Android CA Store. Я работаю над Android Pie.

  1. API Keystore, использующие setCertificateEntry (я запускаю системное приложение), но это молча завершается ошибкой... мой сертификат не виден в учетных данных доверенных (или пользователей).
  2. Создание моего приложения владельцем устройства, а затем использование DevicePolicyManager api installCaCert() Это работает, но показывает мой сертификат в разделе "Пользователь" вместо "Системные сертификаты".

Есть идеи, что я могу упустить?