0%

超级签名详细实现

Because you have never seen the miracle. - 《银翼杀手2049》

超级签名是什么?

所谓的超级签名,其实一句话就能说清楚:使用了苹果提供给开发者的Ad-Hoc分发通道,把安装设备当做开发设备进行分发。

优势:直接分发,安装即可运行,不需要用户做企业证书的信任操作,不会有证书吊销导致的风险
劣势:成本昂贵,单开发者账号的iPhone设备数量只有100个,

实现流程

  1. 手机安装.mobileconf文件,将UDID发给服务器
  2. 服务器将收到的UDID注册到苹果开发者账号中,并更新描述文件
  3. 将更新后的描述文件来重签App
  4. 最后将重签的App上传至cdn,利用itms-services方式做分发下载

详细实现细节

  1. 准备好获取UDID的配置文件,也就是.mobileconf文件,文件内容大致如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

    <plist version="1.0">
    <dict>
    <key>PayloadContent</key>
    <dict>
    <key>URL</key>
    <!– 接收数据的接口地址 –>
    <string>http://106.54.214.191:443/udid/receive</string>
    <key>DeviceAttributes</key>
    <array>
    <string>UDID</string>
    <string>IMEI</string>
    <string>ICCID</string>
    <string>VERSION</string>
    <string>PRODUCT</string>
    </array>
    </dict>
    <key>PayloadOrganization</key>
    <string>www.qianniuniu.com</string>
    <key>PayloadDisplayName</key>
    <string>Test</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
    <key>PayloadUUID</key>
    <string>8C7AD0B8-3900-44DF-A52F-3C4F92921807</string>
    <key>PayloadIdentifier</key>
    <string>com.super.signature</string>
    <key>PayloadDescription</key>
    <string>该配置文件将帮助用户获取当前iOS设备的UDID号码。This temporary profile will be used to find and display your current device's UDID.</string>
    <key>PayloadType</key>
    <string>Profile Service</string>
    </dict>
    </plist>
  2. 使用服务器https证书对配置文件签名

    上图是服务器端生成的证书文件,这里使用的是Apache文件夹下面的

    mbaike.crt:https服务器端使用证书文件。
    mbaike.key:https服务器端使用证书对应的密钥。
    root_bundle.pem:与SSL证书对应的证书链(中级证书)。
    unsigned.mobilecofig 文件:IOS端生成的未签名的配置描述文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 再使用通过openssl命令生成签名后的signed.mobileconfig文件
    openssl smime -sign -in unsigned.mobileconfig -out signed.mobileconfig -signer mbaike.crt -inkey mbaike.key -certfile root_bundle.pem -outform der -nodetach

    # 也可以把key文件的密码写入到key文件中
    openssl rsa -in mbaike.key -out mbaikenopass.key

    # 第二步的命令就应该是
    openssl smime -sign -in unsigned.mobileconfig -out signed.mobileconfig -signer mbaike.crt -inkey mbaikenopass.key -certfile root_bundle.pem -outform der -nodetach

    这样就完成了对 mobileconfig 的签名工作了

  3. 上图是中点击 “获取UDID” ,就会跳到设置 -> 通用 -> 描述文件 去安装已经签名的描述文件

    如图显示已签名,说明第二步对 .mobilecofig 的签名是OK的,安装成功后,返回下载页面并调用http://106.54.214.191:443/udid/receive这个地址,服务器端就会收到UDID等信息

  4. 利用开源工具Spaceship,注册新的开发者设备到苹果开发者中心,并更新 Provisioning Profile,服务器端使用的是 ruby 脚本来完成这个功能:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #!/usr/bin/ruby -w
    require "spaceship"

    puts "======Hello, Write Start======"

    # 先登录
    Spaceship::Portal.login("1711218908@qq.com", "密码")

    is_bundle = Spaceship.app.find("com.super01.signature")
    if !is_bundle
    Spaceship.app.create!(bundle_id: "com.super01.signature", name: 'iosudid')
    end

    #group权限
    app = Spaceship::Portal.app.find("com.super01.signature")

    group = Spaceship::Portal.app_group.find("group.com.super01.signature")
    if !group
    group = Spaceship::Portal.app_group.create!(group_id: "group.com.super01.signature",name: "Another group")
    end
    app = app.associate_groups([group])
    app.update_service(Spaceship::Portal.app_service.network_extension.on)
    app.update_service(Spaceship::Portal.app_service.access_wifi.on)
    app.update_service(Spaceship::Portal.app_service.push_notification.on)
    app.update_service(Spaceship::Portal.app_service.game_center.on)

    # 新增设备的UDID
    Spaceship::Portal.device.create!(name: "那年星空", udid: "***")

    #更新设备
    allDevices = Spaceship.device.all
    device_profiles = Spaceship::Portal.provisioning_profile.ad_hoc.find_by_bundle_id(bundle_id: "com.super01.signature")
    device_profiles.each do |profile|
    profile.devices = allDevices
    profile.update!
    end

    #下载描述文件
    matching_profiles = Spaceship::Portal.provisioning_profile.ad_hoc.find_by_bundle_id(bundle_id: "com.super01.signature")
    if matching_profiles.first
    File.write("SuperSignatureAdHocProfile.mobileprovision", matching_profiles.first.download)
    else
    cert = Spaceship::Portal.certificate.production.all.first
    profile=Spaceship.provisioning_profile.ad_hoc.create!(bundle_id: "com.super01.signature", certificate: cert, name: "com.super01.signature adhoc")
    File.write("SuperSignatureAdHocProfile.mobileprovision", profile.download)
    end

    puts "====== Hello, Write End! ======"

  5. 制作.cer证书,这一步和我们平时做iOS开发一样,我就不多说了

  6. 重点来了,ipa包的重签,这里使用的是 zsign,将步骤3中更新后的描述文件和步骤4中的证书放在zsign项目的同一级目录下,如下图:

    20191114_01.png

    使用命令如下:

    1
    ./zsign -k key.p12 -p 123 -m SuperSignatureAdHocProfile.prov -o output.ipa SASpecs.app

    将重签好的ipa包上传至cdn服务器拿到下载链接,下一步开始制作分发文件。

  7. 分发文件(manifest.plist)需要准备两张图片的下载地址,文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    <key>items</key>
    <array>
    <dict>
    <key>assets</key>
    <array>
    <dict>
    <key>kind</key>
    <string>software-package</string>
    <key>url</key>
    <string>https://qnnapk-1251122539.cos.ap-shanghai.myqcloud.com/SASpecs.ipa</string>
    </dict>
    <dict>
    <key>kind</key>
    <string>display-image</string>
    <key>url</key>
    <string>https://qnnapk-1251122539.cos.ap-shanghai.myqcloud.com/57.png</string>
    </dict>
    <dict>
    <key>kind</key>
    <string>full-size-image</string>
    <key>url</key>
    <string>https://qnnapk-1251122539.cos.ap-shanghai.myqcloud.com/512.png</string>
    </dict>
    </array>
    <key>metadata</key>
    <dict>
    <key>bundle-identifier</key>
    <string>com.super.signature</string>
    <key>bundle-version</key>
    <string>1.0</string>
    <key>kind</key>
    <string>software</string>
    <key>platform-identifier</key>
    <string>com.apple.platform.iphoneos</string>
    <key>title</key>
    <string>SASpecs</string>
    </dict>
    </dict>
    </array>
    </dict>
    </plist>
  8. 当用户下载这个分发文件后就会安装对应的ipa包,

至此,大功告成