App签名机制与重签名

App的签名机制 【Xcode是如何将App安装到手机的】

  • App的签名机制

  • iOS签名机制,保证安装到用户手机上的app都是经过apple官方允许的,现在xcode已经自动实现了下述操作

    1. 生成certificateSigningRequest.cerSigningRequeset文件,mac的公钥及其他信息打包后的csr文件
    2. 获得ios_*.cer证书,CA用apple后台pri加密生成,一次签名
    3. 注册device,添加appid
    4. 获得*.mobileprovision文件,选证书+appid+device再用apple的pri加密后的文件 二次签名
      image.png

    image.png

XCode签名需要用到的理论知识

  • RSA加密算法,一种非对称的加密算法,用于通信。这种算法通常是客户端持有公钥,服务端持有私钥。客户端利用公钥加密。服务端可以用私钥解密。服务利用私钥加密数据发给客户端,客户端可以利用公钥解密出来。【简单来说就是:公钥加密的数据,利用私钥可以解密;私钥加密的数据,公钥同样能解密】
  • 数字签名 客户端把【数据】,并利用公钥加密【数据的MD5】,然后把这【数据】与【机密后的MD5】发给服务器 服务器获取到数据包后,先求出【数据】的MD5,并解密【数据的MD5】,然后两者进行对比,如果不一样就代表数据被截获串改了

XCode如何将App安装到手机的【首先这个流程会涉及到2次数字签名】

  • 从appstore下载安装的没有*.mobileprovision文件的
  1. Mac电脑本地生成公钥和私钥,通过CSR(cerfification signing request) 把自己的公钥打包成CSR文件发给服务器。
  2. 苹果服务器利用自己的私钥,对 Mac电脑的公钥进行数字签名,生成证书与描述文件,将证书与描述文件返回给Mac电脑。 一次签名
  3. Mac电脑利用私钥对App的可执行文件的Hash值进行加密,生成App的签名 二次签名
  4. Mac 将 App的可执行文件、App的签名、证书【关联Mac的私钥】、描述文件 打包成一个App传输给手机
  5. 手机将会使用苹果的公钥,对证书解析,获得Mac的公钥。利用Mac的公钥,解析App签名,获取Hash值进行认证,认证成功则App成功安装上,认证失败就无法安装。
# 查看csr文件信息
openssl req -noout -text -in CertificateSigningRequest.certSigningRequest

#授权机制(Entitlements)

  • 简单说它就是一个沙盒的配置列表,上面列出了哪些行为被允许,哪些会被拒绝
    • codesign -d -entitlements -xx.app 查看授权列表
      • 常见的 get-task-allow true

#配置文件(Provisioning)

  • appid
  • 使用的证书
  • 功能授权列表
  • 可安装的设备列表
  • 苹果签名

#重签名的四种方式
#####重签名APP

  • 手动重签名【这种方法很复杂,容易出错,不过更接近原理】
  • 使用Xcode进行重签名【在手动重签的基础上,利用XCode的功能执行部分操作,这种方法比较简单】
  • 使用XCode脚本自动签名【首选的方法】
  • 使用Monkey自动签名【Monkey的原理其实就是第三种方法】

