你如何为Mac App Storedevise框架绑定?

最近提交后,我得到了以下错误:

无效的签名 – 嵌套的应用程序包(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

当我试图validation结果时,对我来说看起来很好:

 % 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中的标识符?)或权利 – 任何build议吗?

基于baptr的回答,我开发了这个shell脚本,它为所有的框架和其他二进制资源/辅助可执行文件(当前支持的types:dylib,bundle和login项目)进行编码:

 #!/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. 将其保存到项目中的文件中。 我把我的副本保存在项目根目录下的Scripts子目录中。
    • 我的名字叫codesign-frameworks.sh
  2. 在“复制embedded式框架”构build阶段之后立即添加“运行脚本”构build阶段。
    • 你可以把它称为“Codesign Embedded Frameworks”。
  3. ./codesign-frameworks.sh (或上面所说的脚本)粘贴到脚本编辑器文本字段中。 如果将脚本存储在子目录中,请使用./Scripts/codesign-frameworks.sh
  4. build立你的应用程序 所有捆绑的框架将被编码。

如果你仍然得到“ 身份 :模棱两可(匹配:…”错误,请在下面评论,这不应该发生了。

2012-11-14更新:在“codesign-frameworks.sh”中添加对名称中带有特殊字符(不包括单引号)的框架的支持。

更新2013-01-30:在“codesign-frameworks.sh”中添加对所有path中的特殊字符(这应包括单引号)的支持。

更新2013-10-29:添加实验dylib支持。

2013-11-28更新:添加权利支持。 改进实验性dylib支持。

更新2014年6月13日:解决与包含(嵌套)框架的框架代码签名问题。 这是通过添加-depth选项来完成的,这会导致find执行深度优先遍历。 这是必要的,因为这里描述的问题 。 简而言之:如果包含的bundle已经被签名,那么它只能被签名。

更新2014-06-28:添加实验包支持。

更新2014-08-22:改进代码并防止无法恢复IFS。

更新2014-09-26:添加对login项目的支持。

更新2014-10-26:引用目录检查。 这将修复“行31/42:太多参数”错误,并导致包含特殊字符的path产生的“代码对象根本没有签名”错误。

更新2014年11月7日:在Xcode中使用自动身份parsing时,解决模糊身份错误(如“Mac开发人员:模糊…”)。 您不必明确设定身份,只需使用“Mac Developer”!

更新2015-08-07:改进语义。

改进欢迎!

您的评论显示您签署了捆绑包的版本目录中的对象。 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 

这是我如何解决它;

  • input目标的构build设置
  • find“其他代码签名标志”
  • input–deep参数的值
  • closuresXCode
  • input到Mac上派生的数据文件夹并删除旧的派生数据(默认path是:/ Users / YOUR_USER_NAME / Library / Developer / Xcode / DerivedData)
  • 打开Xcode和构build

在构build归档并再次提交应用程序…

我没有在这里提到的一件事是,你需要在版本化的框架目录里面有你的Info.plist / Resources。 否则,当您尝试对版本化的目录进行签名时,您会收到“捆绑格式无法识别,无效或不合适的”错误。

我在这里提供了更多的扩展答案: 如何为Sandboxed Mac App编码Growl.framework

Interesting Posts