Сбой цифровой подписи приложения Mac вне Xcode

я разрабатываю приложение для Mac с Qt5, поэтому вне Xcode. Я хочу, чтобы GateKeeper разрешил моему приложению работать на компьютерах клиентов, а не выдавать предупреждение "невозможно открыть, потому что личность разработчика не может быть подтверждена".

я успешно цифровой подписью приложение, но привратник по-прежнему поставляется с этой жалобой. У меня есть сертификат разработчика Apple (я агент команды), и мой брелок говорит, что он действителен. Я также установил два Apple root сертификаты.

я использую утилиту командной строки codesign подписывать все внутри папки приложения и помимо бинарников я подписать приложение папку сам. Во всех случаях ответ codesign информативен и не отображает ошибок. С codesign я могу проверить, что действительно все двоичные файлы подписаны, запущенные

$ codesign --verify --deep --verbose=2 MyApp.app

видно, что все бинарники проверен. И вдобавок сообщает:

MyApp.app: действительно на диске
Приложение myapp.app: удовлетворяет его назначенное требование

работает:

$ codesign -v --verbose=4 --display MyApp.app   

дает

исполняемый файл= / Users/xxx/trunk/yyy/deploy/release / MyApp.app / содержание / MacOS / MyApp
Идентификатор=аааа.MyApp
Format=комплект с Mach-O thin (x86_64)
CodeDirectory v=20200 size=12461 flags=0x0(нет) хэши=616+3 location=embedded
Хэш тип=значение SHA1 размер=20
CDHash=d1c12c783dac0e8d9a2b749fb896b11558cec8b6
Размер подписи=8532
Authority=идентификатор разработчика приложения: XXXXX
Authority=Центр сертификации ID разработчика
Authority=Яблочный корень CA
Отметка времени=29 июля. 2015 12;04:40
Информация.записи plist=8
TeamIdentifier=YYYYY
Запечатанные ресурсы версия=2 правила=12 файлов=10
Количество внутренних требований=1 размер=180

который, кажется, хорошо.

под управлением

$ spctl -a -t exec -vv MyApp.app

on все двоичные файлы дает в результате

MyApp.app: принято
source=идентификатор разработчика
origin=идентификатор разработчика приложения: XXXX

который также кажется ОК

запуск инструмента командной строки Xcode check-signature в приложении или в двоичных файлах внутри папки приложения:

$ ./check-signature /Users/xxx/trunk/yyy/release/MyApp.app

дает в результате

(c) 2014 Apple Inc. Все права защищены.
Да

, который в все cases-желаемый результат.

но GateKeeper по-прежнему не принимает приложение и жалуется на то, что разработчик не может быть подтвержден.

[добавлено автором в пятницу, 17 июля 2015 года]

Я думаю, что нашел проблема. Я не знаю, является ли это функцией или ошибкой OSX. Мне очень помог stackoverflow вопрос 19551298.

всякий раз, когда файл загружается из интернета он получает расширенный атрибут файл com.яблоко.карантин, связанный с ним. При двойном нажатии на этот загруженный файл в Finder, GateKeeper имеет две возможности:

  1. когда файл не подписан, он выдает " неопознанный разработчик и т. д" сообщение

  2. когда файл имеет цифровую подпись, он выдает сообщение "разработчик не может быть подтвержден и т. д."

в обоих случаях MessageBox имеет только одну кнопку, кнопку OK. При нажатии на эту кнопку ничего не происходит, кроме закрытия MessageBox.

если расширенный атрибут удален (xattr-d), приложения выполняются, подписаны или нет.

поведение отличается, когда приложения запускается щелкните правой кнопкой мыши в Finder на приложении, а затем нажмите на действие меню "Открыть". Снова один из двух messageboxes показан, но теперь с дополнительной кнопкой, чтобы позволить пользователю открыть приложение в любом случае. Опять же, единственное различие между подписанным и не подписанным-это "неопознанное" или "не подтвержденное" сообщение. Я не ожидаю, что мои клиенты смогут сказать differende. В результате подписание приложения является упражнением в бесполезности.