#手动重签名APP

  • 准备,【砸壳有两种方式(Clutch、dumpdecrypted)现在暂时从PP助手上面下载IPA包】
  • 解压ipa,找到Payload文件夹下的 .app 文件
  • 如何判断一个APP是否被砸过壳 砸过壳的App会有两个特点:没有签名信息和已经解过密了
    • 查看.app文件的签名信息
    $codesign -vv -d /Users/liangze/Desktop/砸壳的APPS/i11/i11/TargetApp/i9/Payload/kdweibo.app
    =>
    Executable=/Users/liangze/Desktop/砸壳的APPS/i11/i11/TargetApp/i9/Payload/kdweibo.app/kdweibo
    Identifier=com.kdweibo.client
    Format=app bundle with Mach-O universal (armv7 arm64)
    CodeDirectory v=20500 size=825694 flags=0x0(none) hashes=12896+7 location=embedded
    Signature size=4390
    Authority=(unavailable)  //权限这个地方是unavailbale(不可用)
    Info.plist=not bound
    TeamIdentifier=8M8Y7973D3
    Sealed Resources version=2 rules=45 files=1495
    Internal requirements count=1 size=100
    
    • 查看.app文件里面可执行文件的加密信息 获取给可执行文件的加密信息
      .app/可执行文件
    $otool -l kdweibo | grep crypt
    =>
    cryptoff 16384
    cryptsize 46481408
    cryptid 0
    cryptoff 16384
    cryptsize 50298880
    cryptid 0 
    

    因为cryptid的值为0,代表已经被解密了,砸壳是PP助手帮我们做的

  • 开始手动去重签名
    • 由于 Plugins/Wacth 里面是一些拓展插件 个人的证书没办法签extension,签名后无法正常安装到手机上,需要删掉
      Monkey的签名脚本中是这样删的
    • 签名extension 是一样的 codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" ....
    $rm -rf "$TARGET_APP_PATH/PlugIns" || true
    $rm -rf "$TARGET_APP_PATH/Watch" || true
    
    • 需要对APP用到的每一个动态库【framework/dylib】进行签名
      • 首先签名需要你有苹果开发者账号的开发证书
      • 查看我们可以用来签名的证书信息
      $security find-identity -v -p codesigning
      =>
      1) 84C7A63045A87D9A9A2EDDDA44B7BFB3EA16E268 "iPhone Distribution: Beijing Rongzhi Technology Co., Ltd. (58Y74FY8QK)"
      2) D7708AE17558290755DC44A5B3460AA5A3FF2466 "iPhone Developer: 泽 梁 (WVZ5JP3N7M)"
      
      • 签名动态库【这里需要把.app/Frameworks目录下的所有动态库进行签名】
        $codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" YZJEvent.framework
        $codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" Lottie.framework
        $codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" FLAnimatedImage.framework
        $codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" ExMasonry.framework
        $codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" ExCountly.framework
        $codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" Differentiator.framework
        ""

      • 给.app下的可执行文件执行权限

      $ls -l kdweibo 查看文件权限 
      =>
      -rwxr-xr-x@ 1 liangze  staff  115532224 11  8  2018 kdweibo
      $chmod +x kdweibo
      $ls -l kdweibo 查看文件权限 
      =>
      -rwxr-xr-x@ 1 liangze  staff  115532224 11  8  2018 kdweibo
      
      • 添加描述文件(可以在编译器编译后,对Products->.app点show in finder拿 embedded.mobileprovision),
        同时,修改Info.plist里面的BundleID ,这个要和mobileprovision里的是一样的
      • 生成权限文件 通过我们刚才生成描述文件中,查询出权限信息
        新建一个Entitlements.plist文件把权限信息拷贝进来,这样就得到我们自己的权限文件了,这个可以保存着一直用,只改bundlerID。
      $security cms -D -i /Users/liangze/Documents/VSCode/ARM/embedded.mobileprovision
      => 
       <key>Entitlements</key>
          <dict>
                                                  <key>com.apple.security.application-groups</key>
                  <array></array>
                                                  <key>application-identifier</key>
                  <string>58Y74FY8QK.com.fbbc.supi9</string>
                                                  <key>keychain-access-groups</key>
                  <array>
                                  <string>58Y74FY8QK.*</string>
                  </array>
                                                  <key>get-task-allow</key>
                  <true/>
                                                  <key>com.apple.developer.team-identifier</key>
                  <string>58Y74FY8QK</string>
      
          </dict>
      
      • 把新的权限文件放到.app文件的同级目录下,使用权限文件,签名整个APP
      $codesign -fs "iPhone Developer: 泽 梁 (WVZ5JP3N7M)" --no-strict --entitlements=Entitlements.plist kdweibo.app
      
      • 装到手机上 使用 Devices and Simulators 成功安装到手机上
      • 检查iOS IPA文件的签名信息 用81行的 命令查看 .app里的 mobileprovision $security cms -D -i embedded.mobileprovision

#使用XCode脚本自动签名【仿照Monkey】 在项目下创建一个APP的文件夹,只要在哪个文件夹放置ipa包,就能制动重签名安装到自己的手机

  1. 先将需要重签名的ipa包放置到APP目录下
  2. 在项目运行前执行脚本 sh autoResigning.sh