Как вы кодируете пакеты фреймворка для Mac App Store?

После недавней отправки я получил следующую ошибку:

Недействительная подпись - вложенный пакет приложений (FooBar.app/Contents/Frameworks/GData.framework) не подписан, подпись недействительна или не подписана сертификатом отправки Apple. Дополнительные сведения см. В Руководстве по подписи кода и изолированной программной среде приложений.

Недействительная подпись - вложенный пакет приложений (FooBar.app/Contents/Frameworks/Growl.framework) не подписан, подпись недействительна или не подписана сертификатом отправки Apple. Дополнительные сведения см. В Руководстве по подписи кода и изолированной программной среде приложений.

Недействительная подпись - вложенный пакет приложений libcurl (FooBar.app/Contents/Frameworks/libcurl.framework) не подписан, подпись недействительна или не подписана сертификатом отправки Apple. Дополнительные сведения см. В Руководстве по подписи кода и изолированной программной среде приложений.

Поэтому я подписал все пакеты фреймворка на Technote 2206:

codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A/libcurl
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A/libssh2.1.dylib
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./Growl.framework/Versions/A/Growl
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./GData.framework/Versions/A/GData

Technote 2206 говорит:

Платформы подписи

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

# Это неправильный путь:

codeign -s моя-подписи-личность ../FooBarBaz.framework

# Это правильный путь:

codeign -s моя-подписи-личность ../FooBarBaz.framework/Versions/A

И когда я пытаюсь проверить результаты, мне кажется, что это хорошо:

% codesign -vvv FooBar.app/Contents/Frameworks/libcurl.framework
FooBar.app/Contents/Frameworks/libcurl.framework: valid on disk
FooBar.app/Contents/Frameworks/libcurl.framework: satisfies its Designated Requirement
% codesign -vvv FooBar.app/Contents/Frameworks/Growl.framework
FooBar.app/Contents/Frameworks/Growl.framework: valid on disk
FooBar.app/Contents/Frameworks/Growl.framework: satisfies its Designated Requirement

Ради интереса я попытался подписать пакет фреймворка напрямую, но он все равно был отклонен. Но это именно то, чего не следует делать в документации.

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

Я только предполагаю, что это как-то связано с существующими списками (нужно ли мне владеть идентификаторами в Info.plists фреймворка?) Или правами - какие-либо предложения?


person csexton    schedule 08.10.2011    source источник
comment
Я также обнаружил это ранее, когда отправил свое приложение. К счастью, Apple не отказалась от этого предложения, но отметила, что нам придется подписать фреймворки позже. Я думаю, что лучше опубликовать сообщение на странице проблем с кодом Growl google, и очень скоро люди столкнутся с той же проблемой.   -  person koo    schedule 09.10.2011
comment
Также столкнулся с этой проблемой при отправке приложения с помощью платформы Growl. Я предполагаю, что вам придется изменить идентификатор пакета Growl.framework на тот, который у вас есть, а затем кодировать его.   -  person Andrew    schedule 10.10.2011
comment
Это странно: я опубликовал приложение, которое включает два фреймворка (CorePlot и MacRuby), оба без подписи. Я запускаю команду подписи кода в пакете приложений только один раз, и приложение было принято без каких-либо комментариев по фреймворку. Теперь, если вы посмотрите на пакет приложений (bit.ly/charterapp), оба фреймворка будут подписаны. Вы пытались просто подписать все приложение?   -  person p4010    schedule 12.10.2011
comment
@ p4010, я делал - раньше они были без подписи. Например, Growl - это просто прямая пачка, которую они раздают. У меня уже есть это приложение в магазине, поэтому я предполагаю, что это связано с новой песочницей. Когда вы отправили свое приложение?   -  person csexton    schedule 12.10.2011
comment
@ Андрей, у вас сработало изменение идентификатора пакета?   -  person csexton    schedule 12.10.2011
comment
@csexton, еще не пробовал. В следующем обновлении я еще немного с ним поработаю. Одна вещь, на которую следует обратить внимание, - это использовать липо (для удаления поддержки ppc) после кодовой подписи, поскольку это сделает подпись недействительной.   -  person Andrew    schedule 12.10.2011
comment
Я исправляюсь: я только что загрузил новую версию своего приложения, которая была принята, но с предупреждением об отсутствующих / недействительных подписях на включенных фреймворках. Судя по всему, это недавняя разработка в обзоре приложений (моя предыдущая версия включала те же неподписанные фреймворки, и у меня никогда не было такого предупреждения). @csexton: моя предыдущая отправка была 6 октября.   -  person p4010    schedule 14.10.2011
comment
Сценарий @csexton не включает знак кода для файлов .a. Я пытался использовать его в своем проекте, но он не подходит для такого подкомпонента. Я попытался изменить его, чтобы оценить эти файлы; все в порядке, но (все компоненты подписаны), но приложение не запускается с ошибкой недопустимого знака. Идеи? (Примечание: я думаю, что параметры прав больше не нужны, и он останавливает задачи на XCode 5)   -  person danielemm    schedule 18.02.2014


