IOS 超级签名实现 (linux 版本)

前言

签名原理其实就一句话,使用了苹果提供给开发者的Ad-Hoc分发通道,把安装设备当做开发设备进行分发。

既然签名用是 Ad-Hoc ,那么 Ad-Hoc 所具有的优劣势也一并继承了下来:

优势:

直接分发,安装即可运行,不需要用户做企业证书的信任操作
目前稳定,不会有证书吊销导致的业务风险(后续苹果政策风险非常高)
缺点:

单开发者账号的iPhone设备数量只有100个,导致分发成本非常高(99美元/1年/100个设备)
开发者账号需要预先写入安装设备的UDID,在工具链不通的情况下,获取用户的UDID相对困难和繁琐,而且手动写入UDID不存在商用可行性,当然目前这个缺点被解决了

获取用户设备的UUID

过程参考
https://www.jianshu.com/p/fc0c2b24ac74

登录apple账号注册设备,生成新的mobileprovision

注意保存以下几个文件:

  • 生成的certificateSignRequest, certificateSignRequestPrivateKey
  • 生成的certificate文件
  • 生成的mobileprovision 文件

Apple Developer Center 自动化工具

可以使用fastlane-Spaceship来完成命令行登录appstore, 创建appid,创建certificate,更新profile等一系列操作,完美支持centos7+ 服务器
具体api 可参考 Spaceship Portal Api
然后编写ruby脚本来实现命令行完成profile更新, 脚本如下:

#
# 一键注册设备生成签名文件
# 使用ruby generate_provision.rb 来执行 需要安装ruby 命令
#
#
require "spaceship"

class PortalHandle
    # 初始化参数
    def initialize(appid,username,password,teamId,uuid,csrFile,provisionFile,crtFile)
        @appid = appid                                   # 新的appid
        @username = username                     # apple账号
        @password = password                      # apple账号密码
        @teamId = teamId                              # apple 团队id
        @registerUuid = uuid                          # 需要注册的设备uuid
        @csrFile = csrFile                                # 生成的csr文件,需要和签名用的key 成对
        @provisionFile = provisionFile             # 保存新profile路径
        @certificateFile = crtFile                      # 保存新certificate路径
    end

    #   登录苹果账号
    def login()
        Spaceship::Portal.login(@username,@password)
        Spaceship.client.team_id = @teamId
        say 'Login Success!'
    end


    # 注册新设备到此账号
    def registerDevice()
        current_device = Spaceship::Portal.device.find_by_udid(@registerUuid, include_disabled: true)
        if current_device == nil then
            Spaceship::Portal.device.create!(name: @registerUuid, udid: @registerUuid)
            say 'Register device into account'
        else
            current_device.enable!
            say 'Device exist in account. enable it'
        end
    end

    # 查找或者创建appid
    def createAppid()
        app = Spaceship::Portal.app.find(@appid)
        if app == nil then
            app = Spaceship::Portal.app.create!(bundle_id: @appid, name: "fastlane App")
            say 'Appid not exist generate...'
        end
        app.update_service(Spaceship::Portal.app_service.push_notification.on)
    end

    # 创建证书  如果存在则不创建
    def createCertificate()
        prod_certs = Spaceship::Portal.certificate.apple_distribution.all
        if 0 == prod_certs.length then
            # Create a new certificate signing request
            # csr, pkey = Spaceship::Portal.certificate.create_certificate_signing_request
            # Use the signing request to create a new distribution certificate
            # Spaceship::Portal.certificate.apple_distribution.create!(csr: csr)
            # csrFile = File.new('ios.certificateSignRequest','w')
            # csrFile.syswrite(csr)
            # csrFile.close
            # say 'Download csr Success...!'
            # keyFile = File.new('ios.key','w')
            # keyFile.syswrite(pkey)
            # keyFile.close
            # say 'Download privateKey success...!'
            # File.write('ios_producttion.cer',Spaceship::Portal.certificate.apple_distribution.all.first.download)
            # 从文件中读取csr 由于多个账号共享同一个csr和key
            csr = File.read(@csrFile)
            Spaceship::Portal.certificate.apple_distribution.create!(csr: csr)
        end
        # 下载certificate
        File.write(@certificateFile,Spaceship::Portal.certificate.apple_distribution.all.first.download)
        # 返回证书
        return  Spaceship::Portal.certificate.apple_distribution.all.first
    end

    # 生成ad_hoc profile
    def createAdhocProfile()
        # 创建并获得线上证书
        cert = createCertificate()
        # 获取
        # 创建最新的证书
        matching_profiles = Spaceship::Portal.provisioning_profile.ad_hoc.find_by_bundle_id(bundle_id: @appid)
        profile = nil
        if 0 == matching_profiles.length then
            profile = Spaceship::Portal.provisioning_profile.ad_hoc.create!(bundle_id: @appid,
                                                      certificate: cert,
                                                             name: 'profile_production_adhoc'+@appid)
        else
            devices = Spaceship::Portal.device.all
            profile = matching_profiles.first
            profile.devices = devices
            profile.update!
        end
        profile = Spaceship::Portal.provisioning_profile.ad_hoc.find_by_bundle_id(bundle_id: @appid).first
        provisionFileName = @provisionFile
        File.write(provisionFileName, profile.download)
    end
end

    appid                     = ARGV[0]
    username             = ARGV[1]
    password             = ARGV[2]
    teamId                 = ARGV[3]
    uuid                     = ARGV[4]
    csrFile                 = ARGV[5]
    provisionFile          = ARGV[6]
    certificateFile         = ARGV[7]

    handler = PortalHandle.new(appid,username,password,teamId,uuid,csrFile,provisionFile,certificateFile)
    # 登录
    handler.login()
    # 注册这个设备
    handler.registerDevice()
    # 查找或者创建appid
    handler.createAppid()
    # 创建证书
    handler.createAdhocProfile()

参考文章

IOS 超级签名原理

你可能感兴趣的:(IOS 超级签名实现 (linux 版本))