美文网首页收藏iosiOS技术专题
iOS App 签名过程及重签

iOS App 签名过程及重签

作者: Caolongs | 来源:发表于2018-05-10 15:32 被阅读1031次

    iOS App 签名

    目的:

    保证 iOS 平台对第三方 APP 有绝对的控制权,每一个安装到 iOS 上的 APP 都是经过苹果官方允许的。

    签名过程

    image.png
    1. 在你的 Mac 开发机器生成一对公私钥,这里称为公钥L,私钥L。L:Local
    2. 苹果自己有固定的一对公私钥,跟上面 AppStore 例子一样,私钥在苹果后台,公钥在每个 iOS 设备上。这里称为公钥A,私钥A。A:Apple
    3. 把公钥 L 传到苹果后台,用苹果后台里的私钥 A 去签名公钥 L。得到一份数据包含了公钥 L 以及其签名,把这份数据称为证书。
    4. 在苹果后台申请 AppID,配置好设备 ID 列表和 APP 可使用的权限,再加上第③步的证书,组成的数据用私钥 A 签名,把数据和签名一起组成一个 Provisioning Profile 文件,下载到本地 Mac 开发机。
    5. 在开发时,编译完一个 APP 后,用本地的私钥 L 对这个 APP 进行签名,同时把第④步得到的 Provisioning Profile 文件打包进 APP 里,文件名为 embedded.mobileprovision,把 APP 安装到手机上。
    6. 在安装时,iOS 系统取得证书,通过系统内置的公钥 A,去验证 embedded.mobileprovision 的数字签名是否正确,里面的证书签名也会再验一遍。
    7. 确保了 embedded.mobileprovision 里的数据都是苹果授权以后,就可以取出里面的数据,做各种验证,包括用公钥 L 验证APP签名,验证设备 ID 是否在 ID 列表上,AppID 是否对应得上,权限开关是否跟 APP 里的 Entitlements 对应等。

    概念和操作

    上面的步骤对应到我们平常具体的操作和概念是这样的:

    1. 第 1 步对应的是 keychain 里的 “从证书颁发机构请求证书”,这里就本地生成了一对公私钥,保存的 CertificateSigningRequest 就是公钥,私钥保存在本地电脑里。
    2. 第 2 步苹果处理,不用管。
    3. 第 3 步对应把 CertificateSigningRequest 传到苹果后台生成证书,并下载到本地。这时本地有两个证书,一个是第 1 步生成的,一个是这里下载回来的,keychain 会把这两个证书关联起来,因为他们公私钥是对应的,在XCode选择下载回来的证书时,实际上会找到 keychain 里对应的私钥去签名。这里私钥只有生成它的这台 Mac 有,如果别的 Mac 也要编译签名这个 App 怎么办?答案是把私钥导出给其他 Mac 用,在 keychain 里导出私钥,就会存成 .p12 文件,其他 Mac 打开后就导入了这个私钥。
    4. 第 4 步都是在苹果网站上操作,配置 AppID / 权限 / 设备等,最后下载 Provisioning Profile 文件。
    5. 第 5 步 XCode 会通过第 3 步下载回来的证书(存着公钥),在本地找到对应的私钥(第一步生成的),用本地私钥去签名 App,并把 Provisioning Profile 文件命名为 embedded.mobileprovision 一起打包进去。这里对 App 的签名数据保存分两部分,Mach-O 可执行文件会把签名直接写入这个文件里,其他资源文件则会保存在 _CodeSignature 目录下。
    6. 第 6 – 7 步的打包和验证都是 Xcode 和 iOS 系统自动做的事。

    这里再总结一下这些概念:

    1. 证书:内容是公钥或私钥,由其他机构对其签名组成的数据包。
    2. Entitlements:包含了 App 权限开关列表。
    3. CertificateSigningRequest:本地公钥。
    4. p12:本地私钥,可以导入到其他电脑。
    5. Provisioning Profile:包含了 证书 / Entitlements 等数据,并由苹果后台私钥签名的数据包。

    iOS APP 重签名具体操作(手动)

    1. 干掉插件Plugins文件夹里面的内容!

    2. Watch 文件删除

    3. 对 Frameworks 进行签名!

      `$ codesign -fs "证书" xxx.framework`
      
    4. 给可执行文件执行权限! chmod +x WeChat

    5. 拷贝描述文件(可新建工程,获取app包中embedded.mobileprovision)

    6. 修改info.plist 的Bundle ID(与描述文件工程一致)

    7. 生成plist的权限文件en.plist(复制embedded.mobileprovision权限内容),放到Payload目录下

      <key>keychain-access-groups</key>
              <array>
                  <string>X7Y****CQ.*</string>
              </array>
              <key>get-task-allow</key>
              <true/>
              <key>application-identifier</key>
              <string>X7Y****JCQ.*</string>
              <key>com.apple.developer.team-identifier</key>
              <string>X7Y****CQ</string>
      
    8. 签名整个APP!

      $ codesign -fs "iPhone Developer: xxxxxx (6ZBE4C573L)"  --no-strict --entitlements=en.plist WeChat.app
      
    9. 打包其实就是一个zip

      $ zip -ry WeChat.ipa Payload
      

    iPhone Developer: shan jingjing (3QDN5929LL)

    1. 安装到手机

    Xcode->Window->Devices and Simulators->Devices INSTALL APP 点击+选中WeChat.ipa

    iOS APP 利用Xcode重签名

    1. 创建工程,替换Product下的app

    2. 修改Bundle identifier与新建工程一致

    3. Plugins、Watch 文件删除

    4. Framework重签名

      `$ codesign -fs "证书" xxx.framework`
      
    5. 给可执行文件执行权限! chmod +x WeChat

    6. Xcode 运行安装至手机

    iOS APP 脚本自动化重签名

    1. 新建工程,添加Run Script脚本
    image.png
    # ${SRCROOT} 它是工程文件所在的目录
    TEMP_PATH="${SRCROOT}/Temp"
    #资源文件夹
    ASSETS_PATH="${SRCROOT}/TargetAPP"
    #ipa包路径
    TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
    
    #新建Temp文件夹
    rm -rf "${SRCROOT}/Temp"
    mkdir -p "${SRCROOT}/Temp"
    
    #----------------------------------------
    # 1. 解压IPA到Temp下
    unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
    # 拿到解压的临时的APP的路径
    TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
    # echo "路径是:$TEMP_APP_PATH"
    
    
    #----------------------------------------
    # 2. 将解压出来的.app拷贝进入工程下
    # BUILT_PRODUCTS_DIR 工程生成的APP包的路径
    # TARGET_NAME target名称
    TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
    echo "app路径:$TARGET_APP_PATH"
    
    rm -rf "$TARGET_APP_PATH"
    mkdir -p "$TARGET_APP_PATH"
    cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH"
    
    
    #----------------------------------------
    # 3. 删除extension和WatchAPP.个人证书没法签名Extention
    rm -rf "$TARGET_APP_PATH/PlugIns"
    rm -rf "$TARGET_APP_PATH/Watch"
    
    
    #----------------------------------------
    # 4. 更新info.plist文件 CFBundleIdentifier
    #  设置:"Set : KEY Value" "目标文件路径"
    /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
    
    
    #----------------------------------------
    # 5. 给MachO文件上执行权限
    # 拿到MachO文件的路径
    APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1|cut -f2 -d\>|cut -f1 -d\<`
    #上可执行权限
    chmod +x "$TARGET_APP_PATH/$APP_BINARY"
    
    
    #----------------------------------------
    # 6. 重签名第三方 FrameWorks
    TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
    
    if [ -d "$TARGET_APP_FRAMEWORKS_PATH" ];
    then
    for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
    do
    
    if test -f  $FRAMEWORK
        then
        #签名
        /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
        fi
    done
    fi
    
    


    命令

    查看描述文件信息:$ security cms -D -i 描述文件路径
    
    查看APP的签名信息
    $ codesign -vv -d APP路径(.app)
    
    查看本机所有证书
    $ security find-identity -v -p codesigning
    
    查看可执行文件的加密信息!
    $ otool -l WeChat | grep crypt
    
    签名
    $ codesign -fs "证书" 需要签名的文件
    

    参考

    iOS App 签名的原理

    [toc]

    相关文章

      网友评论

        本文标题:iOS App 签名过程及重签

        本文链接:https://www.haomeiwen.com/subject/zxazrftx.html