на основе Поддержка Apple Документация я ожидал другого, гораздо более приятного поведения привратника при двойном щелчке загруженного приложения (возможно, документация устарела, или я неправильно ее прочитал):

  1. если приложение подписано привратник должен показать MessageBox с ", загруженные из интернета и т. д." и кнопка "все равно продолжить?"

  2. если приложение не подписано MessageBox с одной кнопкой OK и текстом " неопознанный разработчик так далее.."

4 ответов


извините за ответ на мой собственный вопрос, но я не вижу другого пути, как редактировать исходный вопрос приведет к тексту спагетти.

я, наконец, решил свою проблему. Сначала кредит: (i) ответ на мой другой stackoverflow вопрос был очень полезен и (ii) я получил очень хороший (платный) совет от официального разработчика Apple, подав так называемый инцидент технической поддержки (TSI).

на основе всего этого я могу дать очень краткий рецепт того, как ваше приложение Mac успешно лечится GateKeeper. После детализации рецепта я покажу, какой была моя первоначальная ошибка.

цель: после разработки приложения Mac за пределами Xcode, чтобы иметь GateKeeper выдачи предупреждения " загружены из интернета ..."с тремя кнопками, одна из которых"открыта".

сбой: когда GateKeeper выдает предупреждение с текстом ".. неопознанный застройщик.."или текст ".. неофициальный разработчик .. - С - в обоих случаях-почтовым ящиком с одной кнопкой "ОК".

получение вашего приложения GateKeeper-ready включает в себя три шага:

  • Сделайте ваше приложение автономным без неприемлемых внешних зависимостей. Единственными приемлемыми внешними зависимостями являются системные библиотеки. Все остальные зависимости должны быть скопированы в MyApp.папка приложения. GateKeeper отклоняет любое приложение, которое имеет несистемный внешний зависимости
  • двоичные файлы не должны располагаться на незаконных позициях внутри MyApp.папка приложения. Библиотеки переходят в MyApp / Contents/Framework, а исполняемый файл-в MyApp/Contents / MacOS
  • все двоичные файлы внутри MyApp должны быть подписаны цифровой подписью. Затем в myapp.папка приложения должна быть подписана. Для этого подписывается приложение Apple "Developer ID"..."сертификат необходим

наш рецепт автоматический. Вся работа сделана один сценарий. В случае Qt Creator мы используем скрипт qmake, где мы получаем доступ к системной оболочке через . При использовании любой из (Xcode) системных команд codesign, spctl или check-signature мы предполагаем, что вы перенаправили поток stderr в stdout как говорится в ответ на вопрос . В противном случае вы не сможете поймать ответ системы при запуске этих утилит. В следующем мы не будем явно показывать это переадресация.

ВОТ НАШ РЕЦЕПТ

A. создание автономного приложения:

  1. скопируйте (со скриптом) все необходимые двоичные файлы в MyApp.папка
  2. выполнить (со скриптом)install_name_tool -change и install_name_tool -id таким образом, что все зависимости внутри приложения имеют относительный тип @executable_path/../MacOS.. или @executable_path/../Frameworks
  3. выполнить (со скриптом)otool -L на всех двоичных файлах внутри MyApp.папку приложение и флаг какой-либо незаконной зависимость, как "@путь rpath..."или абсолютные пути к файлам не являются системными путями. Обратите внимание, что otool -L не гарантируется поиск всех зависимостей. Плагины часто находятся за горизонтом otool. Вот почему вам нужен следующий чек.
  4. запустите терминал в месте " MyApp.app / содержание / MacOS". Запустить export DYLD_PRINT_LIBRARIES=1. Затем запустите внутри того же окна терминала ./MyApp. Ваш терминал заполнится более чем сотней загруженных библиотек. Проверьте этот список еще раз для запрещенных библиотек (библиотек присутствует на вашем компьютере, но не на компьютере ваших клиентов).
  5. доказательство пудинга находится в еде. Мы используем виртуальные машины MacInCloud и проверьте, работает ли наше приложение там. Альтернативным решением может быть Mac родственника, который не является застройщиком. Или вы также можете создать нового пользователя ("тест") на своем собственном Mac и скопировать приложение в его загрузку (или папку рабочего стола, или ...). В последнем случае необходимо временно переименовать корневую папку ваша IDE, так как в противном случае пользователь "тест" найдет там отсутствующие двоичные файлы.