Ответы (4)


На основе ответа baptr я разработал этот сценарий оболочки, который кодирует все мои фреймворки и другие двоичные ресурсы / вспомогательные исполняемые файлы (в настоящее время поддерживаемые типы: dylib, bundle и элементы входа в систему):

#!/bin/sh

# WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY! 

# Verify that $CODE_SIGN_IDENTITY is set
if [ -z "${CODE_SIGN_IDENTITY}" ] ; then
    echo "CODE_SIGN_IDENTITY needs to be set for framework code-signing!"

    if [ "${CONFIGURATION}" = "Release" ] ; then
        exit 1
    else
        # Code-signing is optional for non-release builds.
        exit 0
    fi
fi

if [ -z "${CODE_SIGN_ENTITLEMENTS}" ] ; then
    echo "CODE_SIGN_ENTITLEMENTS needs to be set for framework code-signing!"

    if [ "${CONFIGURATION}" = "Release" ] ; then
        exit 1
    else
        # Code-signing is optional for non-release builds.
        exit 0
    fi
fi

ITEMS=""

FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -d "$FRAMEWORKS_DIR" ] ; then
    FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle" | sed -e "s/\(.*framework\)/\1\/Versions\/A\//")
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        exit 1
    fi

    ITEMS="${FRAMEWORKS}"
fi

LOGINITEMS_DIR="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Library/LoginItems/"
if [ -d "$LOGINITEMS_DIR" ] ; then
    LOGINITEMS=$(find "${LOGINITEMS_DIR}" -depth -type d -name "*.app")
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        exit 1
    fi

    ITEMS="${ITEMS}"$'\n'"${LOGINITEMS}"
fi

# Prefer the expanded name, if available.
CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then
    # Fall back to old behavior.
    CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}"
fi

echo "Identity:"
echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}"

echo "Entitlements:"
echo "${CODE_SIGN_ENTITLEMENTS}"

echo "Found:"
echo "${ITEMS}"

# Change the Internal Field Separator (IFS) so that spaces in paths will not cause problems below.
SAVED_IFS=$IFS
IFS=$(echo -en "\n\b")

# Loop through all items.
for ITEM in $ITEMS;
do
    echo "Signing '${ITEM}'"
    codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" --entitlements "${CODE_SIGN_ENTITLEMENTS}" "${ITEM}"
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        echo "Failed to sign '${ITEM}'."
        IFS=$SAVED_IFS
        exit 1
    fi
done

# Restore $IFS.
IFS=$SAVED_IFS
  1. Save it to a file in your project. I keep my copy in a Scripts subdirectory in my project’s root.
    • Mine is called codesign-frameworks.sh.
  2. Add a “Run Script” build phase right after your “Copy Embedded Frameworks” build phase.
    • You can call it “Codesign Embedded Frameworks”.
  3. Вставьте ./codesign-frameworks.sh (или то, что вы назвали своим скриптом выше) в текстовое поле редактора скриптов. Используйте ./Scripts/codesign-frameworks.sh, если вы храните сценарий в подкаталоге.
  4. Создайте свое приложение. Все связанные фреймворки будут иметь кодовую подпись.

