Как кодирате рамкови пакети за 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 казва:

Рамки за подписване

Тъй като рамките са пакети, изглежда логично да заключим, че можете да подпишете рамка директно. Това обаче не е така. За да избегнете проблеми при подписване на рамки, уверете се, че подписвате конкретна версия, а не цялата рамка:

# Това е грешният начин:

codesign -s my-signing-identity ../FooBarBaz.framework

# Това е правилният начин:

codesign -s my-signing-identity ../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

За забавление се опитах да подпиша пакета рамка директно и той все още беше отхвърлен. Но точно това е, което документацията каза да не се прави.

Някакви предположения защо това ще се счита за невалидно? Използвам същия сертификат, който използвам за кодиране на моето приложение -- този, който е работил в миналото.

Единственото ми предположение би било нещо общо със съществуващите plists (трябва ли да притежавам идентификаторите в 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
@Andrew, промяната на идентификатора на пакета свърши ли работа за теб?   -  person csexton    schedule 12.10.2011
comment
@csexton, още не съм го пробвал. При следващата актуализация ще се занимавам още малко с него. Едно нещо, за което трябва да внимавате, е използването на lipo (за премахване на поддръжката на 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 разработих този shell скрипт, който кодира всички мои рамки и други бинарни ресурси/спомагателни изпълними файлове (текущо поддържани типове: dylib, пакет и елементи за влизане):

#!/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. Създайте своето приложение. Всички пакетни рамки ще бъдат кодирани.

Ако все още получавате грешка „Идентичност: двусмислена (съвпада с: …), моля, коментирайте по-долу. Това повече не трябва да се случва.

Актуализирано 2012-11-14: Добавяне на поддръжка за рамки със специални символи в името им (това не включва единични кавички) към „codesign-frameworks.sh“.

Актуализирано 2013-01-30: Добавяне на поддръжка за специални символи във всички пътища (това трябва да включва единични кавички) към „codesign-frameworks.sh“.

Актуализирано 2013-10-29: Добавяне на експериментална поддръжка на dylib.

Актуализирано 2013-11-28: Добавяне на поддръжка за права. Подобряване на експерименталната поддръжка на dylib.

Актуализирано 2014-06-13: Коригиране на проблеми с кодовия дизайн с рамки, съдържащи (вложени) рамки. Това беше направено чрез добавяне на опция -depth към find, което кара find да направи първо обхождане в дълбочина. Това се наложи поради проблема, описан тук. Накратко: съдържащ пакет може да бъде подписан само ако неговите вложени пакети вече са подписани.

Актуализирано 2014-06-28: Добавяне на поддръжка на експериментален пакет.

Актуализирано 2014-08-22: Подобряване на кода и предотвратяване на неуспешно възстановяване на IFS.

Актуализирано 2014-09-26: Добавяне на поддръжка за елементи за влизане.

Актуализирано 2014-10-26: Проверки на директория с цитати. Това коригира грешките „ред 31/42: твърде много аргументи“ и произтичащата грешка „кодовият обект изобщо не е подписан“ за пътища, включващи специални знаци.

Актуализирано 2014-11-07: Разрешаване на грешката при нееднозначна самоличност (като „Разработчик на Mac: нееднозначна…“) при използване на автоматично разрешаване на самоличност в Xcode. Вече не е необходимо изрично да задавате самоличността и можете просто да използвате „Mac Developer“!

Актуализирано 2015-08-07: Подобряване на семантиката.

Подобренията са добре дошли!

person JanX2    schedule 01.07.2012
comment
Благодаря за това, но само бележка, не работи, ако вашата цел има интервал в името си. Опитах се да поправя, но не можах да го накарам да работи, така че промених целта. - person Craig; 10.07.2012
comment
Трябва да работи сега, когато FRAMEWORK_DIR има интервали/специални знаци в името си. - person JanX2; 16.07.2012
comment
Трябваше обаче също така да деактивирам опцията за времево клеймо, като добавих --timestamp в края на командата за кодиране. - 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
Elmer Cat -- Не знам каква версия на 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 - това не работи за dylibs, но поправката е лесна - променете вашата sed команда на нещо като: sed -e "s/\(.*framework\)/\1\/Versions\/A\//" - person Adrian; 27.11.2013
comment
Благодаря @Adrian! Просто добави това и някои други неща. - person JanX2; 28.11.2013
comment
Перфектно!! Yosemite изисква подписване на всички рамки на подписано приложение. В моя случай разпространявам извън 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:

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 App в тестова среда

person Ross Bencina    schedule 09.08.2013