B подписание приложения

  1. подписание: с нашим скриптом мы запускаем codesign --force --verify --verbose --sign \"Developer ID Application: ....\" \"/path/to/binary\" на всех двоичных файлах в приложении, а затем в самой папке приложения. В каждом случае реакция системы улавливается. Он должен содержать в каждом случае строку "signed Mach-O thin".
  2. проверка: выполнить (со скриптом) команду codesign --verify --verbose \"/path/to/binary\" на каждом двоичном файле в вашем приложении и в самом приложении и поймать реакцию системы. Он должен в каждом случае содержать строки "действителен на диске"и" удовлетворяет его назначенному требованию".
  3. проверка привратника: запуск (со скриптом)spctl -a -t exec -vv /path/to/binary\" на каждом двоичном файле и в самой папке приложения. Реакция системы поймана. Он должен содержать во всех случаях строку "принятый источник".
  4. check-signature: Run (со скриптом) check-signature \"/path/to/banary\" на каждом двоичном файле и в самой папке приложения. Реакция системы поймана. Он должен содержать строку "YES" в каждом случае.

C внешняя проверка

  1. zip ваше приложение в один zip-файл. Загрузить на один из ваших облачных серверов

  2. GateKeepers хранит длинный список (обычно сотни элементов) исключений в своей общей роли хранителя ворот. Ваше приложение не должно быть в этом списке, если вы хотите проверить привратника. Вместо редактирования этого списка гораздо проще создать нового пользователя на вашем Mac. Войдите к этому пользователю и загрузите zip-файл с сервера Internet cloud. Finder автоматически распакует его. Щелкнуть по нему. Если GateKeeper говорит вам, что он может открыть приложение, но предупреждает Вас в то же время, что он загружен из интернета, пришло время захватить (белое) пиво.

здесь желаемый привратник предупреждение:enter image description here

моя ошибка

я сделал много установка и подписание без явной проверки результата для каждого двоичного файла. После этого я бы использовал otool -L на нескольких двоичных файлах, но не на всех. Я пропустил тот факт, что обновление до Qt 5.5 с более ранней версии Qt binary libqminimal.dylib приобрел дополнительную зависимость, а именно.: QtDBus. Я этого не заметил, но привратник заметил.

разработчики Qt могут задаться вопросом, почему мы не просто используем macdeployqt для развертывания приложения Qt на Mac. Во-первых, мы не любим не использовать плохо документированные утилиты черного ящика. На интернет-форумах есть довольно много людей, сообщающих о проблемах с macdeployqt. Кроме того, библиотеки Qt могут иметь разные места установки (как сообщает otool-L) при сравнении различных версий Qt. Когда у нас будет новая версия Qt, наш скрипт немедленно начнет кричать о запрещенных зависимостях. Таким образом мы получаем информацию о том, что изменилось в новой версии.


