Вам не нужно разбираться в теории сертификатов и профилей, чтобы создать полностью работающее приложение для iOS, но вам может быть интересно узнать, как работает этот процесс, чтобы упростить будущие сеансы отладки. В конце концов, я бы сказал, что вполне вероятно, что вам как инженеру приходилось иметь дело с загадочными ошибками подписи в какой-то момент в прошлом!
Теория, стоящая за этими двумя, неразрывно связана с темой современной криптографии, и я считаю, что хороший способ понять сертификаты и профили — это сделать шаг назад от мобильного мира и понять, как безопасный просмотр веб-страниц (HTTPS, SSL, TLS) работает.
Краткое введение в современный (безопасный) просмотр веб-страниц
Возможно, вы слышали о симметричной криптографии — механизме, который позволяет зашифровать сообщение с помощью специального секретного ключа, а затем расшифровать его тем же ключом:
- Простое сообщение + секретный ключ = зашифрованное сообщение
- Зашифрованное сообщение + секретный ключ = простое сообщение
Если два человека, которые пытаются общаться друг с другом, хотят сделать это безопасным способом, они могут сделать это, договорившись о секретном ключе и используя алгоритм симметричной криптографии для шифрования/дешифрования своих сообщений. Это общение будет безопасным, даже если сеть перехватывается злоумышленником, поскольку этот злоумышленник не сможет разобраться в перехваченных сообщениях, если ему каким-то образом не удастся украсть ключ, используемый для шифрования сообщений. Вот как раньше работали зашифрованные чаты WhatsApp E2E — когда эта функция была впервые выпущена, шифрование активировалось путем отправки QR-кода контакту, с которым вы хотели безопасно поговорить. Этот QR-код представляет собой секретный ключ, сгенерированный вашим устройством, и после того, как он будет передан контакту, оба устройства сохранят этот ключ. (К вашему сведению, шифрование WhatsApp больше не работает так. С тех пор система превратилась в нечто более мощное, использующее концепции, которым пытается научить эта статья.)
Но, несмотря на то, что в то время этот механизм отлично работал для WhatsApp, этот механизм не работает для обычного просмотра веб-страниц по множеству причин.
Прежде всего, вся концепция механизма WhatsApp в то время заключалась в том, что обмен должен был происходить лично. Если вы физически поделились своим QR-кодом, попросив своего контакта отсканировать его, направив камеру прямо на ваш телефон, вы можете быть полностью уверены, что никто не имеет к нему доступа. Если я пытаюсь установить безопасное соединение с Google, то Google наверняка не пришлет какого-нибудь сотрудника ко мне домой, чтобы я дал ему какой-то странный QR-код. Вам нужно каким-то образом передать им ключ через Интернет, что немедленно сделает ваше соединение уязвимым для атак типа «человек посередине»:
- Сгенерировать ключ
- Отправить ключ кому-либо как часть простого HTTP-запроса
- Упс! Кто-то просматривал вашу сеть без вашего ведома и перехватил ключ, который вы пытались отправить. Теперь они могут видеть все, что вы переписываетесь.
Во-вторых, в Интернете нет «учетных записей» — вы не можете сгенерировать ключ один раз и сохранить его на устройстве, как это делает WhatsApp, потому что вам не нужно входить в систему, чтобы выполнить поиск в Google. Это означает, что вам придется выполнять этот процесс каждый раз, когда вы пытаетесь посетить новый веб-сайт, что делает вас еще более уязвимым для перехвата.
Асимметричное шифрование
Часть решения этой проблемы приходит в виде асимметричного шифрования. Вместо того, чтобы иметь один ключ, который может как шифровать, так и расшифровывать сообщения, алгоритмы асимметричного шифрования вместо этого имеют дело с парой ключей, которые не могут функционировать друг без друга:
- Простое сообщение + ключ 1 = зашифрованное сообщение
- Зашифрованное сообщение + ключ 2 = простое сообщение
Вы не можете расшифровать сообщение с помощью самого ключа 1 — только противоположный ключ может восстановить что-то, зашифрованное определенным ключом. Это означает, что возможен и обратный сценарий: зашифровать с помощью ключа 2, расшифровать с помощью ключа 1.
Эти пары ключей часто называют открытыми/закрытыми ключами из-за того, как они предназначены для использования. Поскольку вам нужны оба ключа для полного перехвата сообщений, нет никакой опасности, что злоумышленники перехватят один из ключей, пока вы убедитесь, что другой ключ безопасен (в идеале, не допуская его в сеть). Первый называется открытым ключом, а второй — закрытым (или секретным) ключом.
Вернемся к примеру с просмотром веб-страниц. В предыдущем сценарии мы не смогли установить безопасное соединение с веб-сайтом из-за того, насколько просто кто-то может украсть симметричный секретный ключ и перехватить связь. Однако если мы начнем общаться с помощью пары ключей, ситуация уже может немного улучшиться. Если предположить, что сервер сгенерировал собственную пару ключей для связи со своими пользователями, зашифрованное соединение может быть установлено следующим образом:
- Попросите сервер дать мне свой открытый ключ
- Отправьте сообщение и зашифруйте его с помощью открытого ключа
- Сервер отвечает сообщением, зашифрованным их секретным ключом
- Расшифровать сообщение сервера с помощью открытого ключа
В этом сценарии кто-то, перехватывающий вашу сеть, не сможет прочитать то, что вы отправляете на сервер, поскольку у него нет доступа к ключу, хранящемуся на сервере, но это все равно не является безопасным соединением.
Прежде всего, злоумышленник все еще может перехватить часть, где сервер дает вам открытый ключ, чтобы расшифровать сообщения, которые сервер отправляет вам. Они не будут знать, что вы отправляете на него, но они могут знать, что вы получаете.
Во-вторых, вы никак не можете быть уверены, что открытый ключ, который вы получили, действительно пришел с сервера. Злоумышленник вполне мог бы перехватить его и заменить своим открытым ключом, что дало бы ему полную возможность притворяться сервером, к которому вы пытались подключиться.
Решение первой проблемы состоит в том, чтобы соединение работало не просто за счет асимметричного шифрования сообщений, а за счет того, что клиент и сервер сначала пытаются «проверить» друг друга, выполняя ряд шагов, которые смешивают как симметричное, так и асимметричное шифрование. таким образом, что любая попытка попытки перехватить/изменить соединение приведет к сбою процесса. Этот процесс, называемый рукопожатием, детализируется протоколами безопасного соединения, такими как SSL и TLS, и реализуется вашим браузером (и серверами) для обеспечения функциональности схемы HTTPS, которую вы используете прямо сейчас. Но как насчет той части, где сам открытый ключ может быть подделан? Даже если ваш браузер попытается установить соединение, не будет преувеличением сказать, что злоумышленник может воспроизвести сам процесс установления связи, пытаясь полностью выдать себя за сервер.
В этом случае корень проблемы заключается в том, что в нашем гипотетическом сценарии открытый ключ отправляется нам в виде обычного текста. Чтобы быть уверенным, что ключ не был подделан злоумышленником, сообщение, которое приносит нам ключ, должно само прийти к нам в зашифрованном виде.
Но подождите… В прошлый раз, когда мы пытались что-то зашифровать, мы решили, что этого недостаточно, потому что злоумышленник мог перехватить ту часть, где происходил обмен ключами. Если вы говорите мне, что сам обмен будет зашифрован, как я должен безопасно обмениваться ключами, которые защитят другой обмен ключами? Если чтение этого привело вас в полное замешательство, добро пожаловать в мир криптографии.
Как вы могли заметить, мы имеем дело с игрой в кошки-мышки. Нам нужно защитить данные, но сначала нам нужно поделиться механизмом защиты. Но этот механизм нуждается в защите, и этот механизм нуждается в защите. а затем нужно защитить этот другой механизм, и так далее, и тому подобное. Это никогда не заканчивается! …или нет? Как получается, что сеть работает, если все так несовершенно?
Когда мы говорили о симметричной криптографии, мы упомянули, что причина, по которой первоначальная функция шифрования WhatsApp работала, заключалась в том, что она могла обмениваться информацией за пределами Интернета, и именно так мы смогли вырваться из нашего круга кошек и мышей.
Ввод центров сертификации
Но прежде чем увидеть, как разрывается петля, нам нужно сначала представить упомянутую третью сторону, которая будет отвечать за безопасную передачу нам открытого ключа сервера.
Центр сертификации (ЦС) — это причудливое название сервера, на котором хранится словарь, сопоставляющий принципы (например, IP-адрес swiftrocks.com) с открытым ключом. Это та сторона, о которой мы упоминали — когда сервер хочет внедрить безопасные соединения, он начинает с создания пары ключей и отправки ее в центр сертификации. (Это может насторожить, если вы разработчик iOS; это именно то, что вы делаете, когда просите создать сертификат разработки для своего приложения в цепочке ключей.)
ЦС отвечает на регистрацию, предоставляя вам файл, содержащий ваш открытый ключ, зашифрованный с помощью собственного секретного ключа ЦС. Результат этой операции называется сертификатом, и его цель — обеспечить безопасный доступ пользователей к этому открытому ключу. Если у пользователя есть доступ к открытому ключу этого конкретного ЦС, он может прочитать ваш сертификат и получить неопровержимое доказательство того, что его содержимое не было подделано. В мире есть множество центров сертификации — компании по обеспечению безопасности, Apple и даже почтовое отделение США являются примерами компаний, работающих как таковые.
А теперь подождите, потому что мы уже знаем, что произойдет. Как это должно что-то решить, если вся суть проблемы в том, что вы не можете безопасно передавать открытые ключи через Интернет? Как я должен получить открытый ключ ЦС, не имея ЦС для ЦС и ЦС для ЦС для ЦС?
Ответ может быть неожиданным: вам это не нужно, потому что оно у вас уже есть. Чтобы разорвать петлю кошки-мышки, техническое сообщество согласилось вести список «ЦС, которым можно доверять» и жестко закодировать их открытые ключи в таких вещах, как ваша ОС и выбранный браузер. Ключи не «отправляются» вам как часть процесса рукопожатия, как в наших предыдущих поддельных сценариях — они поставляются в комплекте с устанавливаемым вами материалом. Когда открытый ключ уже находится в вашем распоряжении, злоумышленник не может подделать сертификат с помощью атак типа «человек посередине», что позволяет нам, наконец, установить безопасное соединение.
Этот механизм не является полностью безошибочным. Хакер все еще может нарушить этот процесс в следующих сценариях:
- Компрометация самого ЦС: это не невозможно, но, вероятно, с этим можно будет справиться довольно быстро, установив исправление, удаляющее ЦС из вашего «доверенного» списка.
- Утечка закрытого ключа сервера: это происходит время от времени и может быть устранено путем «отзыва» сертификата. Способы отзыва сертификатов довольно интересны, но я не буду здесь вдаваться в подробности.
- Загрузка и использование поддельной копии браузера, который принимает поддельные центры сертификации. Не исключено, но если вы попадетесь на эту удочку, это на 100 % ваша вина.
Несмотря на теоретические потенциальные проблемы, текущая установка считается достаточно хорошей для своей цели и используется во всей сети. Мы не будем вдаваться в подробности о том, как именно рукопожатие TLS/SSL работает в современной сети, поскольку это не тема статьи, но вот пример изображения, на котором вы можете увидеть, как сертификаты проявляются в соединениях SSL:
Как работают сертификаты в iOS?
Понимая, как сертификаты используются в общем веб-мире, мы лучше понимаем их назначение в мобильной разработке.
В случае с iOS Xcode начнет выдавать вам сообщения о сертификатах и удостоверениях подписи при попытке распространить копии вашего приложения. Это приведет вас к процессу, в котором вы создаете пару ключей шифрования и просите Apple выступить в роли ЦС и предоставить вам сертификат для идентификатора пакета вашего приложения, сохраняя при этом секретный ключ только для себя и своих товарищей по команде.
Цель этого процесса — защитить как загрузку, так и попытку пользователя установить ваше приложение. Вы могли заметить, что вы не можете создавать архивы своего приложения, не имея секретного ключа сертификата, который вы пытаетесь связать с приложением: это потому, что процесс распространения Xcode хочет, чтобы вы «подписали» двоичный файл с вашим секретным ключом, чтобы у Apple было неопровержимое доказательство того, что именно вы (или ваши товарищи по команде) создали этот двоичный файл, а не кто-то, притворяющийся вами. Вот почему Apple требует, чтобы идентификаторы пакетов были уникальными.
Что такое профили обеспечения?
В отличие от сертификатов, концепция профилей специфична для разработки iOS, и их цель напрямую связана с усилиями Apple, направленными на то, чтобы iOS воспринималась как безопасная операционная система. Вот в чем проблема: как Apple может предоставить разработчикам более глубокий доступ к ОС и оборудованию, не ставя под угрозу безопасность обычного пользователя?
Ответ: Пусть делают все, что хотят, но ограничивают их возможность делиться своими творениями в зависимости от того, что делает продукт. В то время как Android позволяет вам загружать двоичные файлы из Интернета и устанавливать их на свой телефон без ограничений, iOS запрещает вам делать это, если только разработчик явным образом не подтвердит во время компиляции, что вашему конкретному телефону разрешено устанавливать этот конкретный двоичный файл. Вы уже знаете, что такое подтверждения — это и есть профиль обеспечения, и они входят в состав ваших приложений вместе с вашими сертификатами, чтобы Apple/iOS могли быть полностью уверены в двоичных файлах, которые они получают.
Разработчики должны предоставлять профили при нацеливании на физические устройства, и они содержат такую информацию, как:
- Идентификатор пакета приложения
- Сертификаты, привязанные к этому идентификатору
- Возможности приложения (например, доступ к камере)
Упомянутый ранее процесс «подписания» затем объединяет эту информацию в двоичный файл, который позже в процессе проверяется устройством, пытающимся установить приложение, чтобы подтвердить, что двоичный файл является законным и что ему действительно разрешено установить его.
Для всех сборок, предназначенных для физических устройств, требуются профили подготовки, но только для отладочных сборок требуется явный список устройств. Для сборок Enterprise и App Store профили не должны включать данные об устройствах, поскольку такие сборки предназначены для установки теоретически бесконечным количеством пользователей.
Вывод
Хотя вам не нужно знать абсолютно ничего об этом, чтобы отправить приложение в App Store, мы надеемся, что эта информация пригодится вам в следующий раз, когда ваша команда столкнется с мистической проблемой, связанной с подписью в Xcode. Теперь вы избраны ответственным лицом вашей компании по вопросам сертификатов!
Спасибо за чтение! Если вы хотите увидеть больше подобного контента для Swift/iOS, подпишитесь на меня в Twitter!