# Клиентский SSL-сертификат на Android и iOS


<!--more-->

Эта инструкция -- продолжение статьи
[Настройка аутентификации по SSL сертификатам клиентов на Nginx]({{< relref "client-certificate-authentication-nginx" >}}).
У вас есть файл `user1.p12` с сертификатом и закрытым ключом и пароль от него. Осталось установить его на телефон
или планшет.

На мобильных системах сертификат ставится в систему, а браузеры берут его оттуда. Но поддерживают это не все
браузеры:

| Система | Работает | Не работает |
|---|---|---|
| Android | Chrome, Яндекс Браузер, Edge, Samsung Internet, Firefox 138 и новее | Firefox до версии 138 |
| iOS / iPadOS | Safari | Chrome, Firefox, Edge и другие сторонние браузеры |

{{< admonition type=info open=true >}}
**Если файл создан в OpenSSL 3.** Старые версии Android и iOS могут не принять `.p12` с алгоритмами шифрования,
которые OpenSSL 3 использует по умолчанию, и сообщить о неверном пароле. В этом случае пересоздайте файл с
параметром `-legacy`:

```shell
openssl pkcs12 -export -legacy -in user1.crt -inkey user1.key -out user1.p12
```
{{< /admonition >}}


## Android

### Через настройки

Скопируйте файл `user1.p12` на устройство -- через USB, облако или мессенджер -- и сохраните его в **Загрузки**.
Для установки сертификата на устройстве должна быть включена блокировка экрана (PIN-код, графический ключ или
пароль).

Названия пунктов меню отличаются у разных производителей и версий Android. Быстрее всего найти нужный пункт поиском
по настройкам: введите «сертификат». На Pixel и в «чистом» Android 14--16 путь такой:

1. **Настройки → Безопасность и конфиденциальность → Другие настройки безопасности → Шифрование и учетные данные**.
2. **Установка сертификата → Сертификат пользователя VPN и приложений**.
3. Выберите файл `user1.p12` и введите пароль от него.
4. Задайте имя сертификата -- под ним он будет отображаться в списке -- и нажмите **ОК**.

На Samsung путь похожий: **Настройки → Безопасность и конфиденциальность → Другие параметры безопасности →
Установка из памяти устройства → Сертификат пользователя VPN и приложений**.

При первом заходе на сайт Chrome покажет окно **Выбор сертификата** -- выберите установленный и нажмите
**Выбрать**.

Посмотреть и удалить сертификат: **Шифрование и учетные данные → Учетные данные пользователя**, нажмите на
сертификат → **Удалить**.

### Через консоль (adb)

Android не позволяет установить клиентский сертификат без подтверждения пользователя -- это можно сделать только
через систему управления устройствами (MDM). Но с компьютера можно скопировать файл и сразу открыть нужный раздел
настроек. Нужна включенная **Отладка по USB** в настройках для разработчиков.

```shell
adb push user1.p12 /sdcard/Download/
adb shell am start -a android.settings.SECURITY_SETTINGS
```

Дальше -- шаги из предыдущего раздела на экране телефона.

### Firefox на Android

Firefox для Android начиная с версии 138 использует сертификаты, установленные в систему. Отдельно ставить
сертификат в Firefox не нужно. Если окно выбора сертификата не появилось с первого раза, обновите страницу.


## iOS и iPadOS

На iPhone и iPad клиентский сертификат может использовать **только Safari** (и приложения Apple, например Почта).
Сторонние браузеры -- Chrome, Firefox, Edge -- не имеют доступа к сертификатам, установленным через профили, это
ограничение iOS.

### Через настройки

1. Передайте файл `user1.p12` на устройство: через AirDrop, по почте или через приложение **Файлы**.
   Откройте файл -- iOS сообщит, что **Профиль загружен**.
2. Откройте **Настройки**. Вверху появится пункт **Профиль загружен** -- нажмите на него. Если пункта нет:
   **Настройки → Основные → VPN и управление устройством**, профиль в разделе **Загруженный профиль**.
3. Нажмите **Установить**, введите код-пароль устройства, затем снова **Установить**.
4. Введите пароль от файла `.p12` и нажмите **Далее → Готово**.

При заходе на сайт Safari предложит выбрать сертификат.

Удалить сертификат: **Настройки → Основные → VPN и управление устройством**, выберите профиль → **Удалить профиль**.

### Через профиль конфигурации и Apple Configurator

Если сертификатов много или их нужно раздавать централизованно, удобнее упаковать `.p12` в профиль конфигурации
`.mobileconfig`. Такой профиль можно отправить по почте, выложить на сайт, установить через Apple Configurator или
через MDM.

Скрипт `mobileconfig.sh` создает профиль из файла `.p12`. Работает в Linux и macOS:

```shell
#!/bin/sh

USER=$1
P12="$USER.p12"
ORG=com.example

if [ -z "$1" ]; then
  echo $0 \"User Name\"
  exit 1
fi

DATA=$(base64 < "$P12" | tr -d '\n')
UUID1=$(uuidgen)
UUID2=$(uuidgen)

cat > "$USER.mobileconfig" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>PayloadContent</key>
  <array>
    <dict>
      <key>PayloadType</key><string>com.apple.security.pkcs12</string>
      <key>PayloadVersion</key><integer>1</integer>
      <key>PayloadIdentifier</key><string>$ORG.client-cert.$UUID1</string>
      <key>PayloadUUID</key><string>$UUID1</string>
      <key>PayloadDisplayName</key><string>$USER</string>
      <key>PayloadCertificateFileName</key><string>$P12</string>
      <key>PayloadContent</key><data>$DATA</data>
    </dict>
  </array>
  <key>PayloadType</key><string>Configuration</string>
  <key>PayloadVersion</key><integer>1</integer>
  <key>PayloadIdentifier</key><string>$ORG.client-cert-profile.$UUID2</string>
  <key>PayloadUUID</key><string>$UUID2</string>
  <key>PayloadDisplayName</key><string>Сертификат для example.com</string>
</dict>
</plist>
EOF
```

```shell
chmod +x mobileconfig.sh
./mobileconfig.sh user1
```

Пароль от `.p12` в профиль не записывается -- iOS спросит его при установке. Установка профиля проходит так же, как
установка файла `.p12` выше.

На Mac с установленным **Apple Configurator** (в меню **Apple Configurator → Install Automation Tools...** ставится
консольная утилита `cfgutil`) профиль можно отправить на подключенное по USB устройство:

```shell
cfgutil install-profile user1.mobileconfig
```

На устройстве, которое не находится под управлением организации (не supervised), профиль придется подтвердить
вручную в **Настройках**, как в предыдущем разделе.


## Если сертификат не работает

- **«Неверный пароль» при установке.** Если пароль правильный -- пересоздайте `.p12` с параметром `-legacy`
  (см. выше).
- **Браузер не предлагает выбрать сертификат.** Проверьте, что браузер есть в списке поддерживаемых. На iOS используйте
  Safari. На Android проверьте, что сертификат установлен как **Сертификат пользователя VPN и приложений**, а не как
  сертификат центра сертификации.
- **Выбран не тот сертификат.** Chrome на Android запоминает выбор до перезапуска -- закройте его из списка недавних
  приложений.
- **Сервер отклоняет сертификат.** Проверьте, что он подписан тем центром сертификации, который указан в
  `ssl_client_certificate` в настройках nginx, и что у CA и клиента разные поля **Organization Name**.

Инструкции для других систем:
[Windows]({{< relref "client-certificate-windows" >}}),
[macOS]({{< relref "client-certificate-macos" >}}),
[Linux]({{< relref "client-certificate-linux" >}}).