Если вы по-прежнему получаете ошибку «Идентификация: неоднозначно (соответствует:…», прокомментируйте, пожалуйста, ниже. Этого больше не должно происходить.

Обновлено 14.11.2012: добавлена ​​поддержка фреймворков со специальными символами в имени (не включая одинарные кавычки) в «codeign-frameworks.sh».

Обновлено 30.01.2013: добавлена ​​поддержка специальных символов во всех путях (это должно включать одинарные кавычки) в «codeign-frameworks.sh».

Обновлено 29.10.2013: добавлена ​​экспериментальная поддержка dylib.

Обновлено 28.11.2013: добавление поддержки прав. Улучшение экспериментальной поддержки dylib.

Обновлено 13.06.2014: Устранение проблем с кодовой подписью фреймворков, содержащих (вложенные) фреймворки. Это было сделано путем добавления параметра -depth к find, который заставляет find выполнять обход в глубину. Это стало необходимым из-за проблемы, описанной здесь. Вкратце: содержащий пакет можно подписать, только если его вложенные пакеты уже подписаны.

Обновлено 28.06.2014: добавлена ​​поддержка экспериментального пакета.

Обновлено 22.08.2014: Улучшение кода и предотвращение сбоев при восстановлении IFS.

Обновлено 26.09.2014: добавлена ​​поддержка элементов входа в систему.

Обновлено 26.10.2014: Проверки каталогов. Это исправляет ошибки «строка 31/42: слишком много аргументов» и результирующая ошибка «объект кода вообще не подписан» для путей, содержащих специальные символы.

Обновлено 07.11.2014: Устранение неоднозначной ошибки идентификации (например, «Разработчик Mac: неоднозначно…») при использовании автоматического разрешения идентификации в Xcode. Вам больше не нужно явно указывать личность, и вы можете просто использовать «Mac Developer»!

Обновлено 07.08.2015: Улучшение семантики.

Улучшения приветствуются!

person JanX2    schedule 01.07.2012
comment
Спасибо за это, просто примечание, это не сработает, если в имени вашей цели есть пробел. Я попытался исправить, но не смог заставить его работать, поэтому изменил цель. - person Craig; 10.07.2012
comment
Должно работать сейчас, когда в имени FRAMEWORK_DIR есть пробелы / специальные символы. - person JanX2; 16.07.2012
comment
Однако мне также нужно было отключить параметр отметки времени, добавив --timestamp в конец команды codeign. - person Elmer Cat; 18.06.2013
comment
Интересно. Вы, @Elmer Cat, случайно делаете это в невыпущенной версии OS X? На странице руководства описывается этот вариант «поведения по умолчанию, зависящего от системы». - person JanX2; 25.07.2013
comment
Еще раз проверив, @ JanX2, необходимость в этом, похоже, была устранена новой версией Xcode, в которой код подписывает фреймворки напрямую. - person Elmer Cat; 26.07.2013
comment
# ВНИМАНИЕ: вам, возможно, придется запустить Clean в Xcode после изменения CODE_SIGN_IDENTITY! Чистое золото. Каждый раз, когда я проводил 2 часа в глубоком поиске, это просто небольшая очистка. :( - person Git.Coach; 25.09.2013
comment
Ян - Можете ли вы обновить это, чтобы также подписывать фреймворки * .dylib? Они копируются в ту же папку Frameworks встроенного пакета приложений, но у них нет вложенных папок (/ Versions / A) и т. Д .; это просто отдельные файлы с расширением .dylib. Каждую тоже нужно подписать. - person Bryan; 27.10.2013
comment
Элмер Кэт - я не знаю, какую версию Xcode вы используете, но я использую 5.0.1, и она определенно НЕ подписывает мои фреймворки автоматически. Я рвал волосы, пока не нашел этот сценарий. - person Bryan; 27.10.2013
comment
Я хотел бы @Bryan, но я не могу это проверить, поскольку я нигде не использую .dylibs. У вас должно быть достаточно репутации, чтобы взять мой сценарий, изменить его на свой вкус и отредактировать здесь! - person JanX2; 28.10.2013
comment
Да, но проблема в том, что я полностью лишился мозгов, когда дело касается сценариев Bash. Понятия не имею, что добавить, чтобы любой файл с * .dylib добавлялся в $ {Frameworks}. - person Bryan; 29.10.2013
comment
Добавление экспериментальной поддержки dylib. - person JanX2; 29.10.2013
comment
JanX2 - это не работает для дилибов, но исправить это легко - измените команду sed на что-то вроде: sed -e "s/\(.*framework\)/\1\/Versions\/A\//" - person Adrian; 27.11.2013
comment
Спасибо, @Adrian! Просто добавил это и еще кое-что. - person JanX2; 28.11.2013
comment
Идеально!! Йосемити требует подписать все фреймворки в подписанном приложении. В моем случае я распространяю за пределами Mac App Store, поэтому никаких прав не требуется. - person Roger Sodré; 05.09.2014
comment
@ JanX2 спасибо за это! Однако у меня есть вспомогательное приложение в моем приложении для OS X (написанное на Swift), и это не отменяет рамки внутри помощников. Я попытался переписать этот сценарий, чтобы подписать их, но мне все равно пришлось уволить их с терминала (после архивирования), чтобы Apple приняла его. - person rdougan; 08.02.2015
comment
@rdougan Вы можете заменить FRAMEWORKS_FOLDER_PATH на CONTENTS_FOLDER_PATH для FRAMEWORK_DIR. Это должно гарантировать, что абсолютно все фреймворки имеют кодовую подпись. Пожалуйста, опубликуйте свои результаты. :) - person JanX2; 08.02.2015
comment
@ JanX2 Я пробовал несколько вещей, но они просто не работают. Это определенно код, подписывающий файлы фреймворка, но после отправки я получаю электронное письмо от Apple, в котором говорится, что это не так. Если я вручную подпишу их после завершения сборки архива, Apple примет сборку. - person rdougan; 08.02.2015
comment
@rdougan, можете ли вы опубликовать пример шагов для ручной подписи после завершения сборки архива? У меня проблемы с подпиской на моем предприятии в собственном приложении. - person SeeCoolGuy; 04.12.2015

