美文网首页
代码签名

代码签名

作者: coder_feng | 来源:发表于2020-04-18 18:38 被阅读0次

    代码签名

    代码签名 是对可执行文件或脚本进行数字签名。用来确认软件在签名后未被修改或损坏的措施。和数字签名原理一样,只不过签名的数据是代码而已。

    苹果的需求

    • 安装包不需要上传到App Store,可以直接安装到手机上
    • 苹果味了保证系统的安全性,又必须对安装的APP有绝对的控制权
      • 经过苹果允许才可以安装
      • 不能被滥用导致非开发APP也能被安装
        为了实现这些需求,iOS签名的复杂度也开始增加,苹果采取的措施是双层签名


        image.png

    双层代码签名

    • 在Mac系统中生成非对称加密算法的一对公钥\私钥(Xcode代办了),这里成为公钥M,私钥M M=Mac
    • 苹果自己有固定的一对公私钥,跟之前AppStore原理一样,私钥在苹果后台,公钥在每个iOS系统当中,这里成为公钥A,私钥A,A=Apple
      -把公钥与及一些开发者信息传到苹果后台(这就是CSR文件),用苹果后台里的私钥A去签名公钥M。得到一份数据包含了公钥M与及其签名,把这份数据称为证书。

    描述文件

    描述文件(Provisioning profile)一般包括三样东西:证书,App ID,设备,当我们在真机运行或者打包一个项目的时候,证书用来证明我们程序的合法性。

    苹果为了解决应用滥用的问题,所以苹果又加了两个限制
    - 第一限制在苹果后台注册过的设备才可以安装
    - 第二限制只能针对某一个具体的APP
    并且苹果还想控制App里面的iCloud、PUSH、后台、调试器附加这些权限,所以苹果把这些权限开关同意成为Entitlements(授权文件),并把这个文件放在一个叫做Provisioning Profile描述文件中,描述文件是在AppleDevelop网站创建的(在Xcode中填上AppID会自动创建),Xcode运行时会打包进入app内,所以我们使用CSR申请证书的时候,我们还需要申请一个东西就是描述文件。在开发时,编译完一个APP后,用本地的私钥M对这个App进行签名,同时把苹果服务器得到的Provisioning Profile文件打包进入App里,文件名为embeded。mobileprovision,把App安装到手机,最后系统进行验证。
    

    应用重签名

    在原有的基础之上破坏原签名,之后使用合法的证书再进行重签

    codesign

    Xcode提供了签名工具:codesign,我们可以通过几个命令就可以完成重签名

    //列出钥匙串里可签名的证书
    $security find -identity -v -p codesigning 
    //强制替换签名
    $Codesign -fs "证书串" 文件名 强制替换签名
    //给文件添加权限
    $Chmod +x 可执行文件 给文件添加权限
    //查看描述文件
    $security cms -D -i ../embeded.mobileprovision 查看描述文件
    // APP包
    codesign -fs "证书串" --no-strict --entitlements=权限文件.plist APP 包
    //将输入文件压缩为输出文件
    Zip -ry 输出文件 输入文件
    
    重签名步骤
    • 1.删除插件和带有插件的.app 包(比如Watch)
    • 2.对Frameworks里面的库进行重签名(动态库)
    • 3.给可执行文件+x(可执行)权限
      -4 添加描述文件(新建工程,真机编译得到)
      -5.替换BundleID
      -6.通过授权文件(Entilements)重签名.app包
    SHELL脚本

    部分linux指令解释

    $source FileName:在当前shell环境中读取并执行FileName中的命令
    特点:命令可以强行让一个脚本去立即影响当前的环境(一般用于加载配置文件)。命令会强制执行脚本中的全部命令,而忽略文件的全向
    $base FileName、$zsh FileName:重新建立一个子shell,在子shell中执行脚本里面的句子
    $./FileName:读取并执行文件中的命令,但前提是脚本必须有可执行权限,也就是x
    
    用户组&文件权限

    Unix和Linux都是多用户,多任务的系统,所以这样的系统里面就拥有了用户,组的概念。那么同样文件的权限也就有相应的所属用户和所属组了。

    ➜  ~ ls -l
    total 0
    drwxr-xr-x   7 apple  staff   224 Apr 16 09:50 DarkModeAdjust
    drwx------@ 13 apple  staff   416 Apr 18 09:42 Desktop
    drwx------@ 23 apple  staff   736 Apr 18 17:32 Documents
    drwx------@ 28 apple  staff   896 Apr 18 17:07 Downloads
    drwxr-xr-x  24 apple  staff   768 Apr 13 11:59 work
    
    • 第一列:[ 权限 ]
    d:文件类型,代表目录(- 代表文件)
    r:read 读,w:write 写,x:excute 执行
    这三个权限的位置不会变,依次次rwx,出现-在对应位置,代表没有这个权限
    一个文件的完整权限,总共分为三组
    - 第一组:文件所有者的权限
    - 第二组:这一组其他用户的权限
    - 第三组:非本组用户的权限
    
    • 第二列:[ 连接 ]
    • 第三列:[ 所属组 ]
    • 第四列:[ 文件大小 ]
    • 第五列:[ 最后修改日期 ]
    • 第六列:[ 文件名称 ]

    改变权限:chmod指令
    文件权限的改变使用chmod命令,设置的方法有两种:数字类型改变和符号类型改变,由于文件权限分为三种身份:[user][group][other] 三个权限:[read][write][execute]

    • 数字类型:
      各个权限数字对照:r:4 w:2 x:1,举个例子说明一下,如果一个文件权限为[-rwxr-xr-x],那么久分别是对应着User:4+2+1=7,Group:4+0+1=5,Other:4+0+1=5;命令:chmod 755 文件名
    权限操作符 对应解释
    --- 0
    --x 1
    -w- 2
    -wx 3
    r-- 4
    r-x 5
    rw- 6
    rwx 7

    符号类型
    chmod [u、g、o、a] [+(加入)、-(除去)、=(设置) [r、w、x] 文件名称

    重签名的demo

    1.Xcode 结合脚本重签


    Snip20200424_71.png

    目录架构大致如上

    • APP目录 负责放置需要重签名的ipa
    • Temp 临时目录,负责放置解压的文档
      配置好bundleID和相关描述文件,让Xcode首先能真机编译,然后再在Xcode Build Phases添加一个Run Script脚本,内容大致如下
    # ${SRCROOT} 它是工程文件所在的目录
    TEMP_PATH="${SRCROOT}/Temp"
    ASSETS_PATH="${SRCROOT}/APP"
    TARGET_IPA_PATH="${ASSETS_PATH}/*.ipa"
    #清空Temp文件夹
    rm -rf "$TEMP_PATH"
    mkdir "$TEMP_PATH"
    
    #1.1将IPA解压到Temp下
    unzip -oqq "$TARGET_IPA_PATH" -d "$TEMP_PATH"
    
    #1.2拿到解压临时的APP路径
    TEMP_APP_PATH=$(set -- "$TEMP_PATH/Payload/"*.app;echo "$1")
    echo "TEMP:🍺$TEMP_APP_PATH"
    
    #2拷贝APP
    #2.1拿到当前工程下的APP路径
    TARGET_APP_PATH="$BUILT_PRODUCTS_DIR/$TARGET_NAME.app"
    echo "TARGET_APP_PATH🍺:$TARGET_APP_PATH"
    #2.2拷贝三方APP到我们的工程下
    cp -rf "$TEMP_APP_PATH/" "$TARGET_APP_PATH"
    
    #3干掉多余的部分
    rm -rf "$TARGET_APP_PATH/PlugIns"
    rm -rf "$TARGET_APP_PATH/Watch"
    #4修改info.plist 文件
    /usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier $PRODUCT_BUNDLE_IDENTIFIER" "$TARGET_APP_PATH/Info.plist"
    
    #5.给可执行文件上权限
    #添加ipa二进制的执行权限,否则xcode会告知无法运行
    #这个操作是要找到第三方app包里的可执行文件名称,因为info.plist的 'Executable file' key对应的是可执行文件的名称
    #我们grep 一下,然后取最后一行, 然后以cut 命令分割,取出想要的关键信息。存到APP_BINARY变量里
    APP_BINARY=`plutil -convert xml1 -o - $TARGET_APP_PATH/Info.plist|grep -A1 Exec|tail -n1 | cut -f2 -d\> | cut -f1 -d\<`
    
    echo "🍺:   $APP_BINARY"
    chmod +x "$TARGET_APP_PATH/$APP_BINARY"
    
    
    #6.重签名三方FrameWorks
    TARGET_APP_FRAMEWORKS_PATH="$TARGET_APP_PATH/Frameworks"
    for FRAMEWORK in "$TARGET_APP_FRAMEWORKS_PATH/"*
    do
    #echo "🍺FRAMEWORK:$FRAMEWORK"
    /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" "$FRAMEWORK"
    done
    
    Snip20200424_72.png 然后运行Xcode,会发现编译完毕,需要重签的app已经可以运行到自己的手机上面来了(我这里运行的是微信) Snip20200424_73.png

    使用纯脚本重签

    param_mobileprovision="/Users/forest/Documents/develop/forest.mobileprovision"
     param_cerName="iPhone Developer: Polly Wilbur (R2N9CWGB83)"
    
     unzip -qo "$param_ipa" -d extracted
    
     APPLICATION=$(ls extracted/Payload/)
    
     cp "$param_mobileprovision" "extracted/Payload/$APPLICATION/embedded.mobileprovision"
    
     echo "Resigning with certificate: $param_cerName" >&2
     find -d extracted  \( -name "*.app" -o -name "*.appex" -o -name "*.framework" -o -name "*.dylib" \) > directories.txt
    security cms -D -i "extracted/Payload/$APPLICATION/embedded.mobileprovision" > t_entitlements_full.plist
    /usr/libexec/PlistBuddy -x -c 'Print:Entitlements' t_entitlements_full.plist > t_entitlements.plist
    while IFS='' read -r line || [[ -n "$line" ]]; do
        /usr/bin/codesign --continue -f -s "$param_cerName" --entitlements "t_entitlements.plist"  "$line"
        echo "line: ${line}"
    done < directories.txt
    
     /usr/bin/codesign --continue -f -s "$param_cerName" --entitlements "t_entitlements.plist"  "extracted/Payload/$APPLICATION"
    
     echo "Creating the Signed IPA"
     cd extracted
     zip -qry ../extracted.ipa *
     cd ..
    
     ls_date=`date +%Y%m%d-%H%M%S`
      # ls_date=`date +%Y%m%d`
     # mv extracted.ipa "/Users/forest/Desktop/ReasignIPAProduct/${ls_date}_Signed.ipa"
      mv extracted.ipa "/Users/forest/Desktop/ReasignIPAProduct/${ls_date}_Signed.ipa"
     echo ${ls_date}_Signed.ipa
     rm -rf "extracted"
     rm directories.txt
     rm t_entitlements.plist
     rm d_full.plist
    

    这里需要事先提供描述文件,和证书,确认提供完毕之后,可以
    $sh sign.sh xxx.ipa
    执行完之后会在指定的路径生成一个重签后的ipa,这个ipa可以直接通过itools pro直接安装到手机上面去

    相关文章

      网友评论

          本文标题:代码签名

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