W jaki sposób projektujecie pakiety ram dla Mac App Store?

81

Po ostatnim zgłoszeniu otrzymałem następujący błąd:

Nieprawidłowy podpis - zagnieżdżony pakiet aplikacji (FooBar.app/Contents/Frameworks/GData.framework) nie jest podpisany, podpis jest nieprawidłowy lub nie jest podpisany certyfikatem przesłania Apple. Więcej informacji zawiera Podręcznik podpisywania kodu i piaskownicy aplikacji.

Nieprawidłowy podpis - zagnieżdżony pakiet aplikacji (FooBar.app/Contents/Frameworks/Growl.framework) nie jest podpisany, podpis jest nieprawidłowy lub nie jest podpisany certyfikatem przesłania Apple. Więcej informacji zawiera Podręcznik podpisywania kodu i piaskownicy aplikacji.

Nieprawidłowy podpis - zagnieżdżony pakiet aplikacji libcurl (FooBar.app/Contents/Frameworks/libcurl.framework) nie jest podpisany, podpis jest nieprawidłowy lub nie jest podpisany certyfikatem przesyłania firmy Apple. Więcej informacji zawiera Podręcznik podpisywania kodu i piaskownicy aplikacji.

Więc podpisałem wszystkie paczki frameworka zgodnie z 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 mówi:

Struktury podpisywania

Biorąc pod uwagę, że frameworki są pakietami, logiczne byłoby stwierdzenie, że można bezpośrednio podpisać strukturę. Jednak tak nie jest. Aby uniknąć problemów podczas podpisywania frameworków, upewnij się, że podpisujesz konkretną wersję, a nie cały framework:

# To jest zły sposób:

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

# To jest właściwy sposób:

codeign -s my-signing-identity ../FooBarBaz.framework/Versions/A

A kiedy próbuję zweryfikować wyniki, wygląda to dobrze:

% 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

Dla zabawy próbowałem bezpośrednio podpisać pakiet frameworka i nadal został odrzucony. Ale to jest dokładnie to, czego dokumentacja mówi, że nie należy robić.

Jakieś przypuszczenia, dlaczego miałoby to zostać uznane za nieważne? Używam tego samego certyfikatu, którego używam do kodowania podpisywania mojej aplikacji - tego, który działał w przeszłości.

Moje jedyne przypuszczenie to coś związanego z istniejącymi plistami (czy muszę posiadać identyfikatory w Info.plists frameworka?) Lub uprawnieniami - jakieś sugestie?

csexton
źródło
Odkryłem to również wcześniej, kiedy złożyłem aplikację. Na szczęście Apple nie odrzuciło tego, ale zauważyło, że później będziemy musieli podpisać ramy. Myślę, że lepiej jest publikować posty na stronie z problemami z kodem Google Growl i już wkrótce ludzie napotkają ten sam problem.
koo
2
Wystąpił również ten problem podczas przesyłania aplikacji z frameworkiem Growl. Domyślam się, że będziesz musiał zmienić identyfikator pakietu growl.framework na taki, który posiadasz, a następnie go kodować.
Andrew,
To dziwne: opublikowałem aplikację, która zawiera dwa frameworki (CorePlot i MacRuby), oba niepodpisane. Uruchomiłem polecenie podpisania kodu na pakiecie aplikacji tylko raz, a aplikacja została zaakceptowana bez komentarza na temat frameworka. Teraz, jeśli spojrzysz na pakiet aplikacji ( bit.ly/charterapp ), oba frameworki wydają się być podpisane. Czy próbowałeś po prostu podpisać całą aplikację?
p4010,
@ p4010, zrobiłem - wcześniej były niepodpisane. Na przykład warczenie było po prostu prostym zawiniątkiem, które rozdają. Teraz mam tę aplikację w sklepie od jakiegoś czasu, więc zakładam, że ma to związek z nową piaskownicą. Kiedy przesłałeś swoją aplikację?
csexton
@Andrew, czy zmiana identyfikatora pakietu zadziałała dla Ciebie?
csexton

Odpowiedzi:

46

Opierając się na odpowiedzi baptr, opracowałem ten skrypt powłoki, który koduje wszystkie moje frameworki i inne zasoby binarne / pomocnicze pliki wykonywalne (obecnie obsługiwane typy: dylib, bundle i elementy logowania):

#!/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. Zapisz go do pliku w swoim projekcie. Trzymam swoją kopię w Scriptspodkatalogu w katalogu głównym mojego projektu.
    • Mój jest nazywany codesign-frameworks.sh.
  2. Dodaj fazę kompilacji „Uruchom skrypt” zaraz po fazie budowania „Kopiuj wbudowane struktury”.
    • Możesz to nazwać „Codesign Embedded Frameworks”.
  3. Wklej ./codesign-frameworks.sh(lub jakkolwiek nazwałeś swój skrypt powyżej) do pola tekstowego edytora skryptów. Użyj, ./Scripts/codesign-frameworks.shjeśli przechowujesz skrypt w podkatalogu.
  4. Zbuduj swoją aplikację. Wszystkie dołączone frameworki będą oznaczone kodem.

