Post

iOS重签名读取本机所有描述文件

一、读取本机的所有描述文件

1.1、macapp使用xib启动后,获取本机的所有证书
ProvisioningProfile.getProfiles()

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
    // MARK: - 读取所有的描述文件
    static func getProfiles() -> [ProvisioningProfile] {
        var output: [ProvisioningProfile] = []
        let fileManager = FileManager()
        // 获取library文件夹地址
        // fiel:///Users/xxx/Library
        if let libraryDirectory = fileManager.urls(for: .libraryDirectory, in: .userDomainMask).first {
            // 获取Provisioning Profiles的路径
            // fiel:///Users/xxx/Library/MobileDevice/Provisioning Profiles
            let provisioningProfilesPath = libraryDirectory.path.stringByAppendingPathComponent("MobileDevice/Provisioning Profiles") as NSString
            // 读取所有描述文件
            let provisioningProfiles = try? fileManager.contentsOfDirectory(atPath: provisioningProfilesPath as String) {
                // 遍历查询所有的后缀是.mobileprovision的文件
                for provFile in provisioningProfiles {
                    if provFile.pathExtension == "mobileprovision" {
                        // 获取xxx.mobileprovision的完整地址
                        let profileFilename = provisioningProfilesPath.appendingPathComponent(provFile)
                        // 创建ProvisioningProfile对象
                        if let profile = ProvisioningProfile(filename: profileFilename) {
                            output.append(profile)
                        }
                    }
                }
            }
        }

        // 按crated时间进行排序
        output = output.sorted(by: {
            $0.created.timeIntervalSince1970 > $1.created.timeIntervalSince1970
        })
        // 对描述文件进行去重,以name+appid为唯一值去重
        var newProfiles = [ProvisioningProfile]()
        var names = [String]()
        for profile in output {
            if !names.contains("\(profile.name)\(profile.appID)") {
                newProfiles.append(profile)
                names.append("\(profile.name)\(profile.appID)")
                NSLog("\(profile.name), \(profile.created)")
            }
        }
        return newProfiles;
    }

1.2 使用Process调用命令/usr/bin/security读取xxx.mobileprovision的信息
1.3 使用PropertyListSerialization.propertyList解析数据成字典

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
init?(filename: String){
         // 使用/usr/bin/security cms -D -i读取xxx.mobileprovison信息
         let securityArgs = ["cms","-D","-i", filename]
         let taskOutput = Process().execute("/usr/bin/security", workingDirectory: nil, arguments: securityArgs)
         let rawXML: String
         if taskOutput.status == 0 {
             // 读取成功
            if let xmlIndex = taskOutput.output.range(of: "<?xml") {
                rawXML = taskOutput.output.substring(from: xmlIndex.lowerBound)
            } else {
                Log.write("Unable to find xml start tag in profile")
                rawXML = taskOutput.output
            }
            // 解析xml的内容
            if let results = try? PropertyListSerialization.propertyList(from: rawXML.data(using: String.Encoding.utf8)!, options: .mutableContainers, format: nil) as? [String : AnyObject] {
                // 解析出创建日期、过期日期、名称、Entitlements等信息
                if let expirationDate = results["ExpirationDate"] as? Date,
                    let creationDate = results["CreationDate"] as? Date,
                    let name = results["Name"] as? String,
                    let entitlements = results["Entitlements"] as? [String : AnyObject],
                    // "teamid.bundleId" -> 696GG234S.com.test.abc
                    let applicationIdentifier = entitlements["application-identifier"] as? String,
                    let periodIndex = applicationIdentifier.firstIndex(of: ".") {
                        self.filename = filename
                        self.expires = expirationDate
                        self.created = creationDate
                        // bundleId部分
                        self.appID = applicationIdentifier.substring(from: applicationIdentifier.index(periodIndex, offsetBy: 1))
                        // teamId部分
                        self.teamID = applicationIdentifier.substring(to: periodIndex)
                        self.name = name
                        self.entitlements = entitlements
                } else {
                    Log.write("Error processing \(filename.lastPathComponent)")
                    return nil
                }
            } else {
                Log.write("Error parsing \(filename.lastPathComponent)")
                return nil
            }
        } else {
            Log.write("Error reading \(filename.lastPathComponent)")
            return nil
        }
    }

读取本机的所有证书

使用/usr/bin/security find-identity -v -p codesigning读取证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@objc func getCodesigningCerts() -> [String] {
        var output: [String] = []
        let securityResult = Process().execute(securityPath, workingDirectory: nil, arguments: ["find-identity","-v","-p","codesigning"])
        if securityResult.output.count < 1 {
            return output
        }
        let rawResult = securityResult.output.components(separatedBy: "\"")
        
        var index: Int
        
        for index in stride(from: 0, through: rawResult.count - 2, by: 2) {
            if !(rawResult.count - 1 < index + 1) {
                output.append(rawResult[index+1])
            }
        }
        return output.sorted()
    }
This post is licensed under CC BY 4.0 by the author.