вопрос и самоответ adlag были бесценны, помогая мне преодолеть ту же проблему. Однако, как бы хорош ни был его рецепт, некоторые утверждения не совсем верны, поэтому я хотел бы предложить несколько дополнительных моментов.

  • нет необходимости заменять записи @rpath в двоичных файлах и динамических библиотеках операторами @executable_path. операторы @rpath прекрасны, пока фактические записи rpath, встроенные в двоичные файлы, не являются абсолютными. Вы можете найти множество допустимых Qt пакеты приложений, использующие rpath. Вы можете заставить его работать, делая то, что сказал adlag, но вы можете работать для себя.
  • см. комментарий jil выше о том, как использовать otool -l $file | grep -A2 LC_RPATH и install_name_tool -delete_rpath $path $file для проверки и удаления встроенных путей в двоичных файлах и библиотеках
  • см https://developer.apple.com/library/content/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG207 для четкого объяснения того, почему привратник жалуется на пути в вашем двоичные файлы, и как вы можете увидеть конкретную жалобу в syslog.
  • если у вас есть проблема с абсолютными путями, вы должны сначала попытаться исправить свою сборку, а не использовать install_name_tool постфактум.
  • если вы используете cmake, это, вероятно, полезно:https://cmake.org/Wiki/CMake_RPATH_handling#Mac_OS_X_and_the_RPATH
  • не работать spctl -a -t exec -vv /path/to/binary в файлах dylib. Вы получите ошибки о конверте ресурса. Это ожидаемо, а не проблема.
  • по моему опыту, macdeployqt работает нормально. Я решил проблему, изменив свою сборку, так что абсолютные пути не попали в оскорбительный файл dylib (libquazip). Я все еще использовал install_name_tool убрать абсолютные пути к установке Qt. Я тогда использовал macdeployqt чтобы создать пакет, подпишите пакет и создайте файл DMG.

мои два бита:

  1. чтобы действительно проверить codesigning, мне пришлось либо загрузить DMG в сервер и скачать его с помощью браузера или установите атрибут карантина вручную:

    APP_PATH="Any.app"
    xattr -w com.apple.quarantine '0081;5a37dc6a;Google Chrome;F15F7E1C-F894-4B7D-91B4-E110D11C4858' "$APP_PATH"
    xattr -l "$APP_PATH" # You should see the quarantine attribute here
    open "$APP_PATH"
    

    Если ваше приложение правильно подписано, вы должны увидеть системный диалог с кнопка Open.

    Я нашел значение атрибута карантина, посмотрев на другой .приложение загружено из интернета. Я не знаю, что значение средства.

    Я действительно не понимаю, почему команда spctl говорит" принято " даже если служба Gatekeeper отрицает открытие приложения.

  2. У меня было окно сообщения "неопознанный разработчик", потому что на мои фреймворки Qt ссылались как" @rpath/необходимости некоторые.рамки." Меняем его на"@application_path/../Базы/необходимости некоторые.рамки" с помощью install_name_tool Исправлена проблема в моем приложении.


выяснил проблему после многих попыток.

в моем случае: Сообщение Pop-поврежденное приложение пришло из-за отсутствия библиотек. Я создал .файл приложения с использованием QT. Для создания dmg я использовал командный инструмент deploymacqt. инструмент deploymacqt создает динамические библиотеки внутри.app, так что в основном, если мы codesign перед созданием dmg, это изменение будет манипулировать кодовым знаком. Так что правильное решение.

# Create dmg using 
    deploymacqt <yourapp.app> -dmg

# Open resulted dmg file, copy <yourapp.app> to different folder(let's say /Documents/<yourapp.app>)

# Codesign the /Documents/<yourapp.app> using 
    codesign --deep --force --verify --verbose --sign "Developer ID Application: <developerid>" <yourapp.app>

# Verify using
    codesign --verify --verbose=4 <yourapp.app>
 * you should see something like this
    <yourapp.app>: valid on disk
    <yourapp.app>: satisfies its Designated Requirement

# Now create again the dmg file using dropdmg(https://c-command.com/dropdmg/) application, download, install dropdmg. set the cofiguration preferences with your developer id certificate in signing option.

# drag and drop <yourapp.app> to dropdmg app, wait for creation of dmg to complete. voila you have now successfully created dmg with proper developer id certification.

# verify resulted dmg again using   
     codesign --verify --verbose=4 <yourapp.dmg>
# you can also verify with gatekeeper
     spctl -a -t exec -vv <yourapp.dmg>

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