Jeśli nadal otrzymujesz błąd „ Tożsamość : niejednoznaczne (pasuje:…”), skomentuj poniżej. To nie powinno już się zdarzać.

Zaktualizowano 14.11.2012: Dodanie obsługi frameworków ze znakami specjalnymi w nazwie (nie obejmuje to apostrofów) do „codign-frameworks.sh”.

Zaktualizowano 30.01.2013: Dodanie obsługi znaków specjalnych we wszystkich ścieżkach (powinno to obejmować apostrofy) do „codign-frameworks.sh”.

Zaktualizowano 29.10.2013: Dodanie eksperymentalnej obsługi dylib.

Zaktualizowano 28.11.2013: Dodawanie obsługi uprawnień. Poprawa obsługi eksperymentalnej dylib.

Zaktualizowano 13.06.2014: Naprawianie problemów z podpisywaniem kodów w frameworkach zawierających (zagnieżdżone) frameworki. Dokonano tego poprzez dodanie -depthopcji do find, która powoduje findwykonanie przejścia w głąb. Stało się to konieczne ze względu na opisany tutaj problem . W skrócie: paczka zawierająca może zostać podpisana tylko wtedy, gdy jej paczki zagnieżdżone są już podpisane.

Zaktualizowano 28.06.2014: Dodanie obsługi pakietów eksperymentalnych.

Zaktualizowano 22.08.2014: Poprawianie kodu i zapobieganie niepowodzeniom w przywracaniu IFS.

Zaktualizowano 26.09.2014: Dodanie obsługi elementów logowania.

Zaktualizowano 26.10.2014: Cytowanie sprawdzeń katalogu. To naprawia błędy „linia 31/42: zbyt wiele argumentów” i wynikowy błąd „obiekt kodu nie jest w ogóle podpisany” dla ścieżek zawierających znaki specjalne.

Zaktualizowano 07.11.2014: Rozwiązywanie niejednoznacznego błędu tożsamości (np. „Mac Developer: niejednoznaczny…”) podczas korzystania z automatycznego rozpoznawania tożsamości w Xcode. Nie musisz już jawnie ustawiać tożsamości i możesz po prostu użyć „Mac Developer”!

Zaktualizowano 07.08.2015: Poprawa semantyki.

Mile widziane ulepszenia!

JanX2
źródło
Dzięki za to, tylko uwaga, to nie zadziała, jeśli twój cel ma spację w nazwie. Próbowałem to naprawić, ale nie mogłem go uruchomić, więc zmieniłem cel.
Craig,
Powinien działać teraz, gdy FRAMEWORK_DIR ma w nazwie spacje / znaki specjalne.
Sty X2,
Jednak musiałem również wyłączyć opcję timestamp, dodając „--timestamp” na końcu polecenia coding.
Elmer Cat,
Ciekawy. Czy przypadkiem jesteś @Elmer Cat, robiąc to na niewydanej wersji OS X? Strona podręcznika opisuje tę opcję „domyślnego zachowania specyficznego dla systemu”.
JanX2
1
Elmer Cat - Nie wiem, z jakiej wersji Xcode korzystasz, ale jestem na 5.0.1 i zdecydowanie NIE podpisuje moich frameworków automatycznie. Wyrywałem sobie włosy, dopóki nie znalazłem tego scenariusza.
Bryan
11

Twój komentarz pokazuje, że podpisałeś obiekty w katalogu wersji pakietu. Technote pokazuje, jak podpisać sam katalog.

Poniższe informacje lepiej pasują do noty technicznej:

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
baptr
źródło
4

Tak to naprawiłem;

  • Wejdź do ustawień kompilacji celu
  • Znajdź wiersz „Inne flagi do podpisywania kodu”
  • Wprowadź wartość --deep do parametru release
  • Zamknij XCode
  • Wejdź do folderu danych pochodnych na komputerze Mac i usuń stare dane pochodne (domyślna ścieżka to: / Users / YOUR_USER_NAME / Library / Developer / Xcode / DerivedData)
  • Otwórz Xcode i skompiluj

Po utworzeniu archiwum i ponownie prześlij aplikację ...

emreoktem
źródło
3
W świecie snów „głęboki” działałby zgodnie z oczekiwaniami, ale nie żyjemy w świecie marzeń ...
mike
0

Jedną rzeczą, o której tutaj nie wspomniałem, jest to, że musisz mieć swój plik Info.plist w / Resources wewnątrz wersjonowanego katalogu frameworka. W przeciwnym razie podczas próby podpisania wersjonowanego katalogu pojawi się błąd „Nierozpoznany, nieprawidłowy lub nieodpowiedni format pakietu”.

Podałem bardziej rozszerzoną odpowiedź tutaj: Jak kodować Growl.framework dla aplikacji Sandboxed Mac

Ross Bencina
źródło