Ваш комментарий показывает, что вы подписали объекты в каталоге версий пакета. Technote показывает, чтобы подписать сам каталог.

Следующее лучше соответствует Technote:

codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./Growl.framework/Versions/A
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./GData.framework/Versions/A
person baptr    schedule 02.12.2011

Вот как я это исправил;

  • Войдите в настройки сборки вашей цели
  • Найдите строку «Другие флаги подписи кода».
  • Введите значение --deep в параметр выпуска.
  • Закройте XCode
  • Войдите в папку производных данных на вашем Mac и удалите старые производные данные (путь по умолчанию: / Users / YOUR_USER_NAME / Library / Developer / Xcode / DerivedData)
  • Откройте Xcode и соберите

После архивации сборки и снова отправьте приложение ...

person emreoktem    schedule 11.09.2015
comment
В мире снов - deep будет работать так, как ожидалось, но мы не живем в мире снов ... - person mike; 26.10.2018

Одна вещь, о которой я здесь не упоминаю, - это то, что вам нужно иметь свой Info.plist внутри / Resources внутри каталога версионной платформы. В противном случае вы получите ошибку «формат пакета нераспознан, недействителен или неподходящий» при попытке подписать каталог с версией.

Я дал здесь более развернутый ответ: Как сделать Codesign Growl.framework для изолированного приложения Mac

person Ross Bencina    schedule 09.08.2013